ManaPlus
game.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 
24 #include "game.h"
25 
26 #include "actormanager.h"
27 #include "client.h"
28 #include "configuration.h"
29 #include "effectmanager.h"
30 #include "eventsmanager.h"
31 #include "gamemodifiers.h"
32 #include "soundmanager.h"
33 #include "settings.h"
34 
35 #include "being/crazymoves.h"
36 #include "being/localplayer.h"
37 #include "being/playerinfo.h"
38 
39 #include "const/itemshortcut.h"
40 #include "const/spells.h"
41 
42 #include "const/gui/chat.h"
43 
45 
46 #include "fs/mkdir.h"
47 
48 #include "fs/virtfs/fs.h"
49 
50 #include "gui/dialogsmanager.h"
51 #include "gui/gui.h"
52 #include "gui/popupmanager.h"
53 #include "gui/viewport.h"
54 #include "gui/windowmanager.h"
55 #include "gui/windowmenu.h"
56 
57 #include "gui/fonts/font.h"
58 
61 
62 #include "gui/popups/popupmenu.h"
63 
64 #include "gui/windows/bankwindow.h"
65 #include "gui/windows/clanwindow.h"
67 #include "gui/windows/mailwindow.h"
68 #include "gui/windows/chatwindow.h"
74 #include "gui/windows/killstats.h"
75 #include "gui/windows/minimap.h"
77 #include "gui/windows/npcdialog.h"
80 #include "gui/windows/shopwindow.h"
88 
90 
96 
100 
101 #include "input/inputmanager.h"
102 #include "input/joystick.h"
103 #include "input/keyboardconfig.h"
104 
106 
107 #include "net/generalhandler.h"
108 #include "net/gamehandler.h"
109 #include "net/net.h"
110 #include "net/packetcounters.h"
111 
112 #include "particle/particleengine.h"
113 
115 #include "resources/mapreader.h"
117 
118 #include "resources/db/mapdb.h"
119 
120 #include "resources/map/map.h"
121 
123 
125 
126 #include "utils/delete2.h"
127 #include "utils/foreach.h"
128 #include "utils/gettext.h"
129 #include "utils/perfstat.h"
130 #include "utils/pnglib.h"
131 #include "utils/sdlcheckutils.h"
132 #include "utils/timer.h"
133 
134 #ifdef __native_client__
135 #include "utils/naclmessages.h"
136 #endif // __native_client__
137 
139 #include "listeners/errorlistener.h"
140 
141 #ifdef TMWA_SUPPORT
142 #include "net/tmwa/guildmanager.h"
143 #endif // TMWA_SUPPORT
144 
145 #ifdef USE_MUMBLE
146 #include "mumblemanager.h"
147 #endif // USE_MUMBLE
148 
149 #ifdef WIN32
150 #include <sys/time.h>
151 #undef ERROR
152 #endif // WIN32
153 
154 #include <fstream>
155 
156 #include "debug.h"
157 
160 
161 bool mStatsReUpdated = false;
162 const time_t adjustDelay = 10;
163 
167 static void initEngines()
168 {
171 #ifdef TMWA_SUPPORT
173 #endif // TMWA_SUPPORT
174 
175  crazyMoves = new CrazyMoves;
176 
178  particleEngine->setMap(nullptr);
180  BeingInfo::init();
181 
182  if (gameHandler != nullptr)
184 
185  keyboard.update();
186  if (joystick != nullptr)
187  joystick->update();
188 
190 }
191 
195 static void createGuiWindows()
196 {
197  if (setupWindow != nullptr)
199 
200  if (emoteShortcut != nullptr)
201  emoteShortcut->load();
202 
204 
205  // Create dialogs
208  if (chatWindow != nullptr)
209  {
211  chatWindow = nullptr;
212  }
214  "Chat");
218  localPlayer,
219  false);
221  nullptr,
222  nullptr,
223  true);
230  {
233  }
238  if (debugWindow != nullptr)
239  {
241  debugWindow = nullptr;
242  }
244  "Debug");
246  "ItemShortcut", "items.xml", 83, 460);
247 
248  for (unsigned f = 0; f < SHORTCUT_TABS - 1; f ++)
249  {
251  new ItemShortcutContainer(nullptr, f));
252  }
254  {
256  new ItemShortcutContainer(nullptr, SHORTCUT_TABS - 1));
257  }
258  if (config.getBoolValue("showDidYouKnow"))
259  {
262  }
263 
265  "EmoteShortcut",
266  new EmoteShortcutContainer(nullptr),
267  "emotes.xml",
268  130, 480);
271  "DropShortcut",
272  new VirtShortcutContainer(nullptr, dropShortcut),
273  "drops.xml",
274  0, 0);
276  "SpellShortcut",
277  "spells.xml",
278  265, 328);
279  for (unsigned f = 0; f < SPELL_SHORTCUT_TABS; f ++)
280  {
282  new SpellShortcutContainer(nullptr, f));
283  }
284 
292 
293  // TRANSLATORS: chat tab header
294  localChatTab = new ChatTab(chatWindow, _("General"),
295  GENERAL_CHANNEL, "#General", ChatTabType::INPUT);
297  if (config.getBoolValue("showChatHistory"))
298  localChatTab->loadFromLogFile("#General");
299 
300  // TRANSLATORS: chat tab header
301  debugChatTab = new ChatTab(chatWindow, _("Debug"), "",
302  "#Debug", ChatTabType::DEBUG);
304 
305  if (assertListener != nullptr)
306  {
307  const StringVect &messages = assertListener->getMessages();
308  FOR_EACH (StringVectCIter, it, messages)
309  {
310  debugChatTab->chatLog(*it,
314  }
316  }
317  if (config.getBoolValue("enableTradeTab"))
319  else
320  tradeChatTab = nullptr;
321 
322  if (config.getBoolValue("enableBattleTab"))
323  {
326  }
327  else
328  {
329  battleChatTab = nullptr;
330  }
331 
333  if (!isSafeMode)
335 
336  if (setupWindow != nullptr)
338 
339  if (localPlayer != nullptr)
341 
342  if (generalHandler != nullptr)
344 }
345 
349 static void destroyGuiWindows()
350 {
351  if (generalHandler != nullptr)
353 
354  if (whoIsOnline != nullptr)
355  whoIsOnline->setAllowUpdate(false);
356 
357 #ifdef TMWA_SUPPORT
359 #endif // TMWA_SUPPORT
360 
362  delete2(localChatTab) // Need to do this first, so it can remove itself
368 #ifdef TMWA_SUPPORT
369  if (guildManager != nullptr && GuildManager::getEnableGuildBot())
370  guildManager->reload();
371 #endif // TMWA_SUPPORT
372 
373  logger->log("start deleting");
376  logger->log("end deleting");
401 }
402 
403 Game *Game::mInstance = nullptr;
404 
406  mCurrentMap(nullptr),
407  mMapName(""),
408  mValidSpeed(true),
409  mNextAdjustTime(cur_time + adjustDelay),
410  mAdjustLevel(0),
411  mAdjustPerfomance(config.getBoolValue("adjustPerfomance")),
412  mLowerCounter(0),
413  mPing(0),
414  mTime(cur_time + 1),
415  mTime2(cur_time + 10)
416 {
417  touchManager.setInGame(true);
418 
419 // assert(!mInstance);
420  if (mInstance != nullptr)
421  logger->log("error: double game creation");
422  mInstance = this;
423 
424  config.incValue("gamecount");
425 
426  disconnectedDialog = nullptr;
427 
428  // Create the viewport
429  viewport = new Viewport;
432 
434 
435  BasicContainer2 *const top = static_cast<BasicContainer2*>(gui->getTop());
436  if (top != nullptr)
437  top->add(viewport);
439 
442  config.getBoolValue("enableDelayedAnimations"));
443 
445  config.getBoolValue("enableCompoundSpriteDelay"));
446 
448  windowMenu = new WindowMenu(nullptr);
449 
450  if (windowContainer != nullptr)
452 
453 #ifdef USE_OPENGL
455 #endif // USE_OPENGL
456 
457  initEngines();
458 
461 
462  // Initialize beings
463  if (actorManager != nullptr)
465 
467 
468  if (setupWindow != nullptr)
469  setupWindow->setInGame(true);
470  clearKeysArray();
471 
472 #ifdef TMWA_SUPPORT
473  if (guildManager != nullptr && GuildManager::getEnableGuildBot())
475 #endif // TMWA_SUPPORT
476 
478  "disableLoggingInGame");
479 }
480 
482 {
483 #ifdef USE_OPENGL
485 #endif // USE_OPENGL
486 
488  touchManager.setInGame(false);
489  config.write();
493 
495 
499  if (effectManager != nullptr)
500  effectManager->clear();
505 #ifdef TMWA_SUPPORT
507 #endif // TMWA_SUPPORT
508 #ifdef USE_MUMBLE
509  delete2(mumbleManager)
510 #endif // USE_MUMBLE
511 
514 
516  mInstance = nullptr;
518 }
519 
521 {
522  if ((boldFont == nullptr) || !config.getBoolValue("addwatermark"))
523  return;
524 
525  const Color &color1 = theme->getColor(ThemeColorId::TEXT, 255);
526  const Color &color2 = theme->getColor(ThemeColorId::TEXT_OUTLINE, 255);
527 
529  color1,
530  color2,
532  100, 50);
533 }
534 
535 bool Game::createScreenshot(const std::string &prefix)
536 {
537  if ((mainGraphics == nullptr) || (screenshortHelper == nullptr))
538  return false;
539 
540  SDL_Surface *screenshot = nullptr;
541 
542  if (!config.getBoolValue("showip") && (gui != nullptr))
543  {
544  mainGraphics->setSecure(true);
546  gui->draw();
547  addWatermark();
549  mainGraphics->setSecure(false);
550  }
551  else
552  {
553  addWatermark();
555  }
556 
557  if (screenshot == nullptr)
558  return false;
559 
560  return saveScreenshot(screenshot, prefix);
561 }
562 
563 bool Game::saveScreenshot(SDL_Surface *const screenshot,
564  const std::string &prefix)
565 {
566  std::string screenshotDirectory = settings.screenshotDir;
567  if (mkdir_r(screenshotDirectory.c_str()) != 0)
568  {
569  logger->log("Directory %s doesn't exist and can't be created! "
570  "Setting screenshot directory to home.",
571  screenshotDirectory.c_str());
572  screenshotDirectory = std::string(VirtFs::getUserDir());
573  }
574 
575  // Search for an unused screenshot name
576  std::stringstream filename;
577  std::fstream testExists;
578 
579  time_t rawtime;
580  char buffer [100];
581  time(&rawtime);
582  tm *const timeinfo = localtime(&rawtime);
583  strftime(buffer, 99, "%Y-%m-%d_%H-%M-%S", timeinfo);
584 
585  const std::string serverName = settings.serverName;
586  std::string screenShortStr;
587  if (prefix.empty())
588  {
589  if (serverName.empty())
590  {
591  screenShortStr = strprintf("%s_Screenshot_%s_",
592  branding.getValue("appName", "ManaPlus").c_str(),
593  buffer);
594  }
595  else
596  {
597  screenShortStr = strprintf("%s_Screenshot_%s_%s_",
598  branding.getValue("appName", "ManaPlus").c_str(),
599  serverName.c_str(), buffer);
600  }
601 
602  bool found = false;
603  static unsigned int screenshotCount = 0;
604  do
605  {
606  screenshotCount++;
607  filename.str("");
608  filename << screenshotDirectory << "/";
609  filename << screenShortStr << screenshotCount << ".png";
610  testExists.open(filename.str().c_str(), std::ios::in);
611  found = !testExists.is_open();
612  testExists.close();
613  }
614  while (!found);
615  }
616  else
617  {
618  screenShortStr = prefix;
619  filename.str("");
620  filename << screenshotDirectory << "/";
621  filename << screenShortStr;
622  }
623 
624  const std::string fileNameStr = filename.str();
625  const bool success = PngLib::writePNG(screenshot, fileNameStr);
626 #ifdef __native_client__
627  std::string nacScreenshotlDir = fileNameStr;
628  cutFirst(nacScreenshotlDir, "/persistent");
629  naclPostMessage("copy-from-persistent", nacScreenshotlDir);
630  logger->log("nacl screenshot path: " + nacScreenshotlDir);
631 #endif // __native_client__
632 
633  if (success)
634  {
635  if (localChatTab != nullptr)
636  {
637  // TRANSLATORS: save file message
638  std::string str = strprintf(_("Screenshot saved as %s"),
639  fileNameStr.c_str());
640  localChatTab->chatLog(str,
644  }
645  }
646  else
647  {
648  if (localChatTab != nullptr)
649  {
650  // TRANSLATORS: save file message
651  localChatTab->chatLog(_("Saving screenshot failed!"),
655  }
656  logger->log1("Error: could not save screenshot.");
657  }
658 
660  return success;
661 }
662 
664 {
665  BLOCK_START("Game::logic")
666  handleInput();
667 
668  // Handle all necessary game logic
669  if (actorManager != nullptr)
670  actorManager->logic();
671  if (particleEngine != nullptr)
673  if (mCurrentMap != nullptr)
674  mCurrentMap->update(1);
675 
676  BLOCK_END("Game::logic")
677 }
678 
680 {
681  BLOCK_START("Game::slowLogic")
682  if (localPlayer != nullptr)
684  const time_t time = cur_time;
685  if (mTime != time)
686  {
687  if (valTest(Updated))
688  mValidSpeed = false;
689 
690  mTime = time + 1;
691  if (debugWindow != nullptr)
693  if (killStats != nullptr)
694  killStats->update();
695  if (socialWindow != nullptr)
697  if (whoIsOnline != nullptr)
700  if (killStats != nullptr)
702 
703  if (time > mTime2 || mTime2 - time > 10)
704  {
705  mTime2 = time + 10;
708  }
709  if (effectManager != nullptr)
710  effectManager->logic();
711  }
712 
715 
716 #ifdef TMWA_SUPPORT
717  if (shopWindow != nullptr)
719  if (guildManager != nullptr)
721 #endif // TMWA_SUPPORT
722 
723  if (skillDialog != nullptr)
725 
727 
728  // Handle network stuff
729  if (!gameHandler->isConnected())
730  {
732  return; // Not a problem here
733 
734  if (client->getState() != State::ERROR)
735  {
736  if (disconnectedDialog == nullptr)
737  {
738  // TRANSLATORS: error message text
739  errorMessage = _("The connection to the server was lost.");
741  // TRANSLATORS: error message header
742  _("Network Error"),
743  errorMessage,
744  Modal_false);
747  }
748  }
749 
750  if ((viewport != nullptr) && !errorMessage.empty())
751  {
752  const Map *const map = viewport->getMap();
753  if (map != nullptr)
754  map->saveExtraLayer();
755  }
759  if (client->getState() != State::ERROR)
760  errorMessage.clear();
761  }
762  else
763  {
764  if (gameHandler->mustPing()
765  && get_elapsed_time1(mPing) > 3000)
766  {
767  mPing = tick_time;
769  }
770 
771  if (mAdjustPerfomance)
773  if (disconnectedDialog != nullptr)
774  {
776  disconnectedDialog = nullptr;
777  }
778  }
779  BLOCK_END("Game::slowLogic")
780 }
781 
783 {
784  FUNC_BLOCK("Game::adjustPerfomance", 1)
785  const time_t time = cur_time;
787  {
788  mNextAdjustTime = time + adjustDelay;
789  }
790  else if (mNextAdjustTime < time)
791  {
792  mNextAdjustTime = time + adjustDelay;
793 
794  if (mAdjustLevel > 3 ||
795  localPlayer == nullptr ||
798  {
799  return;
800  }
801 
802  int maxFps = WindowManager::getFramerate();
803  if (maxFps != config.getIntValue("fpslimit"))
804  return;
805 
806  if (maxFps == 0)
807  maxFps = 30;
808  else if (maxFps < 10)
809  return;
810 
811  if (fps < maxFps - 10)
812  {
813  if (mLowerCounter < 2)
814  {
815  mLowerCounter ++;
817  return;
818  }
819  mLowerCounter = 0;
820  mAdjustLevel ++;
821  switch (mAdjustLevel)
822  {
823  case 1:
824  {
825  if (config.getBoolValue("beingopacity"))
826  {
827  config.setValue("beingopacity", false);
828  config.setSilent("beingopacity", true);
829  if (localChatTab != nullptr)
830  {
832  // TRANSLATORS: auto adjust settings message
833  _("Auto disable Show beings transparency"),
837  }
838  }
839  else
840  {
841  mNextAdjustTime = time + 1;
842  mLowerCounter = 2;
843  }
844  break;
845  }
846  case 2:
848  {
850  if (localChatTab != nullptr)
851  {
853  // TRANSLATORS: auto adjust settings message
854  _("Auto lower Particle effects"),
858  }
859  }
860  else
861  {
862  mNextAdjustTime = time + 1;
863  mLowerCounter = 2;
864  }
865  break;
866  case 3:
867  if (!config.getBoolValue("alphaCache"))
868  {
869  config.setValue("alphaCache", true);
870  config.setSilent("alphaCache", false);
871  if (localChatTab != nullptr)
872  {
874  // TRANSLATORS: auto adjust settings message
875  _("Auto enable opacity cache"),
879  }
880  }
881  break;
882  default:
883  break;
884  }
885  }
886  }
887 }
888 
890 {
891  if (!mAdjustPerfomance)
892  return;
893 
895  switch (mAdjustLevel)
896  {
897  case 1:
898  config.setValue("beingopacity",
899  config.getBoolValue("beingopacity"));
900  break;
901  case 2:
902  config.setValue("beingopacity",
903  config.getBoolValue("beingopacity"));
905  "particleEmitterSkip") + 1;
906  break;
907  default:
908  case 3:
909  config.setValue("beingopacity",
910  config.getBoolValue("beingopacity"));
912  "particleEmitterSkip") + 1;
913  config.setValue("alphaCache",
914  config.getBoolValue("alphaCache"));
915  break;
916  }
917  mAdjustLevel = 0;
918 }
919 
921 {
922  BLOCK_START("Game::handleMove")
923  if (localPlayer == nullptr)
924  {
925  BLOCK_END("Game::handleMove")
926  return;
927  }
928 
929  // Moving player around
930  if ((chatWindow != nullptr) &&
931  (quitDialog == nullptr) &&
932  localPlayer->canMove() &&
936  {
937  NpcDialog *const dialog = NpcDialog::getActive();
938  if (dialog != nullptr)
939  {
940  BLOCK_END("Game::handleMove")
941  return;
942  }
943 
944  // Ignore input if either "ignore" key is pressed
945  // Stops the character moving about if the user's window manager
946  // uses "ignore+arrow key" to switch virtual desktops.
949  {
950  BLOCK_END("Game::handleMove")
951  return;
952  }
953 
954  unsigned char direction = 0;
955 
956  // Translate pressed keys to movement and direction
958  ((joystick != nullptr) && joystick->isUp()))
959  {
960  direction |= BeingDirection::UP;
961  setValidSpeed();
963  }
965  ((joystick != nullptr) && joystick->isDown()))
966  {
967  direction |= BeingDirection::DOWN;
968  setValidSpeed();
970  }
971 
973  ((joystick != nullptr) && joystick->isLeft()))
974  {
975  direction |= BeingDirection::LEFT;
976  setValidSpeed();
978  }
980  ((joystick != nullptr) && joystick->isRight()))
981  {
982  direction |= BeingDirection::RIGHT;
983  setValidSpeed();
985  }
987  {
988  direction = localPlayer->getDirection();
989  setValidSpeed();
991  }
992 
997  || direction == 0)
998  {
999  moveInDirection(direction);
1000  }
1001  }
1002  BLOCK_END("Game::handleMove")
1003 }
1004 
1005 void Game::moveInDirection(const unsigned char direction)
1006 {
1007  if (viewport == nullptr)
1008  return;
1009 
1010  if (settings.cameraMode == 0U)
1011  {
1012  if (localPlayer != nullptr)
1013  localPlayer->specialMove(direction);
1014  }
1015  else
1016  {
1017  int dx = 0;
1018  int dy = 0;
1019  if ((direction & BeingDirection::LEFT) != 0)
1020  dx = -5;
1021  else if ((direction & BeingDirection::RIGHT) != 0)
1022  dx = 5;
1023 
1024  if ((direction & BeingDirection::UP) != 0)
1025  dy = -5;
1026  else if ((direction & BeingDirection::DOWN) != 0)
1027  dy = 5;
1028  viewport->moveCamera(dx, dy);
1029  }
1030 }
1031 
1032 void Game::updateFrameRate(int fpsLimit)
1033 {
1034  if (fpsLimit == 0)
1035  {
1036  if (settings.awayMode)
1037  {
1040  {
1041  fpsLimit = config.getIntValue("fpslimit");
1042  }
1043  else
1044  {
1045  fpsLimit = config.getIntValue("altfpslimit");
1046  }
1047  }
1048  else
1049  {
1050  fpsLimit = config.getIntValue("fpslimit");
1051  }
1052  }
1053  WindowManager::setFramerate(fpsLimit);
1055 }
1056 
1061 {
1062  BLOCK_START("Game::handleInput 1")
1063  if (joystick != nullptr)
1064  joystick->logic();
1065 
1067 
1068  // If the user is configuring the keys then don't respond.
1069  if (!keyboard.isEnabled() || settings.awayMode)
1070  {
1071  BLOCK_END("Game::handleInput 1")
1072  return;
1073  }
1074 
1075  // If pressed outfits keys, stop processing keys.
1078  || ((setupWindow != nullptr) && setupWindow->isWindowVisible()))
1079  {
1080  BLOCK_END("Game::handleInput 1")
1081  return;
1082  }
1083 
1084  handleMove();
1086  BLOCK_END("Game::handleInput 1")
1087 }
1088 
1093 void Game::changeMap(const std::string &mapPath)
1094 {
1095  BLOCK_START("Game::changeMap")
1096 
1097  skipPerfFrames = 3;
1098  resetAdjustLevel();
1100 
1103 
1104  // Clean up floor items, beings and particles
1105  if (actorManager != nullptr)
1106  actorManager->clear();
1107 
1108  // Close the popup menu on map change so that invalid options can't be
1109  // executed.
1110  if (viewport != nullptr)
1112 
1113  // Unset the map of the player so that its particles are cleared before
1114  // being deleted in the next step
1115  if (localPlayer != nullptr)
1116  localPlayer->setMap(nullptr);
1117 
1118  if (particleEngine != nullptr)
1119  particleEngine->clear();
1120 
1121  mMapName = mapPath;
1122 
1123  std::string fullMap = pathJoin(paths.getValue("maps", "maps/"),
1124  mMapName).append(".tmx");
1125  std::string realFullMap = pathJoin(paths.getValue("maps", "maps/"),
1126  MapDB::getMapName(mMapName)).append(".tmx");
1127 
1128  if (!VirtFs::exists(realFullMap))
1129  realFullMap.append(".gz");
1130 
1131  // Attempt to load the new map
1132  Map *const newMap = MapReader::readMap(fullMap, realFullMap);
1133 
1134  if (mCurrentMap != nullptr)
1136 
1137  if (newMap != nullptr)
1138  newMap->addExtraLayer();
1139 
1140  if (socialWindow != nullptr)
1141  socialWindow->setMap(newMap);
1142 
1143  // Notify the minimap and actorManager about the map change
1144  if (minimap != nullptr)
1145  minimap->setMap(newMap);
1146  if (actorManager != nullptr)
1147  actorManager->setMap(newMap);
1148  if (particleEngine != nullptr)
1149  particleEngine->setMap(newMap);
1150  if (viewport != nullptr)
1151  viewport->setMap(newMap);
1152 
1153  // Initialize map-based particle effects
1154  if (newMap != nullptr)
1155  newMap->initializeParticleEffects();
1156 
1157  // Start playing new music file when necessary
1158  const std::string oldMusic = mCurrentMap != nullptr
1159  ? mCurrentMap->getMusicFile() : "";
1160  const std::string newMusic = newMap != nullptr ?
1161  newMap->getMusicFile() : "";
1162  if (newMusic != oldMusic)
1163  {
1164  if (newMusic.empty())
1165  soundManager.fadeOutMusic(1000);
1166  else
1167  soundManager.fadeOutAndPlayMusic(newMusic, 1000);
1168  }
1169 
1170  if (mCurrentMap != nullptr)
1172 
1173  delete mCurrentMap;
1174  mCurrentMap = newMap;
1175 
1176  if (questsWindow != nullptr)
1178 
1179 #ifdef USE_MUMBLE
1180  if (mumbleManager)
1181  mumbleManager->setMap(mapPath);
1182 #endif // USE_MUMBLE
1183 
1184  if (localPlayer != nullptr)
1186 
1188  Perf::init();
1189  BLOCK_END("Game::changeMap")
1190 }
1191 
1192 void Game::updateHistory(const SDL_Event &event)
1193 {
1194  if ((localPlayer == nullptr) || (settings.attackType == 0U))
1195  return;
1196 
1197  if (CAST_S32(event.key.keysym.sym) != -1)
1198  {
1199  bool old = false;
1200 
1201  const InputActionT key = KeyboardConfig::getKeyIndex(event, 1);
1202  const time_t time = cur_time;
1203  int idx = -1;
1204  for (int f = 0; f < MAX_LASTKEYS; f ++)
1205  {
1206  LastKey &lastKey = mLastKeys[f];
1207  if (lastKey.key == key)
1208  {
1209  idx = f;
1210  old = true;
1211  break;
1212  }
1213  else if (idx >= 0 && lastKey.time < mLastKeys[idx].time)
1214  {
1215  idx = f;
1216  }
1217  }
1218  if (idx < 0)
1219  {
1220  idx = 0;
1221  for (int f = 0; f < MAX_LASTKEYS; f ++)
1222  {
1223  LastKey &lastKey = mLastKeys[f];
1224  if (lastKey.key == InputAction::NO_VALUE ||
1225  lastKey.time < mLastKeys[idx].time)
1226  {
1227  idx = f;
1228  }
1229  }
1230  }
1231 
1232  if (idx < 0)
1233  idx = 0;
1234 
1235  LastKey &keyIdx = mLastKeys[idx];
1236  if (!old)
1237  {
1238  keyIdx.time = time;
1239  keyIdx.key = key;
1240  keyIdx.cnt = 0;
1241  }
1242  else
1243  {
1244  keyIdx.cnt++;
1245  }
1246  }
1247 }
1248 
1250 {
1251  const int timeRange = 120;
1252  const int cntInTime = 130;
1253 
1254  if ((localPlayer == nullptr) || (settings.attackType == 0U))
1255  return;
1256 
1257  const time_t time = cur_time;
1258  for (int f = 0; f < MAX_LASTKEYS; f ++)
1259  {
1260  LastKey &lastKey = mLastKeys[f];
1261  if (lastKey.key != InputAction::NO_VALUE)
1262  {
1263  if (lastKey.time + timeRange < time)
1264  {
1265  if (lastKey.cnt > cntInTime)
1266  mValidSpeed = false;
1267  lastKey.key = InputAction::NO_VALUE;
1268  }
1269  }
1270  }
1271 }
1272 
1274 {
1275  clearKeysArray();
1276  mValidSpeed = true;
1277 }
1278 
1280 {
1281  for (int f = 0; f < MAX_LASTKEYS; f ++)
1282  {
1283  mLastKeys[f].time = 0;
1285  mLastKeys[f].cnt = 0;
1286  }
1287 }
1288 
1289 void Game::videoResized(const int width, const int height)
1290 {
1291  if (viewport != nullptr)
1292  viewport->setSize(width, height);
1293  if (windowMenu != nullptr)
1294  windowMenu->setPosition(width - windowMenu->getWidth(), 0);
1295 }
ActorManager * actorManager
AssertListener * assertListener
BankWindow * bankWindow
Definition: bankwindow.cpp:40
BattleTab * battleChatTab
Definition: battletab.cpp:32
volatile time_t cur_time
Definition: timer.cpp:58
BeingSlot * emptyBeingSlot
Definition: beingslot.cpp:26
#define CAST_S32
Definition: cast.h:30
ChatTab * debugChatTab
Definition: chattab.cpp:63
ChatTab * localChatTab
Definition: chattab.cpp:62
ChatWindow * chatWindow
Definition: chatwindow.cpp:94
ClanWindow * clanWindow
Definition: clanwindow.cpp:38
void setPlayer(LocalPlayer *const player)
void setMap(Map *const map)
static void setEnableCache(const bool b)
const StringVect & getMessages() const
virtual void add(Widget *const widget)
static void init()
Definition: beinginfo.cpp:223
uint8_t getDirection() const
Definition: being.h:494
static void clearCache()
Definition: being.cpp:4719
static void reReadConfig()
Definition: being.cpp:3431
void recreateItemParticles()
Definition: being.cpp:5163
void setAllowHighlight(const bool n)
Definition: chattab.h:161
void chatLog(std::string line, ChatMsgTypeT own, const IgnoreRecord ignoreRecord, const TryRemoveColors tryRemoveColors)
Definition: chattab.cpp:111
void loadFromLogFile(const std::string &name)
Definition: chattab.cpp:510
void postConnection()
bool isInputFocused() const
Definition: chatwindow.cpp:579
void scheduleDelete()
void showGMTab()
void loadState()
ChatTab * addSpecialChannelTab(const std::string &name, const bool switchTo)
StateT getState() const
Definition: client.h:69
Definition: color.h:76
static void setEnableDelay(bool b)
std::string getValue(const std::string &key, const std::string &deflt) const
bool getBoolValue(const std::string &key) const
void setValue(const std::string &key, const std::string &value)
void incValue(const std::string &key)
void setSilent(const std::string &key, const std::string &value)
int getIntValue(const std::string &key) const
void slowLogic()
static void delayedLoad()
static Window * openErrorDialog(const std::string &header, const std::string &message, const Modal modal)
static void closeDialogs()
void loadData(int num)
void setVisible(Visible visible)
void handleGameEvents() const
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 void init()
Definition: game.h:64
Map * mCurrentMap
Definition: game.h:143
int mLowerCounter
Definition: game.h:150
void updateFrameRate(int fpsLimit)
Definition: game.cpp:1032
LastKey mLastKeys[MAX_LASTKEYS]
Definition: game.h:146
std::string mMapName
Definition: game.h:144
void adjustPerfomance()
Definition: game.cpp:782
void slowLogic()
Definition: game.cpp:679
static void addWatermark()
Definition: game.cpp:520
time_t mNextAdjustTime
Definition: game.h:147
bool mAdjustPerfomance
Definition: game.h:149
void checkKeys()
Definition: game.cpp:1249
int mPing
Definition: game.h:151
bool mValidSpeed
Definition: game.h:145
void handleMove()
Definition: game.cpp:920
static bool saveScreenshot(SDL_Surface *const screenshot, const std::string &prefix)
Definition: game.cpp:563
void handleInput()
Definition: game.cpp:1060
time_t mTime2
Definition: game.h:153
int mAdjustLevel
Definition: game.h:148
static Game * mInstance
Definition: game.h:155
void resetAdjustLevel()
Definition: game.cpp:889
void updateHistory(const SDL_Event &event)
Definition: game.cpp:1192
static void moveInDirection(const unsigned char direction)
Definition: game.cpp:1005
Game()
Definition: game.cpp:405
void clearKeysArray()
Definition: game.cpp:1279
static bool createScreenshot(const std::string &prefix)
Definition: game.cpp:535
void changeMap(const std::string &mapName)
Definition: game.cpp:1093
~Game()
Definition: game.cpp:481
static void videoResized(const int width, const int height)
Definition: game.cpp:1289
void logic()
Definition: game.cpp:663
time_t mTime
Definition: game.h:152
void setValidSpeed()
Definition: game.cpp:1273
int mWidth
Definition: graphics.h:484
RenderType getOpenGL() const
Definition: graphics.h:308
void setSecure(const bool n)
Definition: graphics.h:290
int mHeight
Definition: graphics.h:485
Widget * getTop() const
Definition: gui.h:248
void draw()
Definition: gui.cpp:470
static void clear()
static void init()
static bool getEnableGuildBot()
Definition: guildmanager.h:56
void requestGuildInfo()
static void handleRepeat()
bool isActionActive(const InputActionT index) const
static bool isAnyInputFocused()
bool isRight() const
Definition: joystick.h:114
bool isDown() const
Definition: joystick.h:108
void update()
Definition: joystick.cpp:359
void logic()
Definition: joystick.cpp:230
bool isLeft() const
Definition: joystick.h:111
bool isUp() const
Definition: joystick.h:105
static InputActionT getKeyIndex(const SDL_Event &event, const int grp)
bool isEnabled() const
void update()
Definition: killstats.cpp:365
void recalcStats()
Definition: killstats.cpp:311
void setMap(Map *const map)
void slowLogic()
bool getHalfAway() const
Definition: localplayer.h:239
void specialMove(const unsigned char direction)
bool canMove() const
void updateStatus() const
void cancelFollow()
void log(const char *const log_text,...)
Definition: logger.cpp:269
void log1(const char *const log_text)
Definition: logger.cpp:238
void postConnection()
Definition: mailwindow.cpp:347
static void unloadEmptyAtlas()
Definition: mapreader.cpp:1335
static Map * readMap(const std::string &filename, const std::string &realFilename)
static void loadEmptyAtlas()
Definition: mapreader.cpp:1319
Definition: map.h:75
void saveExtraLayer() const
Definition: map.cpp:1226
void update(const int ticks)
Definition: map.cpp:328
void initializeParticleEffects() const
Definition: map.cpp:1109
void addExtraLayer()
Definition: map.cpp:1142
const std::string getMusicFile() const
Definition: map.cpp:835
void setMap(const Map *const map)
Definition: minimap.cpp:119
virtual void initEngines() const =0
virtual void ping(const int tick) const =0
virtual bool isConnected() const =0
virtual void mapLoadedEvent() const =0
virtual bool mustPing() const =0
virtual void gameStarted() const =0
virtual void gameEnded() const =0
static NpcDialog * getActive()
Definition: npcdialog.cpp:852
static void update()
void setMap(Map *const map)
static int emitterSkip
static void setupEngine()
static void clearPopup()
static void closePopupMenu()
bool isPopupVisible() const
Definition: popup.h:174
void setMap(const Map *const map)
virtual SDL_Surface * getScreenshot()=0
virtual void prepare()=0
bool awayMode
Definition: settings.h:158
bool disableLoggingInGame
Definition: settings.h:161
std::string serverName
Definition: settings.h:114
unsigned int cameraMode
Definition: settings.h:144
bool mouseFocused
Definition: settings.h:156
KeyboardFocusT inputFocused
Definition: settings.h:155
std::string screenshotDir
Definition: settings.h:115
unsigned int attackType
Definition: settings.h:138
void clearWindowsForReset()
Definition: setupwindow.h:68
void externalUpdate()
void setInGame(const bool inGame)
void updateTimes()
void addTab(const std::string &name, ShortcutContainer *const content)
void slowLogic()
void setMap(Map *const map)
Definition: socialwindow.h:104
void fadeOutAndPlayMusic(const std::string &fileName, const int ms)
void fadeOutMusic(const int ms)
const Color & getColor(const ThemeColorIdT type, const unsigned int alpha)
Definition: theme.h:136
void setInGame(const bool b)
void moveCamera(const int dx, const int dy)
Definition: viewport.cpp:1070
Map * getMap() const
Definition: viewport.h:135
void setMap(Map *const map)
Definition: viewport.cpp:89
void cleanHoverItems()
Definition: viewport.cpp:259
void slowLogic()
void setAllowUpdate(const bool n)
Definition: whoisonline.h:89
void setSize(const int width, const int height)
Definition: widget.cpp:367
virtual void requestMoveToTop()
Definition: widget.cpp:213
virtual void requestMoveToBottom()
Definition: widget.cpp:219
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:252
void setPosition(const int x, const int y)
Definition: widget.cpp:161
int getWidth() const
Definition: widget.h:221
Definition: window.h:102
virtual void setVisible(Visible visible)
Definition: window.cpp:778
bool isWindowVisible() const
Definition: window.h:484
virtual void scheduleDelete()
Definition: window.cpp:831
Configuration config
Configuration paths
Configuration serverConfig
Configuration branding
#define valTest(num)
const std::string GENERAL_CHANNEL
Definition: chat.h:29
const std::string TRADE_CHANNEL
Definition: chat.h:31
const unsigned int SHORTCUT_TABS
Definition: itemshortcut.h:28
CrazyMoves * crazyMoves
Definition: crazymoves.cpp:47
#define CREATEWIDGETV0(var, type)
Definition: createwidget.h:32
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:25
CutInWindow * cutInWindow
Definition: cutinwindow.cpp:37
#define MSDL_FreeSurface(surface)
Definition: debug.h:54
DebugWindow * debugWindow
Definition: debugwindow.cpp:43
#define delete2(var)
Definition: delete2.h:25
DidYouKnowWindow * didYouKnowWindow
DropShortcut * dropShortcut
Client * client
Definition: client.cpp:118
std::string errorMessage
Definition: client.cpp:116
bool isSafeMode
Definition: client.cpp:123
Viewport * viewport
Definition: viewport.cpp:36
EffectManager * effectManager
EmoteShortcut * emoteShortcut
EmoteWindow * emoteWindow
Definition: emotewindow.cpp:49
EquipmentWindow * equipmentWindow
EquipmentWindow * beingEquipmentWindow
ErrorListener errorListener
EventsManager eventsManager
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
static void destroyGuiWindows()
Definition: game.cpp:349
const time_t adjustDelay
Definition: game.cpp:162
static void initEngines()
Definition: game.cpp:167
static void createGuiWindows()
Definition: game.cpp:195
bool mStatsReUpdated
Definition: game.cpp:161
Window * disconnectedDialog
Definition: game.cpp:159
QuitDialog * quitDialog
Definition: game.cpp:158
static const int MAX_LASTKEYS
Definition: game.h:38
Net::GameHandler * gameHandler
Definition: net.cpp:91
Net::GeneralHandler * generalHandler
Definition: net.cpp:88
#define _(s)
Definition: gettext.h:35
GmTab * gmChatTab
Definition: gmtab.cpp:34
Graphics * mainGraphics
Definition: graphics.cpp:109
const Image *restrict const top
ScreenshotHelper * screenshortHelper
Gui * gui
Definition: gui.cpp:111
Font * boldFont
Definition: gui.cpp:112
GuildManager * guildManager
const bool IgnoreRecord_false
Definition: ignorerecord.h:30
InputAction ::T InputActionT
Definition: inputaction.h:717
InputManager inputManager
InventoryWindow * inventoryWindow
InventoryWindow * cartWindow
Joystick * joystick
Definition: joystick.cpp:43
KeyboardConfig keyboard
KillStats * killStats
Definition: killstats.cpp:45
LangTab * langChatTab
Definition: langtab.cpp:28
#define nullptr
Definition: localconsts.h:45
LocalPlayer * localPlayer
Logger * logger
Definition: logger.cpp:89
MailWindow * mailWindow
Definition: mailwindow.cpp:54
Minimap * minimap
Definition: minimap.cpp:62
volatile int tick_time
Definition: timer.cpp:53
MiniStatusWindow * miniStatusWindow
int mkdir_r(const char *const pathname)
Create a directory, making leading components first if necessary.
Definition: mkdir.cpp:109
const bool Modal_false
Definition: modal.h:30
bool screenshot(InputEvent &event)
Definition: actions.cpp:51
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
const std::string getMapName(const std::string &name)
Definition: mapdb.cpp:204
ServerTypeT getNetworkType()
Definition: net.cpp:189
void init()
Definition: perfstat.cpp:41
Inventory * getInventory()
Definition: playerinfo.cpp:195
Equipment * getEquipment()
Definition: playerinfo.cpp:220
Inventory * getCartInventory()
Definition: playerinfo.cpp:207
void clear()
Definition: playerinfo.cpp:452
void gameDestroyed()
Definition: playerinfo.cpp:463
bool writePNG(SDL_Surface *const surface, const std::string &filename)
Definition: pnglib.cpp:37
@ CHANGE_MAP
Definition: state.h:50
@ ERROR
Definition: state.h:35
const char * getUserDir()
Definition: fs.cpp:84
bool exists(std::string name)
Definition: fs.cpp:124
void setFramerate(const unsigned int fpsLimit)
OutfitWindow * outfitWindow
ParticleEngine * particleEngine
#define FUNC_BLOCK(name, id)
Definition: perfomance.h:81
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
int skipPerfFrames
Definition: perfstat.cpp:37
PopupMenu * popupMenu
Definition: popupmenu.cpp:103
QuestsWindow * questsWindow
@ RENDER_SOFTWARE
Definition: rendertype.h:27
Settings settings
Definition: settings.cpp:32
SetupWindow * setupWindow
Definition: setupwindow.cpp:64
ShopWindow * shopWindow
Definition: shopwindow.cpp:101
ShortcutWindow * dropShortcutWindow
ShortcutWindow * spellShortcutWindow
ShortcutWindow * emoteShortcutWindow
ShortcutWindow * itemShortcutWindow
SkillDialog * skillDialog
Definition: skilldialog.cpp:66
SocialWindow * socialWindow
SoundManager soundManager
const unsigned int SPELL_SHORTCUT_TABS
Definition: spells.h:29
StatusWindow * statusWindow
void cutFirst(std::string &str1, const std::string &str2)
std::string strprintf(const char *const format,...)
std::string pathJoin(std::string str1, const std::string &str2)
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:31
std::vector< std::string > StringVect
Definition: stringvector.h:29
Definition: game.h:45
InputActionT key
Definition: game.h:55
int cnt
Definition: game.h:56
time_t time
Definition: game.h:54
Theme * theme
Definition: theme.cpp:62
int get_elapsed_time1(const int startTime)
Definition: timer.cpp:105
volatile int fps
Definition: timer.cpp:54
TouchManager touchManager
TradeTab * tradeChatTab
Definition: tradetab.cpp:36
TradeWindow * tradeWindow
Definition: tradewindow.cpp:65
const bool TryRemoveColors_true
const bool Visible_false
Definition: visible.h:30
const bool Visible_true
Definition: visible.h:30
WhoIsOnline * whoIsOnline
Definition: whoisonline.cpp:82
WindowContainer * windowContainer
WindowMenu * windowMenu
Definition: windowmenu.cpp:51