ManaPlus
viewport.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2018 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
24 
25 #include "actormanager.h"
26 #include "configuration.h"
27 #include "game.h"
28 #include "settings.h"
29 #include "sdlshared.h"
30 #include "textmanager.h"
31 
32 #include "being/flooritem.h"
33 #include "being/localplayer.h"
34 #include "being/playerinfo.h"
35 
38 
39 #include "gui/gui.h"
40 #include "gui/popupmanager.h"
41 #include "gui/userpalette.h"
42 
43 #include "gui/fonts/font.h"
44 
45 #include "gui/popups/beingpopup.h"
46 #include "gui/popups/popupmenu.h"
47 #include "gui/popups/textpopup.h"
48 
50 
51 #include "input/inputmanager.h"
52 
53 #include "utils/checkutils.h"
54 #include "utils/foreach.h"
55 
56 #include "resources/map/map.h"
57 #include "resources/map/mapitem.h"
59 
60 #include "debug.h"
61 
62 Viewport *viewport = nullptr;
63 
64 extern volatile int tick_time;
65 
68  MouseListener(),
70  mMouseX(0),
71  mMouseY(0),
72  mMap(nullptr),
73  mHoverBeing(nullptr),
74  mHoverItem(nullptr),
75  mHoverSign(nullptr),
76  mScrollRadius(config.getIntValue("ScrollRadius")),
77  mScrollLaziness(config.getIntValue("ScrollLaziness")),
78  mScrollCenterOffsetX(config.getIntValue("ScrollCenterOffsetX")),
79  mScrollCenterOffsetY(config.getIntValue("ScrollCenterOffsetY")),
80  mMousePressX(0),
81  mMousePressY(0),
82  mPixelViewX(0),
83  mPixelViewY(0),
84  mMidTileX(0),
85  mMidTileY(0),
86  mViewXmax(0),
87  mViewYmax(0),
88  mLocalWalkTime(-1),
89  mCameraRelativeX(0),
90  mCameraRelativeY(0),
91  mShowBeingPopup(config.getBoolValue("showBeingPopup")),
92  mSelfMouseHeal(config.getBoolValue("selfMouseHeal")),
93  mEnableLazyScrolling(config.getBoolValue("enableLazyScrolling")),
94  mMouseDirectionMove(config.getBoolValue("mouseDirectionMove")),
95  mLongMouseClick(config.getBoolValue("longmouseclick")),
96  mAllowMoveByMouse(config.getBoolValue("allowMoveByMouse")),
97  mMouseClicked(false),
98  mPlayerFollowMouse(false)
99 {
100  setOpaque(Opaque_false);
101  addMouseListener(this);
102 
103  config.addListener("ScrollLaziness", this);
104  config.addListener("ScrollRadius", this);
105  config.addListener("showBeingPopup", this);
106  config.addListener("selfMouseHeal", this);
107  config.addListener("enableLazyScrolling", this);
108  config.addListener("mouseDirectionMove", this);
109  config.addListener("longmouseclick", this);
110  config.addListener("allowMoveByMouse", this);
111 
112  setFocusable(true);
113  updateMidVars();
114 }
115 
117 {
118  config.removeListeners(this);
120 }
121 
122 void Viewport::setMap(Map *const map)
123 {
124  if ((mMap != nullptr) && (map != nullptr))
126  mMap = map;
127  updateMaxVars();
128 }
129 
130 void Viewport::draw(Graphics *const graphics)
131 {
132  BLOCK_START("Viewport::draw 1")
133  static int lastTick = tick_time;
134 
135  if ((mMap == nullptr) || (localPlayer == nullptr))
136  {
137  graphics->setColor(Color(64, 64, 64, 255));
138  graphics->fillRectangle(
139  Rect(0, 0, getWidth(), getHeight()));
140  BLOCK_END("Viewport::draw 1")
141  return;
142  }
143 
144  // Avoid freaking out when tick_time overflows
145  if (tick_time < lastTick)
146  lastTick = tick_time;
147 
148  // Calculate viewpoint
149 
150  const int player_x = localPlayer->mPixelX - mMidTileX;
151  const int player_y = localPlayer->mPixelY - mMidTileY;
152 
153  if (mScrollLaziness < 1)
154  mScrollLaziness = 1; // Avoids division by zero
155 
157  {
158  int cnt = 0;
159 
160  // Apply lazy scrolling
161  while (lastTick < tick_time && cnt < mapTileSize)
162  {
163  if (player_x > mPixelViewX + mScrollRadius)
164  {
166  static_cast<float>(player_x
168  static_cast<float>(mScrollLaziness));
169  }
170  if (player_x < mPixelViewX - mScrollRadius)
171  {
173  static_cast<float>(player_x
175  static_cast<float>(mScrollLaziness));
176  }
177  if (player_y > mPixelViewY + mScrollRadius)
178  {
180  static_cast<float>(player_y
182  static_cast<float>(mScrollLaziness));
183  }
184  if (player_y < mPixelViewY - mScrollRadius)
185  {
187  static_cast<float>(player_y
189  static_cast<float>(mScrollLaziness));
190  }
191  lastTick ++;
192  cnt ++;
193  }
194 
195  // Auto center when player is off screen
196  if (cnt > 30 || player_x - mPixelViewX
197  > graphics->mWidth / 2 || mPixelViewX
198  - player_x > graphics->mWidth / 2 || mPixelViewY
199  - player_y > graphics->getHeight() / 2 || player_y
200  - mPixelViewY > graphics->getHeight() / 2)
201  {
202  if (player_x <= 0 || player_y <= 0)
203  {
204  logger->log("incorrect player position: %d, %d, %d, %d",
205  player_x, player_y, mPixelViewX, mPixelViewY);
206  logger->log("tile position: %d, %d",
208  }
209  mPixelViewX = player_x;
210  mPixelViewY = player_y;
211  }
212  }
213  else
214  {
215  mPixelViewX = player_x;
216  mPixelViewY = player_y;
217  }
218 
219  if (mPixelViewX < 0)
220  mPixelViewX = 0;
221  if (mPixelViewY < 0)
222  mPixelViewY = 0;
223  if (mPixelViewX > mViewXmax)
225  if (mPixelViewY > mViewYmax)
227 
228  // Draw tiles and sprites
229  mMap->draw(graphics, mPixelViewX, mPixelViewY);
230 
231  const MapTypeT drawType = settings.mapDrawType;
232  if (drawType != MapType::NORMAL)
233  {
234  if (drawType != MapType::SPECIAL4)
235  {
236  mMap->drawCollision(graphics, mPixelViewX,
237  mPixelViewY, drawType);
238  }
239  if (drawType == MapType::DEBUGTYPE)
240  drawDebugPath(graphics);
241  }
242 
244  {
247  }
248 
249  // Draw text
250  if (textManager != nullptr)
252 
253  // Draw player names, speech, and emotion sprite as needed
254  const ActorSprites &actors = actorManager->getAll();
255  FOR_EACH (ActorSpritesIterator, it, actors)
256  {
257  if ((*it)->getType() == ActorType::FloorItem)
258  continue;
259  Being *const b = static_cast<Being*>(*it);
260  b->drawEmotion(graphics, mPixelViewX, mPixelViewY);
262  }
263 
264  if (miniStatusWindow != nullptr)
265  miniStatusWindow->drawIcons(graphics);
266 
267  // Draw contained widgets
268  WindowContainer::draw(graphics);
269  BLOCK_END("Viewport::draw 1")
270 }
271 
272 void Viewport::safeDraw(Graphics *const graphics)
273 {
274  Viewport::draw(graphics);
275 }
276 
277 void Viewport::logic()
278 {
279  BLOCK_START("Viewport::logic")
280  // Make the player follow the mouse position
281  // if the mouse is dragged elsewhere than in a window.
283  BLOCK_END("Viewport::logic")
284 }
285 
287 {
288  if (gui == nullptr)
289  return;
291  // If the left button is dragged
292  if (mPlayerFollowMouse && ((button & SDL_BUTTON(1)) != 0))
293  {
294  // We create a mouse event and send it to mouseDragged.
295  const MouseEvent event(nullptr,
298  mMouseX,
299  mMouseY,
300  0);
301 
302  walkByMouse(event);
303  }
304 }
305 
306 void Viewport::drawDebugPath(Graphics *const graphics)
307 {
308  if (localPlayer == nullptr ||
309  userPalette == nullptr ||
310  actorManager == nullptr ||
311  mMap == nullptr ||
312  gui == nullptr)
313  {
314  return;
315  }
316 
318 
319  static Path debugPath;
320  static Vector lastMouseDestination = Vector(0.0F, 0.0F, 0.0F);
321  const int mousePosX = mMouseX + mPixelViewX;
322  const int mousePosY = mMouseY + mPixelViewY;
323  Vector mouseDestination(mousePosX, mousePosY, 0.0F);
324 
325  if (mouseDestination.x != lastMouseDestination.x
326  || mouseDestination.y != lastMouseDestination.y)
327  {
328  debugPath = mMap->findPath(
331  mousePosX / mapTileSize,
332  mousePosY / mapTileSize,
334  500);
335  lastMouseDestination = mouseDestination;
336  }
337  drawPath(graphics, debugPath, userPalette->getColorWithAlpha(
339 
340  const ActorSprites &actors = actorManager->getAll();
341  FOR_EACH (ActorSpritesConstIterator, it, actors)
342  {
343  const Being *const being = dynamic_cast<const Being*>(*it);
344  if ((being != nullptr) && being != localPlayer)
345  {
346  const Path &beingPath = being->getPath();
347  drawPath(graphics, beingPath, userPalette->getColorWithAlpha(
349  }
350  }
351 }
352 
353 void Viewport::drawPath(Graphics *const graphics,
354  const Path &path,
355  const Color &color) const
356 {
357  graphics->setColor(color);
358  Font *const font = getFont();
359 
360  int cnt = 1;
361  FOR_EACH (Path::const_iterator, i, path)
362  {
363  const int squareX = i->x * mapTileSize - mPixelViewX + 12;
364  const int squareY = i->y * mapTileSize - mPixelViewY + 12;
365 
366  graphics->fillRectangle(Rect(squareX, squareY, 8, 8));
367  if (mMap != nullptr)
368  {
369  const std::string str = toString(cnt);
370  font->drawString(graphics,
371  color, color,
372  str,
373  squareX + 4 - font->getWidth(str) / 2,
374  squareY + 12);
375  }
376  cnt ++;
377  }
378 }
379 
380 bool Viewport::openContextMenu(const MouseEvent &event)
381 {
382  mPlayerFollowMouse = false;
383  const int eventX = event.getX();
384  const int eventY = event.getY();
385  if (popupMenu == nullptr)
386  return false;
387  if (mHoverBeing != nullptr)
388  {
389  validateSpeed();
390  if (actorManager != nullptr)
391  {
392  STD_VECTOR<ActorSprite*> beings;
393  const int x = mMouseX + mPixelViewX;
394  const int y = mMouseY + mPixelViewY;
396  if (beings.size() > 1)
397  popupMenu->showPopup(eventX, eventY, beings);
398  else
399  popupMenu->showPopup(eventX, eventY, mHoverBeing);
400  return true;
401  }
402  }
403  else if (mHoverItem != nullptr)
404  {
405  validateSpeed();
406  popupMenu->showPopup(eventX, eventY, mHoverItem);
407  return true;
408  }
409  else if (mHoverSign != nullptr)
410  {
411  validateSpeed();
412  popupMenu->showPopup(eventX, eventY, mHoverSign);
413  return true;
414  }
415  else if (settings.cameraMode != 0U)
416  {
417  if (mMap == nullptr)
418  return false;
419  popupMenu->showMapPopup(eventX, eventY,
422  false);
423  return true;
424  }
425  return false;
426 }
427 
429 {
432  // Interact with some being
433  if (mHoverBeing != nullptr)
434  {
435  if (!mHoverBeing->isAlive())
436  return true;
437 
438  if (mHoverBeing->canTalk())
439  {
440  validateSpeed();
441  mHoverBeing->talkTo();
442  return true;
443  }
444 
445  const ActorTypeT type = mHoverBeing->getType();
446  switch (type)
447  {
448  case ActorType::Player:
449  validateSpeed();
450  if (actorManager != nullptr)
451  {
452 #ifdef TMWA_SUPPORT
455 #endif // TMWA_SUPPORT
456 
457  if (localPlayer == mHoverBeing &&
458  mHoverItem != nullptr)
459  {
461  }
462  return true;
463  }
464  break;
465  case ActorType::Monster:
466  case ActorType::Npc:
468  if (!stopAttack)
469  {
471  false, 0) ||
473  {
474  validateSpeed();
476  {
480  false);
481  return true;
482  }
483  }
484  else if (!inputManager.isActionActive(
486  {
487  validateSpeed();
489  {
491  return true;
492  }
493  }
494  }
495  break;
497  case ActorType::Portal:
498  case ActorType::Pet:
502  break;
503  case ActorType::Unknown:
504  case ActorType::Avatar:
505  default:
506  reportAlways("Left click on unknown actor type: %d",
507  CAST_S32(type));
508  break;
509  }
510  }
511  // Picks up a item if we clicked on one
512  if (mHoverItem != nullptr)
513  {
514  validateSpeed();
516  }
517  else if (stopAttack)
518  {
519  if (mMap != nullptr)
520  {
521  const int mouseTileX = (mMouseX + mPixelViewX)
522  / mMap->getTileWidth();
523  const int mouseTileY = (mMouseY + mPixelViewY)
524  / mMap->getTileHeight();
526  strprintf("%d %d", mouseTileX, mouseTileY),
527  nullptr);
528  }
529  return true;
530  }
531  // Just walk around
533  localPlayer->canMove())
534  {
535  validateSpeed();
536  localPlayer->stopAttack(false);
539  if (mPlayerFollowMouse)
540  {
541  // Make the player go to the mouse position
542  followMouse();
543  }
544  }
545  return false;
546 }
547 
549 {
550  if (event.getSource() != this || event.isConsumed())
551  return;
552 
553  // Check if we are alive and kickin'
554  if ((mMap == nullptr) || (localPlayer == nullptr))
555  return;
556 
557  // Check if we are busy
558  // if commented, allow context menu if npc dialog open
559  if (PlayerInfo::isTalking())
560  {
561  mMouseClicked = false;
562  return;
563  }
564 
565  mMouseClicked = true;
566 
567  mMousePressX = event.getX();
568  mMousePressY = event.getY();
569  const MouseButtonT eventButton = event.getButton();
570  const int pixelX = mMousePressX + mPixelViewX;
571  const int pixelY = mMousePressY + mPixelViewY;
572 
573  // Right click might open a popup
574  if (eventButton == MouseButton::RIGHT)
575  {
576  if (openContextMenu(event))
577  return;
578  }
579 
580  // If a popup is active, just remove it
582  {
583  mPlayerFollowMouse = false;
585  return;
586  }
587 
588  // Left click can cause different actions
589  if (!mLongMouseClick && eventButton == MouseButton::LEFT)
590  {
591  if (leftMouseAction())
592  {
593  mPlayerFollowMouse = false;
594  return;
595  }
596  }
597  else if (eventButton == MouseButton::MIDDLE)
598  {
599  mPlayerFollowMouse = false;
600  validateSpeed();
601  // Find the being nearest to the clicked position
602  if (actorManager != nullptr)
603  {
604  Being *const target = actorManager->findNearestLivingBeing(
605  pixelX, pixelY, 20, ActorType::Monster, nullptr);
606 
607  if (target != nullptr)
608  localPlayer->setTarget(target);
609  }
610  }
611 }
612 
613 void Viewport::getMouseTile(int &destX, int &destY) const
614 {
615  getMouseTile(mMouseX, mMouseY, destX, destY);
616 }
617 
618 void Viewport::getMouseTile(const int x, const int y,
619  int &destX, int &destY) const
620 {
621  if (mMap == nullptr)
622  return;
623  const int tw = mMap->getTileWidth();
624  const int th = mMap->getTileHeight();
625  destX = CAST_S32(x + mPixelViewX)
626  / static_cast<float>(tw);
627 
628  if (mMap->isHeightsPresent())
629  {
630  const int th2 = th / 2;
631  const int clickY = y + mPixelViewY - th2;
632  destY = y + mPixelViewY;
633  int newDiffY = 1000000;
634  const int heightTiles = mainGraphics->mHeight / th;
635  const int tileViewY = mPixelViewY / th;
636  for (int f = tileViewY; f < tileViewY + heightTiles; f ++)
637  {
638  if (!mMap->getWalk(destX,
639  f,
644  {
645  continue;
646  }
647 
648  const int offset = mMap->getHeightOffset(
649  destX, f) * th2;
650  const int pixelF = f * th;
651  const int diff = abs(clickY + offset - pixelF);
652  if (diff < newDiffY)
653  {
654  destY = pixelF;
655  newDiffY = diff;
656  }
657  }
658  destY /= 32;
659  }
660  else
661  {
662  destY = CAST_S32((y + mPixelViewY) / static_cast<float>(th));
663  }
664 }
665 
666 void Viewport::walkByMouse(const MouseEvent &event)
667 {
668  if ((mMap == nullptr) || (localPlayer == nullptr))
669  return;
673  {
674  if (!mMouseDirectionMove)
675  mPlayerFollowMouse = false;
677  {
680  int playerX = localPlayer->getTileX();
681  int playerY = localPlayer->getTileY();
683  {
684  const int width = mainGraphics->mWidth / 2;
685  const int height = mainGraphics->mHeight / 2;
686  const float wh = static_cast<float>(width)
687  / static_cast<float>(height);
688  int x = event.getX() - width;
689  int y = event.getY() - height;
690  if ((x == 0) && (y == 0))
691  return;
692  const int x2 = abs(x);
693  const int y2 = abs(y);
694  const float diff = 2;
695  int dx = 0;
696  int dy = 0;
697  if (x2 > y2)
698  {
699  if (y2 != 0 &&
700  static_cast<float>(x2) / static_cast<float>(y2) /
701  wh > diff)
702  {
703  y = 0;
704  }
705  }
706  else
707  {
708  if ((x2 != 0) && y2 * wh / x2 > diff)
709  x = 0;
710  }
711  if (x > 0)
712  dx = 1;
713  else if (x < 0)
714  dx = -1;
715  if (y > 0)
716  dy = 1;
717  else if (y < 0)
718  dy = -1;
719 
720  if (mMap->getWalk(playerX + dx,
721  playerY + dy,
726  {
727  localPlayer->navigateTo(playerX + dx, playerY + dy);
728  }
729  else
730  {
731  if ((dx != 0) && (dy != 0))
732  {
733  // try avoid diagonal collision
734  if (x2 > y2)
735  {
736  if (mMap->getWalk(playerX + dx,
737  playerY,
742  {
743  dy = 0;
744  }
745  else
746  {
747  dx = 0;
748  }
749  }
750  else
751  {
752  if (mMap->getWalk(playerX,
753  playerY + dy,
758  {
759  dx = 0;
760  }
761  else
762  {
763  dy = 0;
764  }
765  }
766  }
767  else
768  {
769  // try avoid vertical or horisontal collision
770  if (dx == 0)
771  {
772  if (mMap->getWalk(playerX + 1,
773  playerY + dy,
778  {
779  dx = 1;
780  }
781  if (mMap->getWalk(playerX - 1,
782  playerY + dy,
787  {
788  dx = -1;
789  }
790  }
791  if (dy == 0)
792  {
793  if (mMap->getWalk(playerX + dx,
794  playerY + 1,
799  {
800  dy = 1;
801  }
802  if (mMap->getWalk(playerX + dx,
803  playerY - 1,
808  {
809  dy = -1;
810  }
811  }
812  }
813  localPlayer->navigateTo(playerX + dx, playerY + dy);
814  }
815  }
816  else
817  {
818  int destX;
819  int destY;
820  getMouseTile(event.getX(), event.getY(),
821  destX, destY);
822  if (playerX != destX || playerY != destY)
823  {
824  if (!localPlayer->navigateTo(destX, destY))
825  {
826  if (playerX > destX)
827  playerX --;
828  else if (playerX < destX)
829  playerX ++;
830  if (playerY > destY)
831  playerY --;
832  else if (playerY < destY)
833  playerY ++;
834  if (mMap->getWalk(playerX, playerY, 0))
835  localPlayer->navigateTo(playerX, playerY);
836  }
837  }
838  }
839  }
840  }
841 }
842 
844 {
845  if (event.getSource() != this || event.isConsumed())
846  {
847  mPlayerFollowMouse = false;
848  return;
849  }
850  if (mAllowMoveByMouse &&
851  mMouseClicked &&
852  (localPlayer != nullptr) &&
853  localPlayer->canMove())
854  {
855  if (abs(event.getX() - mMousePressX) > 32
856  || abs(event.getY() - mMousePressY) > 32)
857  {
858  mPlayerFollowMouse = true;
859  }
860 
861  walkByMouse(event);
862  }
863 }
864 
866 {
867  mPlayerFollowMouse = false;
868  mLocalWalkTime = -1;
870  {
871  mMouseClicked = false;
872  if (event.getSource() != this || event.isConsumed())
873  return;
874  const MouseButtonT eventButton = event.getButton();
875  if (eventButton == MouseButton::LEFT)
876  {
877  // long button press
878  if ((gui != nullptr) && gui->isLongPress())
879  {
880  if (openContextMenu(event))
881  {
882  gui->resetClickCount();
883  return;
884  }
885  }
886  else
887  {
888  if (leftMouseAction())
889  return;
890  }
891  walkByMouse(event);
892  }
893  }
894 }
895 
896 void Viewport::optionChanged(const std::string &name)
897 {
898  if (name == "ScrollLaziness")
899  mScrollLaziness = config.getIntValue("ScrollLaziness");
900  else if (name == "ScrollRadius")
901  mScrollRadius = config.getIntValue("ScrollRadius");
902  else if (name == "showBeingPopup")
903  mShowBeingPopup = config.getBoolValue("showBeingPopup");
904  else if (name == "selfMouseHeal")
905  mSelfMouseHeal = config.getBoolValue("selfMouseHeal");
906  else if (name == "enableLazyScrolling")
907  mEnableLazyScrolling = config.getBoolValue("enableLazyScrolling");
908  else if (name == "mouseDirectionMove")
909  mMouseDirectionMove = config.getBoolValue("mouseDirectionMove");
910  else if (name == "longmouseclick")
911  mLongMouseClick = config.getBoolValue("longmouseclick");
912  else if (name == "allowMoveByMouse")
913  mAllowMoveByMouse = config.getBoolValue("allowMoveByMouse");
914 }
915 
916 void Viewport::mouseMoved(MouseEvent &event)
917 {
918  // Check if we are on the map
919  if (mMap == nullptr ||
920  localPlayer == nullptr ||
921  actorManager == nullptr)
922  {
923  return;
924  }
925 
927  mPlayerFollowMouse = false;
928 
929  const int x = mMouseX + mPixelViewX;
930  const int y = mMouseY + mPixelViewY;
931 
934  if (mHoverBeing != nullptr)
935  type = mHoverBeing->getType();
936  if ((mHoverBeing != nullptr)
937  && (type == ActorType::Player
938  || type == ActorType::Npc
939  || type == ActorType::Homunculus
940  || type == ActorType::Mercenary
941  || type == ActorType::Pet))
942  {
944  if (mShowBeingPopup && (beingPopup != nullptr))
946  }
947  else
948  {
950  }
951 
953  y / mMap->getTileHeight());
954 
955  if ((mHoverBeing == nullptr) && (mHoverItem == nullptr))
956  {
957  const SpecialLayer *const specialLayer = mMap->getSpecialLayer();
958  if (specialLayer != nullptr)
959  {
960  const int mouseTileX = (mMouseX + mPixelViewX)
961  / mMap->getTileWidth();
962  const int mouseTileY = (mMouseY + mPixelViewY)
963  / mMap->getTileHeight();
964 
965  mHoverSign = specialLayer->getTile(mouseTileX, mouseTileY);
966  if (mHoverSign != nullptr &&
968  {
969  if (!mHoverSign->getComment().empty())
970  {
972  if (textPopup != nullptr)
973  {
976  }
977  }
978  else
979  {
982  }
984  return;
985  }
986  }
987  }
988  if (!event.isConsumed() &&
990  {
992  }
993 
994  if (mHoverBeing != nullptr)
995  {
996  switch (type)
997  {
998  case ActorType::Npc:
999  case ActorType::Monster:
1000  case ActorType::Portal:
1001  case ActorType::Pet:
1002  case ActorType::Mercenary:
1003  case ActorType::Homunculus:
1004  case ActorType::SkillUnit:
1005  case ActorType::Elemental:
1007  break;
1008 
1009  case ActorType::Avatar:
1010  case ActorType::FloorItem:
1011  case ActorType::Unknown:
1012  case ActorType::Player:
1013  default:
1015  break;
1016  }
1017  }
1018  // Item mouseover
1019  else if (mHoverItem != nullptr)
1020  {
1022  }
1023  else
1024  {
1026  }
1027 }
1028 
1030 {
1031  settings.mapDrawType = static_cast<MapTypeT>(
1035  if (mMap != nullptr)
1037 }
1038 
1040 {
1041  settings.cameraMode ++;
1042  if (settings.cameraMode > 1)
1043  settings.cameraMode = 0;
1044  if (settings.cameraMode == 0U)
1045  {
1046  mCameraRelativeX = 0;
1047  mCameraRelativeY = 0;
1048  updateMidVars();
1049  }
1051 }
1052 
1053 void Viewport::clearHover(const ActorSprite *const actor)
1054 {
1055  if (mHoverBeing == actor)
1056  mHoverBeing = nullptr;
1057 
1058  if (mHoverItem == actor)
1059  mHoverItem = nullptr;
1060 }
1061 
1063 {
1064  mHoverBeing = nullptr;
1065  mHoverItem = nullptr;
1066  mHoverSign = nullptr;
1067 }
1068 
1069 void Viewport::moveCamera(const int dx, const int dy)
1070 {
1071  mCameraRelativeX += dx;
1072  mCameraRelativeY += dy;
1073  updateMidVars();
1074 }
1075 
1077  const int x, const int y)
1078 {
1079  if ((localPlayer == nullptr) || (actorManager == nullptr))
1080  return;
1081 
1082  const Actor *const actor = actorManager->findBeing(actorId);
1083  if (actor == nullptr)
1084  return;
1085  settings.cameraMode = 1;
1088  updateMidVars();
1089 }
1090 
1091 void Viewport::moveCameraToPosition(const int x, const int y)
1092 {
1093  if (localPlayer == nullptr)
1094  return;
1095 
1096  settings.cameraMode = 1;
1099  updateMidVars();
1100 }
1101 
1102 void Viewport::moveCameraRelative(const int x, const int y)
1103 {
1104  settings.cameraMode = 1;
1105  mCameraRelativeX += x;
1106  mCameraRelativeY += y;
1107  updateMidVars();
1108 }
1109 
1111 {
1112  settings.cameraMode = 0;
1113  mCameraRelativeX = 0;
1114  mCameraRelativeY = 0;
1115  updateMidVars();
1116 }
1117 
1119 {
1122  {
1123  if (Game::instance() != nullptr)
1125  }
1126 }
1127 
1129 {
1131  - mCameraRelativeX;
1133  - mCameraRelativeY;
1134 }
1135 
1137 {
1138  if (mMap == nullptr)
1139  return;
1141  - mainGraphics->mWidth;
1143  - mainGraphics->mHeight;
1144 }
1145 
1147 {
1148  updateMidVars();
1149  updateMaxVars();
1150 }
void showMapPopup(const int x, const int y, const int x2, const int y2, const bool isMinimap)
Definition: popupmenu.cpp:804
int mViewXmax
Definition: viewport.h:229
Font * getFont() const
Definition: widget.cpp:330
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
void show(const int x, const int y, const std::string &str1)
Definition: textpopup.h:56
void moveCameraToPosition(const int x, const int y)
Definition: viewport.cpp:1091
ActorSprites::const_iterator ActorSpritesConstIterator
Definition: actormanager.h:60
int getWidth() const
Definition: widget.h:220
int mPixelViewX
Definition: viewport.h:194
MapType ::T MapTypeT
Definition: maptype.h:38
int getTileY() const
Definition: being.h:173
TextManager * textManager
Definition: textmanager.cpp:32
void toggleMapDrawType()
Definition: viewport.cpp:250
int mLocalWalkTime
Definition: viewport.h:197
void moveCameraRelative(const int x, const int y)
Definition: viewport.cpp:1102
void drawPath(Graphics *const graphics, const Path &path, const Color &color) const
Definition: viewport.cpp:353
FloorItem * findItem(const BeingId id) const
Gui * gui
Definition: gui.cpp:110
#define MouseStateType
Definition: gui.h:99
void walkByMouse(const MouseEvent &event)
Definition: viewport.cpp:174
Definition: font.h:88
void attack(Being *const target, const bool keep, const bool dontChangeEquipment)
bool mMouseDirectionMove
Definition: viewport.h:205
bool isTalking()
Definition: playerinfo.cpp:456
void setValidSpeed()
Definition: game.cpp:1272
void updateMaxVars()
Definition: viewport.cpp:1136
const Color & getColorWithAlpha(const UserColorIdT type)
Definition: userpalette.h:199
void moveCameraToActor(const BeingId actorId, const int x, const int y)
Definition: viewport.cpp:1076
void followMouse()
Definition: viewport.cpp:124
void setDrawLayersFlags(const MapTypeT &n)
Definition: map.cpp:1698
void mouseDragged(MouseEvent &event)
Definition: viewport.cpp:178
~Viewport()
Definition: viewport.cpp:82
int getTileHeight() const
Definition: map.h:183
const std::string & getComment() const
Definition: mapitem.h:67
Being * mHoverBeing
Definition: viewport.h:184
static void hidePopupMenu()
Definition: vector.h:38
void mouseReleased(MouseEvent &event)
Definition: viewport.cpp:197
Definition: rect.h:72
int mCameraRelativeX
Definition: viewport.h:199
int mWidth
Definition: graphics.h:483
#define BLOCK_START(name)
Definition: perfomance.h:78
int mScrollCenterOffsetX
Definition: viewport.h:190
unsigned char getBlockWalkMask() const A_CONST
Configuration config
int BeingId
Definition: beingid.h:29
bool mMouseClicked
Definition: viewport.h:207
void setGotoTarget(Being *const target)
void cancelFollow()
#define BLOCK_END(name)
Definition: perfomance.h:79
bool isLongPress() const
Definition: gui.h:308
ActorType ::T ActorTypeT
Definition: actortype.h:42
int getIntValue(const std::string &key) const
void drawIcons(Graphics *const graphics)
void toggleCameraMode()
Definition: viewport.cpp:254
int mMouseX
Definition: viewport.h:153
volatile int tick_time
Definition: timer.cpp:52
int mCameraRelativeY
Definition: viewport.h:200
void draw(Graphics *const graphics)
MapTypeT mapDrawType
Definition: settings.h:148
void addListener(const std::string &key, ConfigListener *const listener)
UserPalette * userPalette
Definition: userpalette.cpp:33
bool isActionActive(const InputActionT index) const
int getHeight() const
Definition: map.h:171
bool mStatsReUpdated
Definition: game.cpp:160
bool mPlayerFollowMouse
Definition: viewport.h:208
Logger * logger
Definition: logger.cpp:88
int mScrollRadius
Definition: viewport.h:188
void draw(Graphics *const graphics, int scrollX, int scrollY)
Definition: map.cpp:337
Viewport()
Definition: viewport.cpp:39
void show(const int x, const int y, Being *const b)
Definition: beingpopup.cpp:90
Settings settings
Definition: settings.cpp:31
MiniStatusWindow * miniStatusWindow
bool getBoolValue(const std::string &key) const
int mPixelX
Definition: actor.h:132
void returnCamera()
Definition: viewport.cpp:1110
bool mAllowMoveByMouse
Definition: viewport.h:242
virtual void setColor(const Color &color)
Definition: graphics.h:319
bool isHeightsPresent() const
Definition: map.h:361
#define CAST_S32
Definition: cast.h:29
static void hideTextPopup()
int getType() const
Definition: mapitem.h:54
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
FloorItem * mHoverItem
Definition: viewport.h:185
int mViewYmax
Definition: viewport.h:230
void safeDraw(Graphics *const graphics)
Definition: viewport.cpp:110
Being * findBeingByPixel(const int x, const int y, const AllPlayers allPlayers) const
int mMidTileY
Definition: viewport.h:228
void videoResized()
Definition: viewport.cpp:270
Widget * getSource() const
Definition: event.h:103
LocalPlayer * localPlayer
bool mShowBeingPopup
Definition: viewport.h:202
PopupMenu * popupMenu
Definition: popupmenu.cpp:102
SpecialLayer * getSpecialLayer() const
Definition: map.h:240
bool stopAttack(InputEvent &event)
Definition: actions.cpp:55
int getHeight() const
Definition: graphics.cpp:647
void drawString(Graphics *const graphics, Color col, const Color &col2, const std::string &text, const int x, const int y)
Definition: font.cpp:253
MapItem * getTile(const int x, const int y) const
bool isAlive() const
Definition: being.h:487
static void validateSpeed()
Definition: viewport.cpp:1118
const Path & getPath() const
Definition: being.h:548
void resetClickCount()
Definition: gui.cpp:979
Being * findBeing(const BeingId id) const
void moveCamera(const int dx, const int dy)
Definition: viewport.cpp:1069
int mMousePressY
Definition: viewport.h:193
void stopAttack(const bool keepAttack)
int mScrollCenterOffsetY
Definition: viewport.h:191
ActorSprites::iterator ActorSpritesIterator
Definition: actormanager.h:59
#define nullptr
Definition: localconsts.h:44
Graphics * mainGraphics
Definition: graphics.cpp:108
ActorTypeT getType() const
Definition: being.h:115
const bool Opaque_false
Definition: opaque.h:29
void setMap(Map *const map)
Definition: viewport.cpp:88
bool navigateTo(const int x, const int y)
void cleanHoverItems()
Definition: viewport.cpp:258
bool mSelfMouseHeal
Definition: viewport.h:203
bool getCheckNameSetting() const
Definition: localplayer.h:352
int mHeight
Definition: graphics.h:484
void setCursorType(const CursorT index)
Definition: gui.h:195
void drawEmotion(Graphics *const graphics, const int offsetX, const int offsetY) const
Definition: being.cpp:2377
void updateMidVars()
Definition: viewport.cpp:1128
volatile time_t cur_time
Definition: timer.cpp:57
int mPixelY
Definition: actor.h:133
int mScrollLaziness
Definition: viewport.h:189
static uint8_t getMouseState(int &x, int &y)
Definition: gui.cpp:1170
void unSetPickUpTarget()
Definition: localplayer.h:321
uint8_t getHeightOffset(const int x, const int y) const
Definition: map.cpp:1626
bool isConsumed() const
const std::string & getName() const
Definition: being.h:231
bool getWalk(const int x, const int y, const unsigned char blockWalkMask) const
Definition: map.cpp:780
void getMouseTile(int &destX, int &destY) const
Definition: viewport.cpp:613
Definition: map.h:71
bool mLongMouseClick
Definition: viewport.h:206
int mPixelViewY
Definition: viewport.h:195
void setCheckNameSetting(const bool checked)
Definition: localplayer.h:345
unsigned int cameraMode
Definition: settings.h:142
float x
Definition: vector.h:208
int mMouseY
Definition: viewport.h:154
const bool AllPlayers_true
Definition: allplayers.h:29
int getY() const
Definition: mouseevent.h:137
int getWidth() const
Definition: map.h:165
bool canTalk() const
Definition: being.h:666
MapItem * mHoverSign
Definition: viewport.h:186
Map * mMap
Definition: viewport.h:182
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
virtual void fillRectangle(const Rect &rectangle)=0
static void hideBeingPopup()
void mouseMoved(MouseEvent &event)
Definition: viewport.cpp:246
CursorT getHoverCursor() const
Definition: being.h:892
bool canMove() const
BeingPopup * beingPopup
Definition: beingpopup.cpp:46
MapTypeT getDrawLayersFlags() const
Definition: map.h:230
void logic()
Definition: viewport.cpp:115
void removeListeners(ConfigListener *const listener)
std::string mMap
Definition: gamerecv.cpp:45
bool mEnableLazyScrolling
Definition: viewport.h:204
int getWidth(const std::string &text) const
Definition: font.cpp:333
void drawDebugPath(Graphics *const graphics)
Definition: viewport.cpp:128
void setName(const std::string &name)
Definition: being.cpp:1135
Path findPath(const int startX, const int startY, const int destX, const int destY, const unsigned char blockWalkmask, const int maxCost)
Definition: map.cpp:858
int mMidTileX
Definition: viewport.h:227
void findBeingsByPixel(std::vector< ActorSprite *> &beings, const int x, const int y, const AllPlayers allPlayers) const
int getTileWidth() const
Definition: map.h:177
void setTarget(Being *const target)
static bool isPopupMenuVisible()
float y
Definition: vector.h:208
Definition: actor.h:40
int getHeight() const
Definition: widget.h:239
std::list< Position > Path
Definition: position.h:48
const ActorSprites & getAll() const A_CONST
int getActionTime() const
Definition: being.h:127
static const int mapTileSize
Definition: map.h:26
static Game * instance()
Definition: game.h:81
bool openContextMenu(const MouseEvent &event)
Definition: viewport.cpp:132
Definition: color.h:74
void optionChanged(const std::string &name)
Definition: viewport.cpp:228
int getTileX() const
Definition: being.h:167
int getX() const
Definition: mouseevent.h:126
#define CHECKLISTENERS
Definition: localconsts.h:276
void drawCollision(Graphics *const graphics, const int scrollX, const int scrollY, const MapTypeT drawFlags) const
Definition: map.cpp:564
InputManager inputManager
void log(const char *const log_text,...)
Definition: logger.cpp:264
void mousePressed(MouseEvent &event)
Definition: viewport.cpp:137
static bool isTextPopupVisible()
void draw(Graphics *const graphics, const int xOff, const int yOff)
Definition: textmanager.cpp:73
bool executeChatCommand(const std::string &cmd, const std::string &args, ChatTab *const tab)
void heal(const Being *const target) const
bool leftMouseAction()
Definition: viewport.cpp:265
Being * findNearestLivingBeing(const int x, const int y, int maxTileDist, const ActorTypeT type, const Being *const excluded) const
MouseButton ::T MouseButtonT
Definition: mousebutton.h:77
Definition: being.h:93
bool withinAttackRange(const Being *const target, const bool fixDistance, const int addRange) const
#define reportAlways(...)
Definition: checkutils.h:252
void draw(Graphics *const graphics)
Definition: viewport.cpp:92
void showPopup(const int x, const int y, const Being *const being)
Definition: popupmenu.cpp:202
CursorT getHoverCursor() const
Definition: flooritem.h:116
int mMousePressX
Definition: viewport.h:192
void talkTo() const
Definition: being.cpp:3675
void drawSpeech(const int offsetX, const int offsetY)
Definition: being.cpp:2407
ActorManager * actorManager
TextPopup * textPopup
Definition: textpopup.cpp:32
Viewport * viewport
Definition: viewport.cpp:35
bool pickUp(FloorItem *const item)
void clearHover(const ActorSprite *const actor)
Clears any matching hovers.
Definition: viewport.cpp:1053
std::set< ActorSprite * > ActorSprites
Definition: actormanager.h:56