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