ManaPlus
localplayer.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 "being/localplayer.h"
25 
26 #include "actormanager.h"
27 #include "configuration.h"
28 #include "gamemodifiers.h"
29 #include "guild.h"
30 #include "party.h"
31 #include "settings.h"
32 #include "soundmanager.h"
33 #include "statuseffect.h"
34 
35 #include "being/beingflag.h"
36 #include "being/crazymoves.h"
37 #include "being/playerinfo.h"
38 #include "being/playerrelations.h"
39 
40 #include "const/sound.h"
41 
42 #include "enums/equipslot.h"
43 
45 
48 
50 
51 #include "input/keyboardconfig.h"
52 
53 #include "gui/gui.h"
54 #include "gui/userpalette.h"
55 #include "gui/popupmanager.h"
56 
57 #include "gui/windows/chatwindow.h"
59 #include "gui/windows/okdialog.h"
61 #include "gui/windows/shopwindow.h"
65 
67 
68 #include "listeners/awaylistener.h"
69 
70 #include "net/beinghandler.h"
71 #include "net/chathandler.h"
72 #include "net/inventoryhandler.h"
73 #include "net/net.h"
74 #include "net/packetlimiter.h"
75 #include "net/playerhandler.h"
76 #include "net/serverfeatures.h"
77 
78 #include "resources/iteminfo.h"
79 
80 #include "resources/db/weaponsdb.h"
81 
82 #include "resources/item/item.h"
83 
84 #include "resources/map/map.h"
85 #include "resources/map/mapitem.h"
88 
90 
91 #include "utils/delete2.h"
92 #include "utils/foreach.h"
93 #include "utils/gettext.h"
94 #include "utils/timer.h"
95 
96 #ifdef USE_MUMBLE
97 #include "mumblemanager.h"
98 #endif // USE_MUMBLE
99 
100 #include <climits>
101 
102 #include "debug.h"
103 
104 static const int16_t awayLimitTimer = 60;
105 static const int MAX_TICK_VALUE = INT_MAX / 2;
106 
107 typedef std::map<int, Guild*>::const_iterator GuildMapCIter;
108 
110 
111 extern OkDialog *weightNotice;
112 extern time_t weightNoticeTime;
113 
115  const BeingTypeId subType) :
116  Being(id, ActorType::Player),
120  mMoveState(0),
121  mLastTargetX(0),
122  mLastTargetY(0),
123  mHomes(),
124  mTarget(nullptr),
125  mPlayerFollowed(),
126  mPlayerImitated(),
127  mNextDestX(0),
128  mNextDestY(0),
129  mPickUpTarget(nullptr),
130  mLastAction(-1),
131  mStatusEffectIcons(),
132  mMessages(),
133  mMessageTime(0),
134  mAwayListener(new AwayListener),
135  mAwayDialog(nullptr),
136  mPingSendTick(0),
137  mPingTime(0),
138  mAfkTime(0),
139  mActivityTime(0),
140  mNavigateX(0),
141  mNavigateY(0),
142  mNavigateId(BeingId_zero),
143  mCrossX(0),
144  mCrossY(0),
145  mOldX(0),
146  mOldY(0),
147  mOldTileX(0),
148  mOldTileY(0),
149  mNavigatePath(),
150  mLastHitFrom(),
151  mWaitFor(),
152  mAdvertTime(0),
153  mTestParticle(nullptr),
154  mTestParticleName(),
155  mTestParticleTime(0),
156  mTestParticleHash(0L),
157  mSyncPlayerMoveDistance(config.getIntValue("syncPlayerMoveDistance")),
158  mUnfreezeTime(0),
159  mWalkingDir(0),
160  mUpdateName(true),
161  mBlockAdvert(false),
162  mTargetDeadPlayers(config.getBoolValue("targetDeadPlayers")),
163  mServerAttack(fromBool(config.getBoolValue("serverAttack"), Keep)),
164  mVisibleNames(static_cast<VisibleName::Type>(
165  config.getIntValue("visiblenames"))),
166  mEnableAdvert(config.getBoolValue("enableAdvert")),
167  mTradebot(config.getBoolValue("tradebot")),
168  mTargetOnlyReachable(config.getBoolValue("targetOnlyReachable")),
169  mIsServerBuggy(serverConfig.getValueBool("enableBuggyServers", true)),
170  mSyncPlayerMove(config.getBoolValue("syncPlayerMove")),
171  mDrawPath(config.getBoolValue("drawPath")),
172  mAttackMoving(config.getBoolValue("attackMoving")),
173  mAttackNext(config.getBoolValue("attackNext")),
174  mShowJobExp(config.getBoolValue("showJobExp")),
175  mShowServerPos(config.getBoolValue("showserverpos")),
176  mNextStep(false),
177  mGoingToTarget(false),
178  mKeepAttacking(false),
179  mPathSetByMouse(false),
180  mWaitPing(false),
181  mShowNavigePath(false),
182  mAllowRename(false),
183  mFreezed(false)
184 {
185  logger->log1("LocalPlayer::LocalPlayer");
186 
187 #ifdef TMWA_SUPPORT
189  {
191  config.getIntValue("syncPlayerMoveDistanceLegacy");
192  }
193 #endif
194 
195  postInit(subType, nullptr);
196  mAttackRange = 0;
197  mLevel = 1;
198  mAdvanced = true;
199  mTextColor = &theme->getColor(ThemeColorId::PLAYER, 255);
200  if (userPalette != nullptr)
202  else
203  mNameColor = nullptr;
204 
206  getWalkSpeed(),
207  Notify_true);
209  0,
210  Notify_true);
211 
212  loadHomes();
213 
214  config.addListener("showownname", this);
215  config.addListener("targetDeadPlayers", this);
216  serverConfig.addListener("enableBuggyServers", this);
217  config.addListener("syncPlayerMove", this);
218  config.addListener("syncPlayerMoveDistance", this);
219 #ifdef TMWA_SUPPORT
220  config.addListener("syncPlayerMoveDistanceLegacy", this);
221 #endif
222  config.addListener("drawPath", this);
223  config.addListener("serverAttack", this);
224  config.addListener("attackMoving", this);
225  config.addListener("attackNext", this);
226  config.addListener("showJobExp", this);
227  config.addListener("enableAdvert", this);
228  config.addListener("tradebot", this);
229  config.addListener("targetOnlyReachable", this);
230  config.addListener("showserverpos", this);
231  config.addListener("visiblenames", this);
232  setShowName(config.getBoolValue("showownname"));
233 }
234 
236 {
237  logger->log1("LocalPlayer::~LocalPlayer");
238 
239  config.removeListeners(this);
240  serverConfig.removeListener("enableBuggyServers", this);
241 
242  navigateClean();
243  mCrossX = 0;
244  mCrossY = 0;
245 
247 
248  if (mAwayDialog != nullptr)
249  {
252  }
254 }
255 
257 {
258  BLOCK_START("LocalPlayer::logic")
259 #ifdef USE_MUMBLE
260  if (mumbleManager)
261  mumbleManager->setPos(mX, mY, mDirection);
262 #endif // USE_MUMBLE
263 
264  // Actions are allowed once per second
265  if (get_elapsed_time(mLastAction) >= 1000)
266  mLastAction = -1;
267 
268  if (mActivityTime == 0 || mLastAction != -1)
270 
271  if (mUnfreezeTime > 0 &&
273  {
274  mUnfreezeTime = 0;
275  mFreezed = false;
276  }
277 
278  if ((mAction != BeingAction::MOVE || mNextStep) && !mNavigatePath.empty())
279  {
280  mNextStep = false;
281  int dist = 5;
282  if (!mSyncPlayerMove)
283  dist = 20;
284 
285  if (((mNavigateX != 0) || (mNavigateY != 0)) &&
286  ((mCrossX + dist >= mX && mCrossX <= mX + dist
287  && mCrossY + dist >= mY && mCrossY <= mY + dist)
288  || ((mCrossX == 0) && (mCrossY == 0))))
289  {
290  const Path::const_iterator i = mNavigatePath.begin();
291  if ((*i).x == mX && (*i).y == mY)
292  mNavigatePath.pop_front();
293  else
294  setDestination((*i).x, (*i).y);
295  }
296  }
297 
298  // Show XP messages
299  if (!mMessages.empty())
300  {
301  if (mMessageTime == 0)
302  {
303  const MessagePair info = mMessages.front();
304 
305  if ((particleEngine != nullptr) && (gui != nullptr))
306  {
308  info.first,
309  mPixelX,
310  mPixelY - 48,
311  &userPalette->getColor(info.second, 255U),
313  true);
314  }
315 
316  mMessages.pop_front();
317  mMessageTime = 30;
318  }
319  mMessageTime--;
320  }
321 
322  if (mTarget != nullptr)
323  {
324  if (mTarget->getType() == ActorType::Npc)
325  {
326  // NPCs are always in range
328  }
329  else
330  {
331  // Find whether target is in range
332  const int rangeX = CAST_S32(
333  abs(mTarget->mX - mX));
334  const int rangeY = CAST_S32(
335  abs(mTarget->mY - mY));
336  const int attackRange = getAttackRange();
337  const TargetCursorTypeT targetType
338  = rangeX > attackRange || rangeY > attackRange
340  mTarget->setTargetType(targetType);
341 
342  if (!mTarget->isAlive() && (!mTargetDeadPlayers
344  {
345  stopAttack(true);
346  }
347 
348  if (mKeepAttacking && (mTarget != nullptr))
349  attack(mTarget, true, false);
350  }
351  }
352 
353  Being::logic();
354  BLOCK_END("LocalPlayer::logic")
355 }
356 
358 {
359  BLOCK_START("LocalPlayer::slowLogic")
360  const time_t time = cur_time;
361  if ((weightNotice != nullptr) && weightNoticeTime < time)
362  {
364  weightNotice = nullptr;
365  weightNoticeTime = 0;
366  }
367 
368  if ((serverFeatures != nullptr) &&
370  mEnableAdvert &&
371  !mBlockAdvert &&
373  {
374  uint8_t smile = BeingFlag::SPECIAL;
375  if (mTradebot &&
376  shopWindow != nullptr &&
378  {
379  smile |= BeingFlag::SHOP;
380  }
381 
383  smile |= BeingFlag::AWAY;
384 
385  if (mInactive)
386  smile |= BeingFlag::INACTIVE;
387 
388  if (emote(smile))
389  mAdvertTime = time + 60;
390  else
391  mAdvertTime = time + 30;
392  }
393 
394  if (mTestParticleTime != time && !mTestParticleName.empty())
395  {
396  const unsigned long hash = UpdaterWindow::getFileHash(
398  if (hash != mTestParticleHash)
399  {
401  mTestParticleHash = hash;
402  }
403  mTestParticleTime = time;
404  }
405 
406  BLOCK_END("LocalPlayer::slowLogic")
407 }
408 
410  const int attackId)
411 {
412  if (action == BeingAction::DEAD)
413  {
414  if (!mLastHitFrom.empty() &&
416  {
417  // TRANSLATORS: chat message after death
418  debugMsg(strprintf(_("You were killed by %s."),
419  mLastHitFrom.c_str()))
420  mLastHitFrom.clear();
421  }
422  setTarget(nullptr);
423  }
424 
425  Being::setAction(action,
426  attackId);
427 #ifdef USE_MUMBLE
428  if (mumbleManager)
429  mumbleManager->setAction(CAST_S32(action));
430 #endif // USE_MUMBLE
431 }
432 
433 void LocalPlayer::setGroupId(const int id)
434 {
435  Being::setGroupId(id);
436 
437  if (mIsGM != 0)
438  {
439  if (chatWindow != nullptr)
440  {
443  }
444  }
445  if (statusWindow != nullptr)
447 }
448 
450 {
451  const Party *const party = Party::getParty(1);
452  if (party != nullptr)
453  {
454  PartyMember *const pm = party->getMember(mName);
455  if (pm != nullptr)
456  {
457  pm->setX(mX);
458  pm->setY(mY);
459  }
460  }
461 
462  if (mPath.empty())
463  {
464  if (mPickUpTarget != nullptr)
466 
467  if (mWalkingDir != 0U)
469  }
470  else if (mPath.size() == 1)
471  {
472  if (mPickUpTarget != nullptr)
474  }
475 
476  if (mGoingToTarget &&
477  mTarget != nullptr &&
478  withinAttackRange(mTarget, false, 0))
479  {
481  attack(mTarget, true, false);
482  mGoingToTarget = false;
483  mPath.clear();
484  return;
485  }
486  else if (mGoingToTarget && (mTarget == nullptr))
487  {
488  mGoingToTarget = false;
489  mPath.clear();
490  }
491 
492  if (mPath.empty())
493  {
494  if (mNavigatePath.empty() || mAction != BeingAction::MOVE)
495  {
497  // +++ probably sync position here always?
498  }
499  else
500  {
501  mNextStep = true;
502  }
503  }
504  else
505  {
506  Being::nextTile();
507  }
508 
509  fixPos();
510 }
511 
513 {
514  if (item == nullptr)
515  return false;
516 
518  return false;
519 
520  const int dx = item->getTileX() - mX;
521  const int dy = item->getTileY() - mY;
522  int dist = 6;
523 
524  const unsigned int pickUpType = settings.pickUpType;
525  if (pickUpType >= 4 && pickUpType <= 6)
526  dist = 4;
527 
528  if (dx * dx + dy * dy < dist)
529  {
530  if ((actorManager != nullptr) && actorManager->checkForPickup(item))
531  {
533  mPickUpTarget = nullptr;
534  }
535  }
536  else if (pickUpType >= 4 && pickUpType <= 6)
537  {
538  const Path debugPath = mMap->findPath(
539  (mPixelX - mapTileSize / 2) / mapTileSize,
541  item->getTileX(),
542  item->getTileY(),
544  0);
545  if (!debugPath.empty())
546  navigateTo(item->getTileX(), item->getTileY());
547  else
548  setDestination(item->getTileX(), item->getTileY());
549 
550  mPickUpTarget = item;
552  }
553  return true;
554 }
555 
557 {
558  if (mPickUpTarget == &actorSprite)
559  mPickUpTarget = nullptr;
560 }
561 
563 {
564  return mTarget;
565 }
566 
567 void LocalPlayer::setTarget(Being *const target)
568 {
569  if (target == this && (target != nullptr))
570  return;
571 
572  if (target == mTarget)
573  return;
574 
575  Being *oldTarget = nullptr;
576  if (mTarget != nullptr)
577  {
578  mTarget->untarget();
579  oldTarget = mTarget;
580  }
581 
582  if (mTarget != nullptr)
583  {
585  mTarget->setShowName(false);
586  }
587 
588  mTarget = target;
589 
590  if (oldTarget != nullptr)
591  oldTarget->updateName();
592 
593  if (target != nullptr)
594  {
595  mLastTargetX = target->mX;
596  mLastTargetY = target->mY;
597  target->updateName();
599  target->setShowName(true);
600  }
601  if (oldTarget != nullptr && mVisibleNames == VisibleName::ShowOnSelection)
602  oldTarget->setShowName(false);
603  if (target != nullptr && target->getType() == ActorType::Monster)
604  target->setShowName(true);
605 }
606 
608  const AllowSort allowSort)
609 {
610  if (actorManager != nullptr)
611  {
612  Being *const target = actorManager->findNearestLivingBeing(
613  localPlayer, 20, type, allowSort);
614 
615  if ((target != nullptr) && target != mTarget)
616  setTarget(target);
617 
618  return target;
619  }
620  return nullptr;
621 }
622 
623 void LocalPlayer::setDestination(const int x, const int y)
624 {
626 
627  if (settings.attackType == 0 || !mAttackMoving)
628  mKeepAttacking = false;
629 
630  // Only send a new message to the server when destination changes
631  if (x != mDest.x || y != mDest.y)
632  {
633  if (settings.moveType != 1)
634  {
637  }
638  else
639  {
640  uint8_t newDir = 0;
641  if ((mDirection & BeingDirection::UP) != 0)
642  newDir |= BeingDirection::DOWN;
643  if ((mDirection & BeingDirection::LEFT) != 0)
644  newDir |= BeingDirection::RIGHT;
645  if ((mDirection & BeingDirection::DOWN) != 0)
646  newDir |= BeingDirection::UP;
647  if ((mDirection & BeingDirection::RIGHT) != 0)
648  newDir |= BeingDirection::LEFT;
649 
650  playerHandler->setDestination(x, y, newDir);
651 
652 // if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION))
653  {
654  setDirection(newDir);
655  playerHandler->setDirection(newDir);
656  }
657 
660  }
661  }
662 }
663 
664 void LocalPlayer::setWalkingDir(const unsigned char dir)
665 {
666  // This function is called by Game::handleInput()
667  mWalkingDir = dir;
668 
669  // If we're not already walking, start walking.
670  if (mAction != BeingAction::MOVE && (dir != 0U))
671  startWalking(dir);
672 }
673 
674 void LocalPlayer::startWalking(const unsigned char dir)
675 {
676  // This function is called by setWalkingDir(),
677  // but also by nextTile() for TMW-Athena...
678  if ((mMap == nullptr) || (dir == 0U))
679  return;
680 
681  mPickUpTarget = nullptr;
682  if (mAction == BeingAction::MOVE && !mPath.empty())
683  {
684  // Just finish the current action, otherwise we get out of sync
686  return;
687  }
688 
689  int dx = 0;
690  int dy = 0;
691  if ((dir & BeingDirection::UP) != 0)
692  dy--;
693  if ((dir & BeingDirection::DOWN) != 0)
694  dy++;
695  if ((dir & BeingDirection::LEFT) != 0)
696  dx--;
697  if ((dir & BeingDirection::RIGHT) != 0)
698  dx++;
699 
700  const unsigned char blockWalkMask = getBlockWalkMask();
701  // Prevent skipping corners over colliding tiles
702  if ((dx != 0) && !mMap->getWalk(mX + dx, mY, blockWalkMask))
703  dx = 0;
704  if ((dy != 0) && !mMap->getWalk(mX, mY + dy, blockWalkMask))
705  dy = 0;
706 
707  // Choose a straight direction when diagonal target is blocked
708  if (dx != 0 && dy != 0 && !mMap->getWalk(mX + dx, mY + dy, blockWalkMask))
709  dx = 0;
710 
711  // Walk to where the player can actually go
712  if ((dx != 0 || dy != 0) && mMap->getWalk(mX + dx, mY + dy, blockWalkMask))
713  {
714  setDestination(mX + dx, mY + dy);
715  }
716  else if (dir != mDirection)
717  {
718  // If the being can't move, just change direction
719 
720 // if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION))
721  {
723  setDirection(dir);
724  }
725  }
726 }
727 
728 void LocalPlayer::stopWalking(const bool sendToServer)
729 {
730  if (mAction == BeingAction::MOVE && (mWalkingDir != 0U))
731  {
732  mWalkingDir = 0;
733  mPickUpTarget = nullptr;
735  mPixelY);
736  if (sendToServer)
737  {
739  mPixelX,
740  mPixelY,
741  -1);
742  }
744  }
745 
746  // No path set anymore, so we reset the path by mouse flag
747  mPathSetByMouse = false;
748 
749  clearPath();
750  navigateClean();
751 }
752 
754 {
756  return false;
757 
758  BeingActionT newAction;
759  switch (mAction)
760  {
761  case BeingAction::STAND:
763  case BeingAction::SPAWN:
764  newAction = BeingAction::SIT;
765  break;
766  case BeingAction::SIT:
767  newAction = BeingAction::STAND;
768  break;
769  case BeingAction::MOVE:
770  case BeingAction::ATTACK:
771  case BeingAction::DEAD:
772  case BeingAction::HURT:
773  case BeingAction::CAST:
774  default:
775  return true;
776  }
777 
778  playerHandler->changeAction(newAction);
779  return true;
780 }
781 
783 {
785  return false;
786 
788  return true;
789 }
790 
791 bool LocalPlayer::emote(const uint8_t emotion)
792 {
794  return false;
795 
796  playerHandler->emote(emotion);
797  return true;
798 }
799 
800 void LocalPlayer::attack(Being *const target,
801  const bool keep,
802  const bool dontChangeEquipment)
803 {
804  mKeepAttacking = keep;
805 
806  if ((target == nullptr) || target->getType() == ActorType::Npc)
807  return;
808 
809  if (mTarget != target)
810  setTarget(target);
811 
812  // Must be standing or sitting or casting to attack
813  if (mAction != BeingAction::STAND &&
816  {
817  return;
818  }
819 
820 #ifdef TMWA_SUPPORT
821  const int dist_x = target->mX - mX;
822  const int dist_y = target->mY - mY;
823 
825  {
826  if (abs(dist_y) >= abs(dist_x))
827  {
828  if (dist_y > 0)
830  else
832  }
833  else
834  {
835  if (dist_x > 0)
837  else
839  }
840  }
841 #endif // TMWA_SUPPORT
842 
844 
845  if (target->getType() != ActorType::Player
846  || checAttackPermissions(target))
847  {
849 
851  return;
852 
853  if (!dontChangeEquipment)
855 
856  const BeingId targetId = target->getId();
857  playerHandler->attack(targetId, mServerAttack);
859  }
860 
861  if (!keep)
862  stopAttack(false);
863 }
864 
865 void LocalPlayer::stopAttack(const bool keepAttack)
866 {
868  return;
869 
872 
873  untarget();
874  if (!keepAttack || !mAttackNext)
875  mKeepAttacking = false;
876 }
877 
879 {
882 
883  if (mTarget != nullptr)
884  setTarget(nullptr);
885 }
886 
888  const int amount,
889  const ItemColor color,
890  const BeingId floorItemId,
891  const PickupT fail)
892 {
893  if (fail != Pickup::OKAY)
894  {
895  if ((actorManager != nullptr) && floorItemId != BeingId_zero)
896  {
897  FloorItem *const item = actorManager->findItem(floorItemId);
898  if (item != nullptr)
899  {
900  if (!item->getShowMsg())
901  return;
902  item->setShowMsg(false);
903  }
904  }
905  const char* msg = nullptr;
906  switch (fail)
907  {
908  case Pickup::BAD_ITEM:
909  // TRANSLATORS: pickup error message
910  msg = N_("Tried to pick up nonexistent item.");
911  break;
912  case Pickup::TOO_HEAVY:
913  // TRANSLATORS: pickup error message
914  msg = N_("Item is too heavy.");
915  break;
916  case Pickup::TOO_FAR:
917  // TRANSLATORS: pickup error message
918  msg = N_("Item is too far away.");
919  break;
920  case Pickup::INV_FULL:
921  // TRANSLATORS: pickup error message
922  msg = N_("Inventory is full.");
923  break;
924  case Pickup::STACK_FULL:
925  // TRANSLATORS: pickup error message
926  msg = N_("Stack is too big.");
927  break;
928  case Pickup::DROP_STEAL:
929  // TRANSLATORS: pickup error message
930  msg = N_("Item belongs to someone else.");
931  break;
932  case Pickup::MAX_AMOUNT:
933  // TRANSLATORS: pickup error message
934  msg = N_("You can't pickup this amount of items.");
935  break;
937  // TRANSLATORS: pickup error message
938  msg = N_("Your item stack has max amount.");
939  break;
940  case Pickup::OKAY:
941  break;
942  default:
943  case Pickup::UNKNOWN:
944  // TRANSLATORS: pickup error message
945  msg = N_("Unknown problem picking up item.");
946  break;
947  }
948  if (localChatTab != nullptr &&
949  config.getBoolValue("showpickupchat"))
950  {
951  localChatTab->chatLog(gettext(msg),
955  }
956 
957  if ((mMap != nullptr) && config.getBoolValue("showpickupparticle"))
958  {
959  // Show pickup notification
961  }
962  }
963  else
964  {
965  std::string str;
966 #ifdef TMWA_SUPPORT
968  {
969  str = itemInfo.getName();
970  }
971  else
972 #endif // TMWA_SUPPORT
973  {
974  str = itemInfo.getName(color);
975  }
976 
977  if (config.getBoolValue("showpickupchat") && (localChatTab != nullptr))
978  {
979  // TRANSLATORS: %d is number,
980  // [@@%d|%s@@] - here player can see link to item
981  localChatTab->chatLog(strprintf(ngettext("You picked up %d "
982  "[@@%d|%s@@].", "You picked up %d [@@%d|%s@@].", amount),
983  amount, itemInfo.getId(), str.c_str()),
987  }
988 
989  if ((mMap != nullptr) && config.getBoolValue("showpickupparticle"))
990  {
991  // Show pickup notification
992  if (amount > 1)
993  {
994  addMessageToQueue(strprintf("%d x %s", amount,
995  str.c_str()), UserColorId::PICKUP_INFO);
996  }
997  else
998  {
1000  }
1001  }
1002  }
1003 }
1004 
1006 {
1007  if (mAttackRange > -1)
1008  {
1009  return mAttackRange;
1010  }
1011 
1012  const Item *const weapon = PlayerInfo::getEquipment(
1014  if (weapon != nullptr)
1015  {
1016  const ItemInfo &info = weapon->getInfo();
1017  return info.getAttackRange();
1018  }
1019  return 48; // unarmed range
1020 }
1021 
1022 bool LocalPlayer::withinAttackRange(const Being *const target,
1023  const bool fixDistance,
1024  const int addRange) const
1025 {
1026  if (target == nullptr)
1027  return false;
1028 
1029  int range = getAttackRange() + addRange;
1030  int dx;
1031  int dy;
1032 
1033  if (fixDistance && range == 1)
1034  range = 2;
1035 
1036  dx = CAST_S32(abs(target->mX - mX));
1037  dy = CAST_S32(abs(target->mY - mY));
1038  return !(dx > range || dy > range);
1039 }
1040 
1042 {
1043  if (target == nullptr)
1044  return;
1045 
1046  mPickUpTarget = nullptr;
1047  setTarget(target);
1048  mGoingToTarget = true;
1049  navigateTo(target->mX,
1050  target->mY);
1051 }
1052 
1054  const int32_t effectId,
1055  const Enable newStatus,
1056  const IsStart start)
1057 {
1059  effectId,
1060  newStatus,
1061  start);
1062 
1063  if (effect != nullptr)
1064  {
1065  effect->deliverMessage();
1066  effect->playSFX();
1067 
1068  AnimatedSprite *const sprite = effect->getIcon();
1069 
1070  if (sprite == nullptr)
1071  {
1072  // delete sprite, if necessary
1073  for (size_t i = 0; i < mStatusEffectIcons.size(); )
1074  {
1075  if (mStatusEffectIcons[i] == effectId)
1076  {
1077  mStatusEffectIcons.erase(mStatusEffectIcons.begin() + i);
1078  if (miniStatusWindow != nullptr)
1080  }
1081  else
1082  {
1083  i++;
1084  }
1085  }
1086  }
1087  else
1088  {
1089  // replace sprite or append
1090  bool found = false;
1091  const size_t sz = mStatusEffectIcons.size();
1092  for (size_t i = 0; i < sz; i++)
1093  {
1094  if (mStatusEffectIcons[i] == effectId)
1095  {
1096  if (miniStatusWindow != nullptr)
1097  miniStatusWindow->setIcon(CAST_S32(i), sprite);
1098  found = true;
1099  break;
1100  }
1101  }
1102 
1103  if (!found)
1104  { // add new
1105  if (miniStatusWindow != nullptr)
1106  {
1107  const int offset = CAST_S32(mStatusEffectIcons.size());
1108  miniStatusWindow->setIcon(offset, sprite);
1109  }
1110  mStatusEffectIcons.push_back(effectId);
1111  }
1112  }
1113  }
1114 }
1115 
1116 void LocalPlayer::addMessageToQueue(const std::string &message,
1117  const UserColorIdT color)
1118 {
1119  if (mMessages.size() < 20)
1120  mMessages.push_back(MessagePair(message, color));
1121 }
1122 
1123 void LocalPlayer::optionChanged(const std::string &value)
1124 {
1125  if (value == "showownname")
1126  {
1127  setShowName(config.getBoolValue("showownname"));
1128  }
1129  else if (value == "targetDeadPlayers")
1130  {
1131  mTargetDeadPlayers = config.getBoolValue("targetDeadPlayers");
1132  }
1133  else if (value == "enableBuggyServers")
1134  {
1135  mIsServerBuggy = serverConfig.getBoolValue("enableBuggyServers");
1136  }
1137  else if (value == "syncPlayerMove")
1138  {
1139  mSyncPlayerMove = config.getBoolValue("syncPlayerMove");
1140  }
1141  else if (value == "syncPlayerMoveDistance")
1142  {
1143 #ifdef TMWA_SUPPORT
1145 #endif
1146  {
1148  config.getIntValue("syncPlayerMoveDistance");
1149  }
1150  }
1151 #ifdef TMWA_SUPPORT
1152  else if (value == "syncPlayerMoveDistanceLegacy")
1153  {
1155  {
1157  config.getIntValue("syncPlayerMoveDistanceLegacy");
1158  }
1159  }
1160 #endif
1161  else if (value == "drawPath")
1162  {
1163  mDrawPath = config.getBoolValue("drawPath");
1164  }
1165  else if (value == "serverAttack")
1166  {
1167  mServerAttack = fromBool(config.getBoolValue("serverAttack"), Keep);
1168  }
1169  else if (value == "attackMoving")
1170  {
1171  mAttackMoving = config.getBoolValue("attackMoving");
1172  }
1173  else if (value == "attackNext")
1174  {
1175  mAttackNext = config.getBoolValue("attackNext");
1176  }
1177  else if (value == "showJobExp")
1178  {
1179  mShowJobExp = config.getBoolValue("showJobExp");
1180  }
1181  else if (value == "enableAdvert")
1182  {
1183  mEnableAdvert = config.getBoolValue("enableAdvert");
1184  }
1185  else if (value == "tradebot")
1186  {
1187  mTradebot = config.getBoolValue("tradebot");
1188  }
1189  else if (value == "targetOnlyReachable")
1190  {
1191  mTargetOnlyReachable = config.getBoolValue("targetOnlyReachable");
1192  }
1193  else if (value == "showserverpos")
1194  {
1195  mShowServerPos = config.getBoolValue("showserverpos");
1196  }
1197  else if (value == "visiblenames")
1198  {
1199  mVisibleNames = static_cast<VisibleName::Type>(
1200  config.getIntValue("visiblenames"));
1201  }
1202 }
1203 
1204 void LocalPlayer::addJobMessage(const int64_t change)
1205 {
1206  if (change != 0 && mMessages.size() < 20)
1207  {
1208  const std::string xpStr = toString(CAST_U64(change));
1209  if (!mMessages.empty())
1210  {
1211  MessagePair pair = mMessages.back();
1212  // TRANSLATORS: this is normal experience
1213  if (pair.first.find(strprintf(" %s", _("xp"))) ==
1214  // TRANSLATORS: this is normal experience
1215  pair.first.size() - strlen(_("xp")) - 1)
1216  {
1217  mMessages.pop_back();
1218  pair.first.append(strprintf(", %s %s",
1219  xpStr.c_str(),
1220  // TRANSLATORS: this is job experience
1221  _("job")));
1222  mMessages.push_back(pair);
1223  }
1224  else
1225  {
1226  addMessageToQueue(strprintf("%s %s",
1227  xpStr.c_str(),
1228  // TRANSLATORS: this is job experience
1229  _("job")),
1231  }
1232  }
1233  else
1234  {
1235  addMessageToQueue(strprintf("%s %s",
1236  xpStr.c_str(),
1237  // TRANSLATORS: this is job experience
1238  _("job")),
1240  }
1241  }
1242 }
1243 
1244 void LocalPlayer::addXpMessage(const int64_t change)
1245 {
1246  if (change != 0 && mMessages.size() < 20)
1247  {
1248  addMessageToQueue(strprintf("%s %s",
1249  toString(CAST_U64(change)).c_str(),
1250  // TRANSLATORS: get xp message
1251  _("xp")),
1253  }
1254 }
1255 
1256 void LocalPlayer::addHomunXpMessage(const int change)
1257 {
1258  if (change != 0 && mMessages.size() < 20)
1259  {
1260  addMessageToQueue(strprintf("%s %d %s",
1261  // TRANSLATORS: get homunculus xp message
1262  _("Homun"),
1263  change,
1264  // TRANSLATORS: get xp message
1265  _("xp")),
1267  }
1268 }
1269 
1270 void LocalPlayer::addHpMessage(const int change)
1271 {
1272  if (change != 0 && mMessages.size() < 20)
1273  {
1274  // TRANSLATORS: get hp message
1275  addMessageToQueue(strprintf("%d %s", change, _("hp")),
1277  }
1278 }
1279 
1280 void LocalPlayer::addSpMessage(const int change)
1281 {
1282  if (change != 0 && mMessages.size() < 20)
1283  {
1284  // TRANSLATORS: get hp message
1285  addMessageToQueue(strprintf("%d %s", change, _("mana")),
1287  }
1288 }
1289 
1291  const int64_t oldVal,
1292  const int64_t newVal)
1293 {
1294  PRAGMA45(GCC diagnostic push)
1295  PRAGMA45(GCC diagnostic ignored "-Wswitch-enum")
1296  switch (id)
1297  {
1299  {
1301  break;
1302  if (oldVal > newVal)
1303  break;
1304 
1305  const int change = CAST_S32(newVal - oldVal);
1306  addXpMessage(change);
1307  break;
1308  }
1310  mLevel = CAST_S32(newVal);
1311  break;
1312  case Attributes::PLAYER_HP:
1313  if (oldVal != 0 && newVal == 0)
1315  break;
1317  {
1318  if (!mShowJobExp ||
1320  {
1321  return;
1322  }
1323  if (oldVal > newVal ||
1326  {
1327  return;
1328  }
1329  const int32_t change = CAST_S32(newVal - oldVal);
1330  addJobMessage(change);
1331  break;
1332  }
1333  default:
1334  break;
1335  }
1336  PRAGMA45(GCC diagnostic pop)
1337 }
1338 
1339 void LocalPlayer::move(const int dX, const int dY)
1340 {
1341  mPickUpTarget = nullptr;
1342  setDestination(mX + dX, mY + dY);
1343 }
1344 
1346 {
1347  bool gotPos(false);
1348  Path debugPath;
1349 
1350  size_t limit(0);
1351 
1352  if (dist == -1)
1353  {
1354  dist = settings.moveToTargetType;
1355  if (dist != 0)
1356  {
1357  const bool broken = (Net::getNetworkType() ==
1359  switch (dist)
1360  {
1361  case 10:
1362  dist = mAttackRange;
1363  if (dist == 1 && broken)
1364  dist = 2;
1365  break;
1366  case 11:
1367  dist = mAttackRange - 1;
1368  if (dist < 1)
1369  dist = 1;
1370  if (dist == 1 && broken)
1371  dist = 2;
1372  break;
1373  default:
1374  break;
1375  }
1376  }
1377  }
1378 
1379  if (mTarget != nullptr)
1380  {
1381  if (mMap != nullptr)
1382  {
1383  debugPath = mMap->findPath(
1384  (mPixelX - mapTileSize / 2) / mapTileSize,
1386  mTarget->mX,
1387  mTarget->mY,
1388  getBlockWalkMask(),
1389  0);
1390  }
1391 
1392  const size_t sz = debugPath.size();
1393  if (sz < CAST_SIZE(dist))
1394  return;
1395  limit = CAST_S32(sz) - dist;
1396  gotPos = true;
1397  }
1398  else if ((mNavigateX != 0) || (mNavigateY != 0))
1399  {
1400  debugPath = mNavigatePath;
1401  limit = dist;
1402  gotPos = true;
1403  }
1404 
1405  if (gotPos)
1406  {
1407  if (dist == 0)
1408  {
1409  if (mTarget != nullptr)
1411  }
1412  else
1413  {
1414  Position pos(0, 0);
1415  size_t f = 0;
1416 
1417  for (Path::const_iterator i = debugPath.begin(),
1418  i_fend = debugPath.end();
1419  i != i_fend && f < limit; ++i, f++)
1420  {
1421  pos = (*i);
1422  }
1423  navigateTo(pos.x, pos.y);
1424  }
1425  }
1426  else if ((mLastTargetX != 0) || (mLastTargetY != 0))
1427  {
1429  }
1430 }
1431 
1433 {
1434  mPickUpTarget = nullptr;
1435  if ((mX != mCrossX || mY != mCrossY) && (mCrossX != 0) && (mCrossY != 0))
1436  {
1438  }
1439  else if (mMap != nullptr)
1440  {
1441  const std::map<std::string, Vector>::const_iterator iter =
1442  mHomes.find(mMap->getProperty("_realfilename", std::string()));
1443 
1444  if (iter != mHomes.end())
1445  {
1446  const Vector pos = mHomes[(*iter).first];
1447  if (mX == pos.x && mY == pos.y)
1448  {
1450  CAST_S32(pos.x),
1451  CAST_S32(pos.y),
1452  CAST_S32(mDirection));
1453  }
1454  else
1455  {
1456  navigateTo(CAST_S32(pos.x), CAST_S32(pos.y));
1457  }
1458  }
1459  }
1460 }
1461 
1462 void LocalPlayer::changeEquipmentBeforeAttack(const Being *const target) const
1463 {
1464  if (settings.attackWeaponType == 1
1465  || (target == nullptr)
1466  || (PlayerInfo::getInventory() == nullptr))
1467  {
1468  return;
1469  }
1470 
1471  bool allowSword = false;
1472  const int dx = target->mX - mX;
1473  const int dy = target->mY - mY;
1474  const Item *item = nullptr;
1475 
1476  if (dx * dx + dy * dy > 80)
1477  return;
1478 
1479  if (dx * dx + dy * dy < 8)
1480  allowSword = true;
1481 
1482  const Inventory *const inv = PlayerInfo::getInventory();
1483  if (inv == nullptr)
1484  return;
1485 
1486  // if attack distance for sword
1487  if (allowSword)
1488  {
1489  // searching swords
1490  const WeaponsInfos &swords = WeaponsDB::getSwords();
1491  FOR_EACH (WeaponsInfosIter, it, swords)
1492  {
1493  item = inv->findItem(*it, ItemColor_zero);
1494  if (item != nullptr)
1495  break;
1496  }
1497 
1498  // no swords
1499  if (item == nullptr)
1500  return;
1501 
1502  // if sword not equiped
1503  if (item->isEquipped() == Equipped_false)
1505 
1506  // if need equip shield too
1507  if (settings.attackWeaponType == 3)
1508  {
1509  // searching shield
1510  const WeaponsInfos &shields = WeaponsDB::getShields();
1511  FOR_EACH (WeaponsInfosIter, it, shields)
1512  {
1513  item = inv->findItem(*it, ItemColor_zero);
1514  if (item != nullptr)
1515  break;
1516  }
1517  if ((item != nullptr) && item->isEquipped() == Equipped_false)
1519  }
1520  }
1521  // big distance. allowed only bow
1522  else
1523  {
1524  // searching bow
1525  const WeaponsInfos &bows = WeaponsDB::getBows();
1526  FOR_EACH (WeaponsInfosIter, it, bows)
1527  {
1528  item = inv->findItem(*it, ItemColor_zero);
1529  if (item != nullptr)
1530  break;
1531  }
1532 
1533  // no bow
1534  if (item == nullptr)
1535  return;
1536 
1537  if (item->isEquipped() == Equipped_false)
1539  }
1540 }
1541 
1543  const int maxCost)
1544 {
1545  if ((being == nullptr) || (mMap == nullptr))
1546  return false;
1547 
1548  if (being->getReachable() == Reachable::REACH_NO)
1549  return false;
1550 
1551  if (being->mX == mX &&
1552  being->mY == mY)
1553  {
1554  being->setDistance(0);
1556  return true;
1557  }
1558  else if (being->mX - 1 <= mX &&
1559  being->mX + 1 >= mX &&
1560  being->mY - 1 <= mY &&
1561  being->mY + 1 >= mY)
1562  {
1563  being->setDistance(1);
1565  return true;
1566  }
1567 
1568  const Path debugPath = mMap->findPath(
1569  (mPixelX - mapTileSize / 2) / mapTileSize,
1571  being->mX,
1572  being->mY,
1573  getBlockWalkMask(),
1574  maxCost);
1575 
1576  being->setDistance(CAST_S32(debugPath.size()));
1577  if (!debugPath.empty())
1578  {
1580  return true;
1581  }
1583  return false;
1584 }
1585 
1586 bool LocalPlayer::isReachable(const int x, const int y,
1587  const bool allowCollision) const
1588 {
1589  const WalkLayer *const walk = mMap->getWalkLayer();
1590  if (walk == nullptr)
1591  return false;
1592  int num = walk->getDataAt(x, y);
1593  if (allowCollision && num < 0)
1594  num = -num;
1595 
1596  return walk->getDataAt(mX, mY) == num;
1597 }
1598 
1599 bool LocalPlayer::pickUpItems(int pickUpType)
1600 {
1601  if (actorManager == nullptr)
1602  return false;
1603 
1604  bool status = false;
1605  int x = mX;
1606  int y = mY;
1607 
1608  // first pick up item on player position
1609  FloorItem *item =
1610  actorManager->findItem(x, y);
1611  if (item != nullptr)
1612  status = pickUp(item);
1613 
1614  if (pickUpType == 0)
1615  pickUpType = settings.pickUpType;
1616 
1617  if (pickUpType == 0)
1618  return status;
1619 
1620  int x1;
1621  int y1;
1622  int x2;
1623  int y2;
1624  switch (pickUpType)
1625  {
1626  case 1:
1627  switch (mDirection)
1628  {
1629  case BeingDirection::UP : --y; break;
1630  case BeingDirection::DOWN : ++y; break;
1631  case BeingDirection::LEFT : --x; break;
1632  case BeingDirection::RIGHT: ++x; break;
1633  default: break;
1634  }
1635  item = actorManager->findItem(x, y);
1636  if (item != nullptr)
1637  status = pickUp(item);
1638  break;
1639  case 2:
1640  switch (mDirection)
1641  {
1642  case BeingDirection::UP:
1643  x1 = x - 1; y1 = y - 1; x2 = x + 1; y2 = y; break;
1644  case BeingDirection::DOWN:
1645  x1 = x - 1; y1 = y; x2 = x + 1; y2 = y + 1; break;
1646  case BeingDirection::LEFT:
1647  x1 = x - 1; y1 = y - 1; x2 = x; y2 = y + 1; break;
1648  case BeingDirection::RIGHT:
1649  x1 = x; y1 = y - 1; x2 = x + 1; y2 = y + 1; break;
1650  default:
1651  x1 = x; x2 = x; y1 = y; y2 = y; break;
1652  }
1653  if (actorManager->pickUpAll(x1, y1, x2, y2, false))
1654  status = true;
1655  break;
1656  case 3:
1657  if (actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1, false))
1658  status = true;
1659  break;
1660 
1661  case 4:
1662  if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1, false))
1663  {
1664  if (actorManager->pickUpNearest(x, y, 4))
1665  status = true;
1666  }
1667  else
1668  {
1669  status = true;
1670  }
1671  break;
1672 
1673  case 5:
1674  if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1, false))
1675  {
1676  if (actorManager->pickUpNearest(x, y, 8))
1677  status = true;
1678  }
1679  else
1680  {
1681  status = true;
1682  }
1683  break;
1684 
1685  case 6:
1686  if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1, false))
1687  {
1688  if (actorManager->pickUpNearest(x, y, 90))
1689  status = true;
1690  }
1691  else
1692  {
1693  status = true;
1694  }
1695  break;
1696 
1697  default:
1698  break;
1699  }
1700  return status;
1701 }
1702 
1703 
1704 void LocalPlayer::moveByDirection(const unsigned char dir)
1705 {
1706  int dx = 0;
1707  int dy = 0;
1708  if ((dir & BeingDirection::UP) != 0)
1709  dy--;
1710  if ((dir & BeingDirection::DOWN) != 0)
1711  dy++;
1712  if ((dir & BeingDirection::LEFT) != 0)
1713  dx--;
1714  if ((dir & BeingDirection::RIGHT) != 0)
1715  dx++;
1716  move(dx, dy);
1717 }
1718 
1719 void LocalPlayer::specialMove(const unsigned char direction)
1720 {
1721  if ((direction != 0U) && ((mNavigateX != 0) || (mNavigateY != 0)))
1722  navigateClean();
1723 
1724  if ((direction != 0U) && (settings.moveType >= 2
1725  && settings.moveType <= 4))
1726  {
1727  if (mAction == BeingAction::MOVE)
1728  return;
1729 
1730  unsigned int max;
1731 
1732  if (settings.moveType == 2)
1733  max = 5;
1734  else if (settings.moveType == 4)
1735  max = 1;
1736  else
1737  max = 3;
1738 
1739  if (getMoveState() < max)
1740  {
1741  moveByDirection(direction);
1742  mMoveState ++;
1743  }
1744  else
1745  {
1746  mMoveState = 0;
1747  crazyMoves->crazyMove();
1748  }
1749  }
1750  else
1751  {
1752  setWalkingDir(direction);
1753  }
1754 }
1755 
1756 #ifdef TMWA_SUPPORT
1758 {
1760  return;
1761  if (chatWindow == nullptr ||
1762  !isAlive() ||
1764  {
1765  return;
1766  }
1767 
1768  switch (settings.magicAttackType)
1769  {
1770  // flar W00
1771  case 0:
1772  tryMagic("#flar", 1, 0, 10);
1773  break;
1774  // chiza W01
1775  case 1:
1776  tryMagic("#chiza", 1, 0, 9);
1777  break;
1778  // ingrav W10
1779  case 2:
1780  tryMagic("#ingrav", 2, 2, 20);
1781  break;
1782  // frillyar W11
1783  case 3:
1784  tryMagic("#frillyar", 2, 2, 25);
1785  break;
1786  // upmarmu W12
1787  case 4:
1788  tryMagic("#upmarmu", 2, 2, 20);
1789  break;
1790  default:
1791  break;
1792  }
1793 }
1794 
1795 void LocalPlayer::tryMagic(const std::string &spell, const int baseMagic,
1796  const int schoolMagic, const int mana)
1797 {
1798  if (chatWindow == nullptr)
1799  return;
1800 
1801  if (PlayerInfo::getSkillLevel(340) >= baseMagic
1802  && PlayerInfo::getSkillLevel(342) >= schoolMagic)
1803  {
1805  {
1807  return;
1808 
1809  chatWindow->localChatInput(spell);
1810  }
1811  }
1812 }
1813 #endif // TMWA_SUPPORT
1814 
1816 {
1817  std::string buf;
1818  std::stringstream ss(serverConfig.getValue("playerHomes", ""));
1819 
1820  while (ss >> buf)
1821  {
1822  Vector pos;
1823  ss >> pos.x;
1824  ss >> pos.y;
1825  mHomes[buf] = pos;
1826  }
1827 }
1828 
1829 void LocalPlayer::setMap(Map *const map)
1830 {
1831  BLOCK_START("LocalPlayer::setMap")
1832  if (map != nullptr)
1833  {
1834  if (socialWindow != nullptr)
1836  }
1837  navigateClean();
1838  mCrossX = 0;
1839  mCrossY = 0;
1840 
1841  Being::setMap(map);
1843  BLOCK_END("LocalPlayer::setMap")
1844 }
1845 
1847 {
1848  if ((mMap == nullptr) || (socialWindow == nullptr))
1849  return;
1850 
1851  SpecialLayer *const specialLayer = mMap->getSpecialLayer();
1852 
1853  if (specialLayer == nullptr)
1854  return;
1855 
1856  const std::string key = mMap->getProperty("_realfilename", std::string());
1857  Vector pos = mHomes[key];
1858 
1859  if (mAction == BeingAction::SIT)
1860  {
1861  const std::map<std::string, Vector>::const_iterator
1862  iter = mHomes.find(key);
1863 
1864  if (iter != mHomes.end())
1865  {
1867  CAST_S32(pos.y));
1868  }
1869 
1870  if (iter != mHomes.end() && mX == CAST_S32(pos.x)
1871  && mY == CAST_S32(pos.y))
1872  {
1873  mMap->updatePortalTile("",
1875  CAST_S32(pos.x),
1876  CAST_S32(pos.y),
1877  true);
1878 
1879  mHomes.erase(key);
1881  CAST_S32(pos.y));
1882  }
1883  else
1884  {
1885  if (iter != mHomes.end())
1886  {
1887  specialLayer->setTile(CAST_S32(pos.x),
1888  CAST_S32(pos.y), MapItemType::EMPTY);
1889  specialLayer->updateCache();
1890  }
1891 
1892  pos.x = static_cast<float>(mX);
1893  pos.y = static_cast<float>(mY);
1894  mHomes[key] = pos;
1895  mMap->updatePortalTile("home",
1897  mX,
1898  mY,
1899  true);
1901  }
1902  MapItem *const mapItem = specialLayer->getTile(mX, mY);
1903  if (mapItem != nullptr)
1904  {
1905  const int idx = socialWindow->getPortalIndex(mX, mY);
1907  OutfitWindow::keyName(idx)));
1908  }
1909  saveHomes();
1910  }
1911  else
1912  {
1913  MapItem *mapItem = specialLayer->getTile(mX, mY);
1914  int type = 0;
1915 
1916  const std::map<std::string, Vector>::iterator iter = mHomes.find(key);
1917  if (iter != mHomes.end() && mX == pos.x && mY == pos.y)
1918  {
1919  mHomes.erase(key);
1920  saveHomes();
1921  }
1922 
1923  if ((mapItem == nullptr) || mapItem->getType() == MapItemType::EMPTY)
1924  {
1925  if ((mDirection & BeingDirection::UP) != 0)
1926  type = MapItemType::ARROW_UP;
1927  else if ((mDirection & BeingDirection::LEFT) != 0)
1928  type = MapItemType::ARROW_LEFT;
1929  else if ((mDirection & BeingDirection::DOWN) != 0)
1930  type = MapItemType::ARROW_DOWN;
1931  else if ((mDirection & BeingDirection::RIGHT) != 0)
1932  type = MapItemType::ARROW_RIGHT;
1933  }
1934  else
1935  {
1936  type = MapItemType::EMPTY;
1937  }
1938  mMap->updatePortalTile("",
1939  type,
1940  mX,
1941  mY,
1942  true);
1943 
1944  if (type != MapItemType::EMPTY)
1945  {
1947  mapItem = specialLayer->getTile(mX, mY);
1948  if (mapItem != nullptr)
1949  {
1950  const int idx = socialWindow->getPortalIndex(mX, mY);
1952  OutfitWindow::keyName(idx)));
1953  }
1954  }
1955  else
1956  {
1957  specialLayer->setTile(mX, mY, MapItemType::EMPTY);
1958  specialLayer->updateCache();
1960  }
1961  }
1962 }
1963 
1965 {
1966  std::stringstream ss;
1967 
1968  for (std::map<std::string, Vector>::const_iterator iter = mHomes.begin(),
1969  iter_fend = mHomes.end();
1970  iter != iter_fend;
1971  ++iter)
1972  {
1973  const Vector &pos = (*iter).second;
1974 
1975  if (iter != mHomes.begin())
1976  ss << " ";
1977  ss << (*iter).first << " " << pos.x << " " << pos.y;
1978  }
1979 
1980  serverConfig.setValue("playerHomes", ss.str());
1981 }
1982 
1984 {
1985  const int time = tick_time;
1986  if (mWaitPing == true && mPingSendTick != 0)
1987  {
1988  if (time >= mPingSendTick && (time - mPingSendTick) > 1000)
1989  return;
1990  }
1991 
1992  mPingSendTick = time;
1993  mWaitPing = true;
1995 }
1996 
1997 std::string LocalPlayer::getPingTime() const
1998 {
1999  std::string str;
2000  if (!mWaitPing)
2001  {
2002  if (mPingTime == 0)
2003  str = "?";
2004  else
2005  str = toString(CAST_S32(mPingTime));
2006  }
2007  else
2008  {
2009  time_t time = tick_time;
2010  if (time > mPingSendTick)
2011  time -= mPingSendTick;
2012  else
2013  time += MAX_TICK_VALUE - mPingSendTick;
2014  if (time <= mPingTime)
2015  time = mPingTime;
2016  if (mPingTime != time)
2017  str = strprintf("%d (%d)", CAST_S32(mPingTime), CAST_S32(time));
2018  else
2019  str = toString(CAST_S32(time));
2020  }
2021  return str;
2022 }
2023 
2025 {
2026  if (mWaitPing == true && mPingSendTick > 0)
2027  {
2028  mWaitPing = false;
2029  const int time = tick_time;
2030  if (time < mPingSendTick)
2031  {
2032  mPingSendTick = 0;
2033  mPingTime = 0;
2034  }
2035  else
2036  {
2037  mPingTime = (time - mPingSendTick) * 10;
2038  }
2039  }
2040 }
2041 
2043 {
2044  if (mPingSendTick == 0 || tick_time < mPingSendTick
2045  || (tick_time - mPingSendTick) > 200)
2046  {
2047  pingRequest();
2048  }
2049 }
2050 
2051 
2052 void LocalPlayer::setAway(const std::string &message) const
2053 {
2054  setAfkMessage(message);
2056  updateStatus();
2057 }
2058 
2059 void LocalPlayer::setAfkMessage(std::string message)
2060 {
2061  if (!message.empty())
2062  {
2063  if (message.size() > 4 && message.substr(0, 4) == "/me ")
2064  {
2065  message = message.substr(4);
2066  config.setValue("afkFormat", 1);
2067  }
2068  else
2069  {
2070  config.setValue("afkFormat", 0);
2071  }
2072  serverConfig.setValue("afkMessage", message);
2073  }
2074 }
2075 
2076 void LocalPlayer::setPseudoAway(const std::string &message)
2077 {
2078  setAfkMessage(message);
2080 }
2081 
2082 void LocalPlayer::afkRespond(ChatTab *const tab, const std::string &nick)
2083 {
2084  if (settings.awayMode)
2085  {
2086  const time_t time = cur_time;
2087  if (mAfkTime == 0 || time < mAfkTime
2088  || time - mAfkTime > awayLimitTimer)
2089  {
2090  std::string str(serverConfig.getValue("afkMessage",
2091  "I am away from keyboard."));
2092  if (str.find("'NAME'") != std::string::npos)
2093  replaceAll(str, "'NAME'", nick);
2094 
2095  std::string msg("*AFK*: " + str);
2096 
2097  if (config.getIntValue("afkFormat") == 1)
2098  msg = "*" + msg + "*";
2099 
2100  if (tab == nullptr)
2101  {
2102  chatHandler->privateMessage(nick, msg);
2103  if (localChatTab != nullptr)
2104  {
2105  localChatTab->chatLog(std::string(mName).append(
2106  " : ").append(msg),
2110  }
2111  }
2112  else
2113  {
2114  if (tab->getNoAway())
2115  return;
2116  chatHandler->privateMessage(nick, msg);
2117  tab->chatLog(mName, msg);
2118  }
2119  mAfkTime = time;
2120  }
2121  }
2122 }
2123 
2124 bool LocalPlayer::navigateTo(const int x, const int y)
2125 {
2126  if (mMap == nullptr)
2127  return false;
2128 
2129  SpecialLayer *const tmpLayer = mMap->getTempLayer();
2130  if (tmpLayer == nullptr)
2131  return false;
2132 
2133  mShowNavigePath = true;
2134  mOldX = mPixelX;
2135  mOldY = mPixelY;
2136  mOldTileX = mX;
2137  mOldTileY = mY;
2138  mNavigateX = x;
2139  mNavigateY = y;
2141 
2143  (mPixelX - mapTileSize / 2) / mapTileSize,
2145  x,
2146  y,
2147  getBlockWalkMask(),
2148  0);
2149 
2150  if (mDrawPath)
2151  tmpLayer->addRoad(mNavigatePath);
2152  return !mNavigatePath.empty();
2153 }
2154 
2156 {
2157  if (mMap == nullptr)
2158  return;
2159 
2160  mShowNavigePath = false;
2161  mOldX = 0;
2162  mOldY = 0;
2163  mOldTileX = 0;
2164  mOldTileY = 0;
2165  mNavigateX = 0;
2166  mNavigateY = 0;
2168 
2169  mNavigatePath.clear();
2170 
2171  SpecialLayer *const tmpLayer = mMap->getTempLayer();
2172  if (tmpLayer == nullptr)
2173  return;
2174 
2175  tmpLayer->clean();
2176 }
2177 
2179 {
2180  if (mMap != nullptr)
2181  {
2182  std::string str = mMap->getObjectData(mX, mY, MapItemType::MUSIC);
2183  if (str.empty())
2184  str = mMap->getMusicFile();
2185  if (str != soundManager.getCurrentMusicFile())
2186  {
2187  if (str.empty())
2188  soundManager.fadeOutMusic(1000);
2189  else
2190  soundManager.fadeOutAndPlayMusic(str, 1000);
2191  }
2192  }
2193 }
2194 
2196 {
2198 
2199  // probably map not loaded.
2200  if ((mPixelX == 0) || (mPixelY == 0))
2201  return;
2202 
2203  if (mX != mOldTileX || mY != mOldTileY)
2204  {
2205  if (socialWindow != nullptr)
2208  updateMusic();
2209  }
2210 
2211  if ((mMap != nullptr) && (mX != mOldTileX || mY != mOldTileY))
2212  {
2213  SpecialLayer *const tmpLayer = mMap->getTempLayer();
2214  if (tmpLayer == nullptr)
2215  return;
2216 
2217  const int x = (mPixelX - mapTileSize / 2) / mapTileSize;
2218  const int y = (mPixelY - mapTileSize) / mapTileSize;
2219  if (mNavigateId != BeingId_zero)
2220  {
2221  if (actorManager == nullptr)
2222  {
2223  navigateClean();
2224  return;
2225  }
2226 
2227  const Being *const being = actorManager
2229  if (being == nullptr)
2230  {
2231  navigateClean();
2232  return;
2233  }
2234  mNavigateX = being->mX;
2235  mNavigateY = being->mY;
2236  }
2237 
2238  if (mNavigateX == x && mNavigateY == y)
2239  {
2240  navigateClean();
2241  return;
2242  }
2243  for (Path::const_iterator i = mNavigatePath.begin(),
2244  i_fend = mNavigatePath.end();
2245  i != i_fend;
2246  ++i)
2247  {
2248  if ((*i).x == mX && (*i).y == mY)
2249  {
2250  mNavigatePath.pop_front();
2251  fixPos();
2252  break;
2253  }
2254  }
2255  if (mDrawPath && mShowNavigePath)
2256  {
2257  tmpLayer->clean();
2258  tmpLayer->addRoad(mNavigatePath);
2259  }
2260  }
2261  mOldX = mPixelX;
2262  mOldY = mPixelY;
2263  mOldTileX = mX;
2264  mOldTileY = mY;
2265 }
2266 
2268 {
2269 /*
2270  if (mKeepAttacking)
2271  {
2272  if (mTarget && mServerAttack == Keep_true)
2273  {
2274  logger->log("LocalPlayer::targetMoved0");
2275  if (!PacketLimiter::limitPackets(PacketType::PACKET_ATTACK))
2276  return;
2277  logger->log("LocalPlayer::targetMoved");
2278  playerHandler->attack(mTarget->getId(), mServerAttack);
2279  }
2280  }
2281 */
2282 }
2283 
2284 int LocalPlayer::getPathLength(const Being *const being) const
2285 {
2286  if ((mMap == nullptr) || (being == nullptr))
2287  return 0;
2288 
2289  if (being->mX == mX && being->mY == mY)
2290  return 0;
2291 
2292  if (being->mX - 1 <= mX &&
2293  being->mX + 1 >= mX &&
2294  being->mY - 1 <= mY &&
2295  being->mY + 1 >= mY)
2296  {
2297  return 1;
2298  }
2299 
2301  {
2302  const Path debugPath = mMap->findPath(
2303  (mPixelX - mapTileSize / 2) / mapTileSize,
2305  being->mX,
2306  being->mY,
2307  getBlockWalkMask(),
2308  0);
2309  return CAST_S32(debugPath.size());
2310  }
2311 
2312  const int dx = CAST_S32(abs(being->mX - mX));
2313  const int dy = CAST_S32(abs(being->mY - mY));
2314  if (dx > dy)
2315  return dx;
2316  return dy;
2317 }
2318 
2320 {
2321  int range = getAttackRange();
2322  if (range == 1)
2323  range = 2;
2324  return range;
2325 }
2326 
2327 void LocalPlayer::attack2(Being *const target,
2328  const bool keep,
2329  const bool dontChangeEquipment)
2330 {
2331  if (!dontChangeEquipment && (target != nullptr))
2333 
2334  const bool broken = (Net::getNetworkType() == ServerType::TMWATHENA);
2335 
2336  // probably need cache getPathLength(target)
2337  if ((target == nullptr ||
2338  settings.attackType == 0 ||
2339  settings.attackType == 3) ||
2340  (withinAttackRange(target, broken, broken ? 1 : 0) &&
2341  getPathLength(target) <= getAttackRange2()))
2342  {
2343  attack(target, keep, false);
2344  if (settings.attackType == 2)
2345  {
2346  if (target == nullptr)
2347  {
2348  if (pickUpItems(0))
2349  return;
2350  }
2351  else
2352  {
2353  pickUpItems(3);
2354  }
2355  }
2356  }
2357  else if (mPickUpTarget == nullptr)
2358  {
2359  if (settings.attackType == 2)
2360  {
2361  if (pickUpItems(0))
2362  return;
2363  }
2364  setTarget(target);
2365  if (target->getType() != ActorType::Npc)
2366  {
2367  mKeepAttacking = true;
2368  moveToTarget(-1);
2369  }
2370  }
2371 }
2372 
2373 void LocalPlayer::setFollow(const std::string &player)
2374 {
2375  mPlayerFollowed = player;
2376  if (!mPlayerFollowed.empty())
2377  {
2378  // TRANSLATORS: follow command message
2379  std::string msg = strprintf(_("Follow: %s"), player.c_str());
2380  debugMsg(msg)
2381  }
2382  else
2383  {
2384  // TRANSLATORS: follow command message
2385  debugMsg(_("Follow canceled"))
2386  }
2387 }
2388 
2389 void LocalPlayer::setImitate(const std::string &player)
2390 {
2391  mPlayerImitated = player;
2392  if (!mPlayerImitated.empty())
2393  {
2394  // TRANSLATORS: imitate command message
2395  std::string msg = strprintf(_("Imitation: %s"), player.c_str());
2396  debugMsg(msg)
2397  }
2398  else
2399  {
2400  // TRANSLATORS: imitate command message
2401  debugMsg(_("Imitation canceled"))
2402  }
2403 }
2404 
2406 {
2407  if (!mPlayerFollowed.empty())
2408  {
2409  // TRANSLATORS: cancel follow message
2410  debugMsg(_("Follow canceled"))
2411  }
2412  if (!mPlayerImitated.empty())
2413  {
2414  // TRANSLATORS: cancel follow message
2415  debugMsg(_("Imitation canceled"))
2416  }
2417  mPlayerFollowed.clear();
2418  mPlayerImitated.clear();
2419 }
2420 
2421 void LocalPlayer::imitateEmote(const Being *const being,
2422  const unsigned char action) const
2423 {
2424  if (being == nullptr)
2425  return;
2426 
2427  std::string player_imitated = getImitate();
2428  if (!player_imitated.empty() && being->mName == player_imitated)
2429  emote(action);
2430 }
2431 
2432 void LocalPlayer::imitateAction(const Being *const being,
2433  const BeingActionT &action)
2434 {
2435  if (being == nullptr)
2436  return;
2437 
2438  if (!mPlayerImitated.empty() && being->mName == mPlayerImitated)
2439  {
2440  setAction(action, 0);
2441  playerHandler->changeAction(action);
2442  }
2443 }
2444 
2445 void LocalPlayer::imitateDirection(const Being *const being,
2446  const unsigned char dir)
2447 {
2448  if (being == nullptr)
2449  return;
2450 
2451  if (!mPlayerImitated.empty() && being->mName == mPlayerImitated)
2452  {
2454  return;
2455 
2456  if (settings.followMode == 2)
2457  {
2458  uint8_t dir2 = 0;
2459  if ((dir & BeingDirection::LEFT) != 0)
2460  dir2 |= BeingDirection::RIGHT;
2461  else if ((dir & BeingDirection::RIGHT) != 0)
2462  dir2 |= BeingDirection::LEFT;
2463  if ((dir & BeingDirection::UP) != 0)
2464  dir2 |= BeingDirection::DOWN;
2465  else if ((dir & BeingDirection::DOWN) != 0)
2466  dir2 |= BeingDirection::UP;
2467 
2468  setDirection(dir2);
2469  playerHandler->setDirection(dir2);
2470  }
2471  else
2472  {
2473  setDirection(dir);
2475  }
2476  }
2477 }
2478 
2479 void LocalPlayer::imitateOutfit(const Being *const player,
2480  const int sprite) const
2481 {
2482  if (player == nullptr)
2483  return;
2484 
2485  if (settings.imitationMode == 1 &&
2486  !mPlayerImitated.empty() &&
2487  player->mName == mPlayerImitated)
2488  {
2489  if (sprite < 0 || sprite >= player->getNumberOfLayers())
2490  return;
2491 
2492  const AnimatedSprite *const equipmentSprite
2493  = dynamic_cast<const AnimatedSprite *>(
2494  player->mSprites[sprite]);
2495 
2496  if (equipmentSprite != nullptr)
2497  {
2498 // logger->log("have equipmentSprite");
2499  const Inventory *const inv = PlayerInfo::getInventory();
2500  if (inv == nullptr)
2501  return;
2502 
2503  const std::string &path = equipmentSprite->getIdPath();
2504  if (path.empty())
2505  return;
2506 
2507 // logger->log("idPath: " + path);
2508  const Item *const item = inv->findItemBySprite(path,
2509  player->getGender(), player->getSubType());
2510  if ((item != nullptr) && item->isEquipped() == Equipped_false)
2512  }
2513  else
2514  {
2515 // logger->log("have unequip %d", sprite);
2516  const int equipmentSlot = inventoryHandler
2517  ->convertFromServerSlot(sprite);
2518 // logger->log("equipmentSlot: " + toString(equipmentSlot));
2519  if (equipmentSlot == inventoryHandler->getProjectileSlot())
2520  return;
2521 
2522  const Item *const item = PlayerInfo::getEquipment(equipmentSlot);
2523  if (item != nullptr)
2524  {
2525 // logger->log("unequiping");
2527  }
2528  }
2529  }
2530 }
2531 
2532 void LocalPlayer::followMoveTo(const Being *const being,
2533  const int x, const int y)
2534 {
2535  if ((being != nullptr) &&
2536  !mPlayerFollowed.empty() &&
2537  being->mName == mPlayerFollowed)
2538  {
2539  mPickUpTarget = nullptr;
2540  navigateTo(x, y);
2541  }
2542 }
2543 
2544 void LocalPlayer::followMoveTo(const Being *const being,
2545  const int x1, const int y1,
2546  const int x2, const int y2)
2547 {
2548  if (being == nullptr)
2549  return;
2550 
2551  mPickUpTarget = nullptr;
2552  if (!mPlayerFollowed.empty() &&
2553  being->mName == mPlayerFollowed)
2554  {
2555  switch (settings.followMode)
2556  {
2557  case 0:
2558  navigateTo(x1, y1);
2559  setNextDest(x2, y2);
2560  break;
2561  case 1:
2562  if (x1 != x2 || y1 != y2)
2563  {
2564  navigateTo(mX + x2 - x1, mY + y2 - y1);
2565  setNextDest(mX + x2 - x1, mY + y2 - y1);
2566  }
2567  break;
2568  case 2:
2569  if (x1 != x2 || y1 != y2)
2570  {
2571  navigateTo(mX + x1 - x2, mY + y1 - y2);
2572  setNextDest(mX + x1 - x2, mY + y1 - y2);
2573  }
2574  break;
2575  case 3:
2576  if (mTarget == nullptr ||
2578  {
2579  if (actorManager != nullptr)
2580  {
2581  Being *const b = actorManager->findBeingByName(
2583  setTarget(b);
2584  }
2585  }
2586  moveToTarget(-1);
2587  setNextDest(x2, y2);
2588  break;
2589  default:
2590  break;
2591  }
2592  }
2593 }
2594 
2595 void LocalPlayer::setNextDest(const int x, const int y)
2596 {
2597  mNextDestX = x;
2598  mNextDestY = y;
2599 }
2600 
2602 {
2603  if (mIsServerBuggy)
2604  {
2605  if (mLastAction != -1)
2606  return false;
2608  }
2609  return true;
2610 }
2611 
2613 {
2614  if ((mCrossX == 0) && (mCrossY == 0))
2615  return;
2616 
2617  const int dx = (mX >= mCrossX) ? mX - mCrossX : mCrossX - mX;
2618  const int dy = (mY >= mCrossY) ? mY - mCrossY : mCrossY - mY;
2619  const int dist = dx > dy ? dx : dy;
2620  const time_t time = cur_time;
2621 
2622 #ifdef TMWA_SUPPORT
2623  int maxDist;
2624  if (mSyncPlayerMove)
2625  {
2626  maxDist = mSyncPlayerMoveDistance;
2627  }
2628  else
2629  {
2631  maxDist = 30;
2632  else
2633  maxDist = 10;
2634  }
2635 #else
2636  const int maxDist = mSyncPlayerMove ? mSyncPlayerMoveDistance : 10;
2637 #endif
2638 
2639  if (dist > maxDist)
2640  {
2641  mActivityTime = time;
2642 #ifdef ENABLEDEBUGLOG
2643  logger->dlog(strprintf("Fix position from (%d,%d) to (%d,%d)",
2644  mX, mY,
2645  mCrossX, mCrossY));
2646 #endif
2648 /*
2649  if (mNavigateX != 0 || mNavigateY != 0)
2650  {
2651 #ifdef ENABLEDEBUGLOG
2652  logger->dlog(strprintf("Renavigate to (%d,%d)",
2653  mNavigateX, mNavigateY));
2654 #endif
2655  navigateTo(mNavigateX, mNavigateY);
2656  }
2657 */
2658 // alternative way to fix, move to real position
2659 // setDestination(mCrossX, mCrossY);
2660  }
2661 }
2662 
2663 void LocalPlayer::setTileCoords(const int x, const int y) restrict2
2664 {
2666  mCrossX = x;
2667  mCrossY = y;
2668 }
2669 
2670 void LocalPlayer::setRealPos(const int x, const int y)
2671 {
2672  if (mMap == nullptr)
2673  return;
2674 
2675  SpecialLayer *const layer = mMap->getTempLayer();
2676  if (layer != nullptr)
2677  {
2678  bool cacheUpdated(false);
2679  if (((mCrossX != 0) || (mCrossY != 0)) &&
2680  (layer->getTile(mCrossX, mCrossY) != nullptr) &&
2682  {
2684  layer->updateCache();
2685  cacheUpdated = true;
2686  }
2687 
2688  if (mShowServerPos)
2689  {
2690  const MapItem *const mapItem = layer->getTile(x, y);
2691 
2692  if (mapItem == nullptr ||
2693  mapItem->getType() == MapItemType::EMPTY)
2694  {
2695  if (mX != x && mY != y)
2696  {
2697  layer->setTile(x, y, MapItemType::CROSS);
2698  if (cacheUpdated == false)
2699  layer->updateCache();
2700  }
2701  }
2702  }
2703 
2704  if (mCrossX != x || mCrossY != y)
2705  {
2706  mCrossX = x;
2707  mCrossY = y;
2708  // +++ possible configuration option
2709  fixPos();
2710  }
2711  }
2712  if (mMap->isCustom())
2713  mMap->setWalk(x, y);
2714 }
2715 
2717 {
2718  if ((mMap == nullptr) || (mTarget == nullptr))
2719  return;
2720 
2721  if (settings.moveToTargetType == 11 || (settings.attackType == 0U)
2722  || !config.getBoolValue("autofixPos"))
2723  {
2724  return;
2725  }
2726 
2727  const Path debugPath = mMap->findPath(
2728  (mPixelX - mapTileSize / 2) / mapTileSize,
2730  mTarget->mX,
2731  mTarget->mY,
2732  getBlockWalkMask(),
2733  0);
2734 
2735  if (!debugPath.empty())
2736  {
2737  const Path::const_iterator i = debugPath.begin();
2738  setDestination((*i).x, (*i).y);
2739  }
2740 }
2741 
2743 {
2744  navigateClean();
2745 }
2746 
2748 {
2750 }
2751 
2753 {
2754  if (mMap != nullptr)
2755  {
2756  const std::map<std::string, Vector>::const_iterator iter =
2757  mHomes.find(mMap->getProperty("_realfilename", std::string()));
2758 
2759  if (iter != mHomes.end())
2760  {
2761  const Vector &pos = mHomes[(*iter).first];
2762  if ((pos.x != 0.0F) && (pos.y != 0.0F))
2763  {
2765  CAST_S32(pos.x), CAST_S32(pos.y));
2766  }
2767  }
2768  }
2769 }
2770 
2772  const int y A_UNUSED)
2773 {
2774  fixPos();
2775 }
2776 
2777 void LocalPlayer::waitFor(const std::string &nick)
2778 {
2779  mWaitFor = nick;
2780 }
2781 
2783 {
2784  if (being == nullptr)
2785  return;
2786 
2787  const std::string &nick = being->mName;
2788  if (being->getType() == ActorType::Player)
2789  {
2790  const Guild *const guild = getGuild();
2791  if (guild != nullptr)
2792  {
2793  const GuildMember *const gm = guild->getMember(nick);
2794  if (gm != nullptr)
2795  {
2796  const int level = gm->getLevel();
2797  if (level > 1 && being->getLevel() != level)
2798  {
2799  being->setLevel(level);
2800  being->updateName();
2801  }
2802  }
2803  }
2804  if (chatWindow != nullptr)
2805  {
2806  WhisperTab *const tab = chatWindow->getWhisperTab(nick);
2807  if (tab != nullptr)
2808  tab->setWhisperTabColors();
2809  }
2810  }
2811 
2812  if (!mWaitFor.empty() && mWaitFor == nick)
2813  {
2814  // TRANSLATORS: wait player/monster message
2815  debugMsg(strprintf(_("You see %s"), mWaitFor.c_str()))
2817  mWaitFor.clear();
2818  }
2819 }
2820 
2821 unsigned char LocalPlayer::getBlockWalkMask() const
2822 {
2823  // for now blocking all types of collisions
2824  return BlockMask::WALL |
2825  BlockMask::AIR |
2828 }
2829 
2831 {
2832  if (mMap == nullptr)
2833  return;
2834 
2835  const std::string key = mMap->getProperty("_realfilename", std::string());
2836  const std::map<std::string, Vector>::iterator iter = mHomes.find(key);
2837 
2838  if (iter != mHomes.end())
2839  mHomes.erase(key);
2840 }
2841 
2843 {
2844  mBlockAdvert = true;
2845 }
2846 
2848 {
2849  if (target == nullptr)
2850  return false;
2851 
2852  switch (settings.pvpAttackType)
2853  {
2854  case 0:
2855  return true;
2856  case 1:
2857  return !(playerRelations.getRelation(target->mName)
2858  == Relation::FRIEND);
2859  case 2:
2860  return playerRelations.checkBadRelation(target->mName);
2861  default:
2862  case 3:
2863  return false;
2864  }
2865 }
2866 
2868 {
2870  {
2871  uint8_t status = 0;
2873  {
2874  if (mTradebot &&
2875  shopWindow != nullptr &&
2876  !shopWindow->isShopEmpty())
2877  {
2878  status |= BeingFlag::SHOP;
2879  }
2880  }
2882  status |= BeingFlag::AWAY;
2883 
2884  if (mInactive)
2885  status |= BeingFlag::INACTIVE;
2886 
2887  playerHandler->updateStatus(status);
2888  }
2889 }
2890 
2891 void LocalPlayer::setTestParticle(const std::string &fileName,
2892  const bool updateHash)
2893 {
2896  if (mTestParticle != nullptr)
2897  {
2899  mTestParticle = nullptr;
2900  }
2901  if (!fileName.empty())
2902  {
2905  if (updateHash)
2907  }
2908 }
2909 
2911 {
2912  if (mAction != BeingAction::DEAD)
2913  {
2916  }
2917 }
2918 
2920 {
2921  return !mFreezed &&
2925 }
2926 
2927 void LocalPlayer::freezeMoving(const int timeWaitTicks)
2928 {
2929  if (timeWaitTicks <= 0)
2930  return;
2931  const int nextTime = tick_time + timeWaitTicks;
2932  if (mUnfreezeTime < nextTime)
2933  mUnfreezeTime = nextTime;
2934  if (mUnfreezeTime > 0)
2935  mFreezed = true;
2936 }
ActorManager * actorManager
ActorType ::T ActorTypeT
Definition: actortype.h:43
bool AllowSort
Definition: allowsort.h:30
Attributes ::T AttributesT
Definition: attributes.h:118
volatile time_t cur_time
Definition: timer.cpp:58
BeingAction ::T BeingActionT
Definition: beingaction.h:41
Net::BeingHandler * beingHandler
Definition: net.cpp:99
int BeingId
Definition: beingid.h:30
const BeingId BeingId_zero
Definition: beingid.h:30
int BeingTypeId
Definition: beingtypeid.h:30
#define fromBool(val, name)
Definition: booldefines.h:49
#define CAST_S32
Definition: cast.h:30
#define CAST_SIZE
Definition: cast.h:34
#define CAST_U64
Definition: cast.h:33
Net::ChatHandler * chatHandler
Definition: net.cpp:86
ChatTab * localChatTab
Definition: chattab.cpp:62
#define debugMsg(str)
Definition: chattab.h:42
ChatWindow * chatWindow
Definition: chatwindow.cpp:94
bool pickUpAll(const int x1, const int y1, const int x2, const int y2, const bool serverBuggy) const
Being * findNearestLivingBeing(const int x, const int y, int maxTileDist, const ActorTypeT type, const Being *const excluded) const
Being * findBeing(const BeingId id) const
Being * findBeingByName(const std::string &name, const ActorTypeT type) const
FloorItem * findItem(const BeingId id) const
bool checkForPickup(const FloorItem *const item) const
bool pickUpNearest(const int x, const int y, int maxdist) const
ParticleList mChildParticleEffects
Definition: actorsprite.h:245
BeingId getId() const
Definition: actorsprite.h:64
void untarget()
Definition: actorsprite.h:116
void setTargetType(const TargetCursorTypeT type)
void controlCustomParticle(Particle *const particle)
void addActorSpriteListener(ActorSpriteListener *const listener)
virtual void handleStatusEffect(const StatusEffect *const effect, const int32_t effectId, const Enable newStatus, const IsStart start)
int mPixelX
Definition: actor.h:133
Map * mMap
Definition: actor.h:139
int mPixelY
Definition: actor.h:134
std::string getIdPath() const
void setY(const int y)
Definition: avatar.h:135
void setX(const int x)
Definition: avatar.h:129
Definition: being.h:96
bool mIsGM
Definition: being.h:1235
virtual void nextTile()
Definition: being.cpp:1782
virtual void setDirection(const uint8_t direction)
Definition: being.cpp:1690
virtual void setAction(const BeingActionT &action, const int attackId)
Definition: being.cpp:1554
void logic()
Definition: being.cpp:1834
int mX
Definition: being.h:1314
ReachableT getReachable() const
Definition: being.h:610
virtual int getLevel() const
Definition: being.h:604
int mY
Definition: being.h:1315
int getWalkSpeed() const
Definition: being.h:458
virtual void setTileCoords(const int x, const int y)
Definition: being.cpp:5010
const Color * mNameColor
Definition: being.h:1192
int getNumberOfLayers() const
Definition: being.h:377
void updateName()
Definition: being.cpp:3425
const Color * mTextColor
Definition: being.h:1199
BeingTypeId getSubType() const
Definition: being.h:400
void setLevel(const int n)
Definition: being.h:601
friend class LocalPlayer
Definition: being.h:100
std::string mName
Definition: being.h:1180
int mAttackRange
Definition: being.h:1222
virtual void updateCoords()
Definition: being.cpp:2501
void postInit(const BeingTypeId subType, Map *const map)
Definition: being.cpp:289
void recalcSpritesOrder()
Definition: being.cpp:4359
void setShowName(const bool doShowName)
Definition: being.cpp:1166
Vector mDest
Definition: being.h:1201
Guild * getGuild() const
Definition: being.cpp:1280
int mActionTime
Definition: being.h:1213
bool isAlive() const
Definition: being.h:488
void setDistance(const int n)
Definition: being.h:555
bool mInactive
Definition: being.h:1383
void setMap(Map *const map)
Definition: being.cpp:5023
virtual void setGroupId(const int id)
Definition: being.cpp:5587
GenderT getGender() const
Definition: being.h:626
void setReachable(const ReachableT n)
Definition: being.h:607
bool mAdvanced
Definition: being.h:1380
uint8_t mDirection
Definition: being.h:1231
void clearPath()
Definition: being.cpp:554
BeingActionT mAction
Definition: being.h:1229
ActorTypeT getType() const
Definition: being.h:116
int mLevel
Definition: being.h:1220
void setDestination(const int dstX, const int dstY)
Definition: being.cpp:540
Path mPath
Definition: being.h:1197
bool getNoAway() const
Definition: chattab.h:170
void chatLog(std::string line, ChatMsgTypeT own, const IgnoreRecord ignoreRecord, const TryRemoveColors tryRemoveColors)
Definition: chattab.cpp:111
WhisperTab * getWhisperTab(const std::string &nick) const
void localChatInput(const std::string &msg) const
Definition: chatwindow.cpp:691
void showGMTab()
void loadGMCommands()
Definition: chatwindow.cpp:264
std::vector< Sprite * > mSprites
std::string getValue(const std::string &key, const std::string &deflt) const
bool getBoolValue(const std::string &key) const
void addListener(const std::string &key, ConfigListener *const listener)
void setValue(const std::string &key, const std::string &value)
void removeListener(const std::string &key, ConfigListener *const listener)
void removeListeners(ConfigListener *const listener)
int getIntValue(const std::string &key) const
void crazyMove()
Definition: crazymoves.cpp:55
bool getShowMsg() const
Definition: flooritem.h:108
void setShowMsg(const bool n)
Definition: flooritem.h:111
int getTileY() const
Definition: flooritem.h:96
int getTileX() const
Definition: flooritem.h:93
static void changeAwayMode(const bool forward)
Font * getInfoParticleFont() const
Definition: gui.h:185
Definition: guild.h:70
const Item * findItemBySprite(std::string spritePath, const GenderT gender, const BeingTypeId race) const
Definition: inventory.cpp:318
Item * findItem(const int itemId, const ItemColor color) const
Definition: inventory.cpp:94
Definition: item.h:50
Equipped isEquipped() const
Definition: item.h:129
const ItemInfo & getInfo() const
Definition: item.h:171
static std::string getKeyShortString(const std::string &key)
void updateCoords()
void setNextDest(const int x, const int y)
void updateNavigateList()
AwayListener * mAwayListener
Definition: localplayer.h:482
static bool checAttackPermissions(const Being *const target)
bool mTargetDeadPlayers
Definition: localplayer.h:513
void attack2(Being *const target, const bool keep, const bool dontChangeEquipment)
int getLevel() const
void fixAttackTarget()
void moveToTarget(int dist)
bool mShowJobExp
Definition: localplayer.h:524
std::string mTestParticleName
Definition: localplayer.h:504
void freezeMoving(const int timeWaitTicks)
void setTileCoords(const int x, const int y)
void setWalkingDir(const unsigned char dir)
bool pickUpItems(int pickUpType)
void moveToHome()
bool toggleSit() const
void followMoveTo(const Being *const being, const int x, const int y)
void removeHome()
void stopAdvert()
void addHpMessage(const int change)
void setMap(Map *const map)
void failMove(const int x, const int y)
void startWalking(const unsigned char dir)
std::string getPingTime() const
int mUnfreezeTime
Definition: localplayer.h:508
void attributeChanged(const AttributesT id, const int64_t oldVal, const int64_t newVal)
void setTarget(Being *const target)
std::vector< int32_t > mStatusEffectIcons
Definition: localplayer.h:476
bool mWaitPing
Definition: localplayer.h:533
Being * getTarget() const
int getAttackRange() const
bool mAttackMoving
Definition: localplayer.h:522
int mMessageTime
Definition: localplayer.h:481
void imitateDirection(const Being *const being, const unsigned char dir)
void untarget()
void addHomunXpMessage(const int change)
void nextTile()
void waitFor(const std::string &nick)
void setFollow(const std::string &player)
Path mNavigatePath
Definition: localplayer.h:498
FloorItem * mPickUpTarget
Definition: localplayer.h:472
int mLastTargetY
Definition: localplayer.h:460
time_t mAdvertTime
Definition: localplayer.h:502
void attack(Being *const target, const bool keep, const bool dontChangeEquipment)
unsigned char mWalkingDir
Definition: localplayer.h:509
void pingRequest()
void setGroupId(const int id)
bool mKeepAttacking
Definition: localplayer.h:530
void targetMoved() const
void setAction(const BeingActionT &action, const int attackId)
bool mIsServerBuggy
Definition: localplayer.h:519
void imitateEmote(const Being *const being, const unsigned char action) const
static void tryMagic(const std::string &spell, const int baseMagic, const int schoolMagic, const int mana)
bool navigateTo(const int x, const int y)
void setRealPos(const int x, const int y)
int getAttackRange2() const
void stopAttack(const bool keepAttack)
void stopWalking(const bool sendToServer)
time_t mAfkTime
Definition: localplayer.h:487
std::list< MessagePair > mMessages
Definition: localplayer.h:480
OkDialog * mAwayDialog
Definition: localplayer.h:483
bool mGoingToTarget
Definition: localplayer.h:528
bool mEnableAdvert
Definition: localplayer.h:516
void setImitate(const std::string &player)
bool mShowNavigePath
Definition: localplayer.h:534
bool mTradebot
Definition: localplayer.h:517
bool mAttackNext
Definition: localplayer.h:523
void slowLogic()
void optionChanged(const std::string &value)
bool mBlockAdvert
Definition: localplayer.h:512
void setDestination(const int x, const int y)
void setTestParticle(const std::string &fileName, const bool updateHash)
void actorSpriteDestroyed(const ActorSprite &actorSprite)
void move(const int dX, const int dY)
void handleStatusEffect(const StatusEffect *const effect, const int32_t effectId, const Enable newStatus, const IsStart start)
time_t mTestParticleTime
Definition: localplayer.h:505
void moveByDirection(const unsigned char dir)
bool withinAttackRange(const Being *const target, const bool fixDistance, const int addRange) const
unsigned int mMoveState
Definition: localplayer.h:457
void setAway(const std::string &message) const
unsigned long mTestParticleHash
Definition: localplayer.h:506
void addJobMessage(const int64_t change)
const std::string & getImitate() const
Definition: localplayer.h:342
std::string mPlayerImitated
Definition: localplayer.h:468
bool mTargetOnlyReachable
Definition: localplayer.h:518
Being * mTarget
Definition: localplayer.h:464
unsigned int getMoveState() const
Definition: localplayer.h:193
int mPingSendTick
Definition: localplayer.h:485
VisibleName::Type mVisibleNames
Definition: localplayer.h:515
void navigateClean()
void imitateOutfit(const Being *const player, const int sprite) const
bool allowAction()
void afkRespond(ChatTab *const tab, const std::string &nick)
void magicAttack() const
std::pair< std::string, UserColorIdT > MessagePair
Definition: localplayer.h:478
Particle * mTestParticle
Definition: localplayer.h:503
void checkNewName(Being *const being)
std::string mPlayerFollowed
Definition: localplayer.h:467
BeingId mNavigateId
Definition: localplayer.h:491
bool mPathSetByMouse
Definition: localplayer.h:532
void setGotoTarget(Being *const target)
static bool emote(const uint8_t emotion)
std::string mLastHitFrom
Definition: localplayer.h:500
int getPathLength(const Being *const being) const
void addXpMessage(const int64_t change)
time_t mActivityTime
Definition: localplayer.h:488
std::string mWaitFor
Definition: localplayer.h:501
void pingResponse()
void addSpMessage(const int change)
bool mDrawPath
Definition: localplayer.h:521
void changeEquipmentBeforeAttack(const Being *const target) const
void loadHomes()
void specialMove(const unsigned char direction)
Being * setNewTarget(const ActorTypeT type, const AllowSort allowSort)
static void setPseudoAway(const std::string &message)
bool isReachable(Being *const being, const int maxCost)
static void setAfkMessage(std::string message)
time_t mPingTime
Definition: localplayer.h:486
void addMessageToQueue(const std::string &message, const UserColorIdT color)
bool mShowServerPos
Definition: localplayer.h:525
unsigned char getBlockWalkMask() const A_CONST
bool mNextStep
Definition: localplayer.h:526
void saveHomes()
bool canMove() const
bool pickUp(FloorItem *const item)
void updateStatus() const
void pickedUp(const ItemInfo &itemInfo, const int amount, const ItemColor color, const BeingId floorItemId, const PickupT fail)
int mLastTargetX
Definition: localplayer.h:459
void playerDeath()
void imitateAction(const Being *const being, const BeingActionT &action)
void updateMusic() const
void tryPingRequest()
bool mSyncPlayerMove
Definition: localplayer.h:520
int mSyncPlayerMoveDistance
Definition: localplayer.h:507
Keep mServerAttack
Definition: localplayer.h:514
bool updateSit() const
std::map< std::string, Vector > mHomes
Definition: localplayer.h:462
void cancelFollow()
void log1(const char *const log_text)
Definition: logger.cpp:238
void dlog(const std::string &str)
Definition: logger.cpp:148
void setName(const std::string &name)
Definition: mapitem.h:77
int getType() const
Definition: mapitem.h:55
Definition: map.h:75
void addPortalTile(const std::string &name, const int type, const int x, const int y)
Definition: map.cpp:1300
void updatePortalTile(const std::string &name, const int type, const int x, const int y, const bool addNew)
Definition: map.cpp:1313
std::string getObjectData(const unsigned x, const unsigned y, const int type) const
Definition: map.cpp:1393
bool getWalk(const int x, const int y, const unsigned char blockWalkMask) const
Definition: map.cpp:785
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
SpecialLayer * getSpecialLayer() const
Definition: map.h:241
const WalkLayer * getWalkLayer() const
Definition: map.h:347
SpecialLayer * getTempLayer() const
Definition: map.h:238
const std::string getMusicFile() const
Definition: map.cpp:835
bool isCustom() const
Definition: map.h:327
void setWalk(const int x, const int y)
Definition: map.cpp:807
void setIcon(const int index, AnimatedSprite *const sprite)
void eraseIcon(const int index)
virtual void requestNameById(const BeingId id) const =0
virtual void privateMessage(const std::string &recipient, const std::string &text) const =0
virtual int convertFromServerSlot(const int eAthenaSlot) const =0
virtual int getProjectileSlot() const =0
virtual void setDirection(const unsigned char direction) const =0
virtual void stopAttack() const =0
virtual void changeAction(const BeingActionT &action) const =0
virtual void setDestination(const int x, const int y, const int direction) const =0
virtual bool canUseMagic() const =0
virtual void attack(const BeingId id, const Keep keep) const =0
virtual void updateStatus(const uint8_t status) const =0
virtual void emote(const uint8_t emoteId) const =0
virtual bool haveMoveWhileSit() const =0
virtual bool havePlayerStatusUpdate() const =0
virtual bool haveKillerId() const =0
static std::string keyName(const int number)
Particle * addEffect(const std::string &particleEffectFile, const int pixelX, const int pixelY, const int rotation)
Particle * addTextRiseFadeOutEffect(const std::string &text, const int x, const int y, const Color *const color, Font *const font, const bool outline)
void removeLocally(const Particle *const particle)
Definition: party.h:63
static Party * getParty(const int16_t id)
Definition: party.cpp:313
RelationT getRelation(const std::string &name) const
bool checkBadRelation(const std::string &name) const
static void hideBeingPopup()
const std::string getProperty(const std::string &name, const std::string &def) const
Definition: properties.h:59
unsigned int pickUpType
Definition: settings.h:140
bool awayMode
Definition: settings.h:158
unsigned int imitationMode
Definition: settings.h:143
unsigned int magicAttackType
Definition: settings.h:141
unsigned int moveType
Definition: settings.h:133
unsigned int followMode
Definition: settings.h:136
unsigned int attackWeaponType
Definition: settings.h:137
unsigned int pvpAttackType
Definition: settings.h:142
bool pseudoAwayMode
Definition: settings.h:159
unsigned int moveToTargetType
Definition: settings.h:135
unsigned int attackType
Definition: settings.h:138
bool isShopEmpty() const
void updatePortals()
void removePortal(const int x, const int y)
int getPortalIndex(const int x, const int y)
void addPortal(const int x, const int y)
void updateActiveList()
std::string getCurrentMusicFile() const
Definition: soundmanager.h:135
void fadeOutAndPlayMusic(const std::string &fileName, const int ms)
void playGuiSound(const std::string &name)
void volumeRestore() const
void fadeOutMusic(const int ms)
MapItem * getTile(const int x, const int y) const
void setTile(const int x, const int y, MapItem *const item)
void updateCache()
void addRoad(const Path &road)
AnimatedSprite * getIcon() const
void deliverMessage() const
void playSFX() const
void updateLevelLabel()
const Color & getColor(const ThemeColorIdT type, const unsigned int alpha)
Definition: theme.h:136
static unsigned long getFileHash(const std::string &filePath)
const Color & getColor(UserColorIdT type, const unsigned int alpha)
Definition: userpalette.h:160
Definition: vector.h:40
float y
Definition: vector.h:209
float x
Definition: vector.h:209
int getDataAt(const int x, const int y) const
Definition: walklayer.cpp:40
void setWhisperTabColors()
Definition: whispertab.cpp:123
virtual void scheduleDelete()
Definition: window.cpp:831
Configuration config
Configuration serverConfig
static const int mapTileSize
Definition: map.h:27
CrazyMoves * crazyMoves
Definition: crazymoves.cpp:47
#define new
Definition: debug_new.h:147
#define delete2(var)
Definition: delete2.h:25
bool Enable
Definition: enable.h:30
const bool Equipped_false
Definition: equipped.h:30
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define N_(s)
Definition: gettext.h:36
#define _(s)
Definition: gettext.h:35
PRAGMA45(GCC diagnostic push) PRAGMA45(GCC diagnostic ignored "-Wredundant-decls") PRAGMA45(GCC diagnostic pop) class TestMain
Gui * gui
Definition: gui.cpp:111
const bool IgnoreRecord_false
Definition: ignorerecord.h:30
Net::InventoryHandler * inventoryHandler
Definition: net.cpp:89
bool IsStart
Definition: isstart.h:30
uint16_t ItemColor
Definition: itemcolor.h:30
const ItemColor ItemColor_zero
Definition: itemcolor.h:30
const bool Keep_true
Definition: keep.h:30
bool Keep
Definition: keep.h:30
#define restrict2
Definition: localconsts.h:166
#define nullptr
Definition: localconsts.h:45
#define A_UNUSED
Definition: localconsts.h:160
static const int16_t awayLimitTimer
static const int MAX_TICK_VALUE
time_t weightNoticeTime
OkDialog * weightNotice
std::map< int, Guild * >::const_iterator GuildMapCIter
LocalPlayer * localPlayer
Logger * logger
Definition: logger.cpp:89
uint32_t guild
uint32_t party
volatile int tick_time
Definition: timer.cpp:53
MiniStatusWindow * miniStatusWindow
bool msg(InputEvent &event)
Definition: chat.cpp:39
bool itemInfo(InputEvent &event)
Definition: commands.cpp:105
bool gm(InputEvent &event)
Definition: commands.cpp:75
bool info(InputEvent &event)
Definition: commands.cpp:57
@ PLAYER_BASE_LEVEL
Definition: attributes.h:31
@ PLAYER_JOB_EXP
Definition: attributes.h:66
@ PLAYER_WALK_SPEED
Definition: attributes.h:53
@ PLAYER_JOB_EXP_NEEDED
Definition: attributes.h:67
@ INACTIVE
Definition: beingflag.h:31
@ PLAYERWALL
Definition: blockmask.h:36
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
@ FIGHT1_SLOT
Definition: equipslot.h:41
ServerTypeT getNetworkType()
Definition: net.cpp:189
bool limitPackets(const PacketTypeT type)
@ PACKET_ATTACK
Definition: packettype.h:38
@ PACKET_EMOTE
Definition: packettype.h:35
@ PACKET_DIRECTION
Definition: packettype.h:37
@ PACKET_STOPATTACK
Definition: packettype.h:39
@ PACKET_PICKUP
Definition: packettype.h:30
@ INV_FULL
Definition: pickup.h:38
@ BAD_ITEM
Definition: pickup.h:35
@ UNKNOWN
Definition: pickup.h:34
@ OKAY
Definition: pickup.h:33
@ TOO_FAR
Definition: pickup.h:37
@ MAX_AMOUNT
Definition: pickup.h:41
@ STACK_FULL
Definition: pickup.h:39
@ STACK_AMOUNT
Definition: pickup.h:42
@ TOO_HEAVY
Definition: pickup.h:36
@ DROP_STEAL
Definition: pickup.h:40
Inventory * getInventory()
Definition: playerinfo.cpp:195
void setStatMod(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:159
void equipItem(const Item *const item, const Sfx sfx)
Definition: playerinfo.cpp:238
Equipment * getEquipment()
Definition: playerinfo.cpp:220
void pickUpItem(const FloorItem *const item, const Sfx sfx)
Definition: playerinfo.cpp:366
int32_t getAttribute(const AttributesT id)
Definition: playerinfo.cpp:102
int getSkillLevel(const int id)
Definition: playerinfo.cpp:120
void unequipItem(const Item *const item, const Sfx sfx)
Definition: playerinfo.cpp:246
void updateAttackAi(const BeingId targetId, const Keep keep)
Definition: playerinfo.cpp:618
void setStatBase(const AttributesT id, const int value, const Notify notify)
Definition: playerinfo.cpp:143
@ REACH_YES
Definition: reachable.h:32
@ REACH_NO
Definition: reachable.h:33
@ FRIEND
Definition: relation.h:32
const WeaponsInfos & getShields()
Definition: weaponsdb.cpp:83
const WeaponsInfos & getSwords()
Definition: weaponsdb.cpp:78
const WeaponsInfos & getBows()
Definition: weaponsdb.cpp:73
std::vector< std::string > mMessages
Definition: deaddb.cpp:36
static const int blockWalkMask
Net::ServerFeatures * serverFeatures
Definition: net.cpp:101
Net::PlayerHandler * playerHandler
Definition: net.cpp:96
const bool Notify_true
Definition: notify.h:30
ParticleEngine * particleEngine
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
Pickup ::T PickupT
Definition: pickup.h:44
PlayerRelationsManager playerRelations
std::list< Position > Path
Definition: position.h:49
Settings settings
Definition: settings.cpp:32
const bool Sfx_false
Definition: sfx.h:30
const bool Sfx_true
Definition: sfx.h:30
ShopWindow * shopWindow
Definition: shopwindow.cpp:101
SocialWindow * socialWindow
static const std::string SOUND_INFO
Definition: sound.h:27
SoundManager soundManager
StatusWindow * statusWindow
std::string & replaceAll(std::string &context, const std::string &from, const std::string &to)
std::string strprintf(const char *const format,...)
int y
Definition: position.h:46
int x
Definition: position.h:45
TargetCursorType ::T TargetCursorTypeT
std::string fileName
Definition: testmain.cpp:39
Theme * theme
Definition: theme.cpp:62
int get_elapsed_time(const int startTime)
Definition: timer.cpp:94
const bool TryRemoveColors_true
UserColorId ::T UserColorIdT
Definition: usercolorid.h:99
UserPalette * userPalette
Definition: userpalette.cpp:34
std::vector< int > WeaponsInfos
Definition: weaponsdb.h:29
WeaponsInfos::const_iterator WeaponsInfosIter
Definition: weaponsdb.h:30