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 #ifndef BEING_LOCALPLAYER_H
25 #define BEING_LOCALPLAYER_H
26 
27 #include "being/being.h"
28 
29 #include "enums/being/pickup.h"
30 #include "enums/being/visiblename.h"
31 
32 #include "enums/simpletypes/allowsort.h"
33 #include "enums/simpletypes/keep.h"
34 
35 #include "listeners/actorspritelistener.h"
36 #include "listeners/attributelistener.h"
37 #include "listeners/playerdeathlistener.h"
38 
39 #include "localconsts.h"
40 
41 class AwayListener;
42 class ChatTab;
43 class FloorItem;
44 class Map;
45 class OkDialog;
46 
47 /**
48  * The local player character.
49  */
50 class LocalPlayer final : public Being,
51                           public ActorSpriteListener,
52                           public AttributeListener,
53                           public PlayerDeathListener
54 {
55     public:
56         /**
57          * Constructor.
58          */
59         LocalPlayer(const BeingId id,
60                     const BeingTypeId subType);
61 
62         A_DELETE_COPY(LocalPlayer)
63 
64         /**
65          * Destructor.
66          */
67         ~LocalPlayer() override final;
68 
69         void logic() override final;
70 
71         void slowLogic();
72 
73         void setAction(const BeingActionT &action,
74                        const int attackId) override final;
75 
76         /**
77          * Compute the next pathnode location when walking using keyboard.
78          * used by nextTile().
79          */
80         Position getNextWalkPosition(const unsigned char dir)
81                                      const A_WARN_UNUSED;
82 
83         /**
84          * Adds a new tile to the path when walking.
85          * @note Eathena
86          * Also, when specified, it picks up an item at the end of a path
87          * or attack target.
88          */
89         void nextTile() override final;
90 
91         bool pickUp(FloorItem *const item);
92 
93         /**
94          * Called when an ActorSprite has been destroyed.
95          * @param actorSprite the ActorSprite being destroyed.
96          */
97         void actorSpriteDestroyed(const ActorSprite &actorSprite)
98                                   override final;
99 
100         /**
101          * Gets the attack range.
102          */
103         int getAttackRange() const A_WARN_UNUSED;
104 
105         int getAttackRange2() const A_WARN_UNUSED;
106 
107         void attack(Being *const target,
108                     const bool keep,
109                     const bool dontChangeEquipment);
110 
111         void attack2(Being *const target,
112                      const bool keep,
113                      const bool dontChangeEquipment);
114 
115         void setGroupId(const int id) override final;
116 
117         void stopAttack(const bool keepAttack);
118 
119         void untarget();
120 
121         /**
122          * Returns the current target of the player. Returns 0 if no being is
123          * currently targeted.
124          */
125         Being *getTarget() const A_WARN_UNUSED;
126 
127         /**
128          * Sets the target being of the player.
129          */
130         void setTarget(Being *const target);
131 
132         Being *setNewTarget(const ActorTypeT type,
133                             const AllowSort allowSort);
134 
135         /**
136          * Sets a new destination for this being to walk to.
137          */
138         void setDestination(const int x, const int y);
139 
140         /**
141          * Sets a new direction to keep walking in.
142          */
143         void setWalkingDir(const unsigned char dir);
144 
145         /**
146          * Gets the walking direction
147          */
getWalkingDir()148         unsigned char getWalkingDir() const noexcept2 A_WARN_UNUSED
149         { return mWalkingDir; }
150 
151         /**
152          * Sets going to being to attack
153          */
154         void setGotoTarget(Being *const target);
155 
156         /**
157          * Returns whether the target is in range to attack
158          */
159         bool withinAttackRange(const Being *const target,
160                                const bool fixDistance,
161                                const int addRange) const A_WARN_UNUSED;
162 
163         /**
164          * Stops the player dead in his tracks
165          */
166         void stopWalking(const bool sendToServer);
167 
168         bool toggleSit() const;
169 
170         bool updateSit() const;
171 
172         static bool emote(const uint8_t emotion);
173 
174         /**
175          * Shows item pickup notifications.
176          */
177         void pickedUp(const ItemInfo &itemInfo,
178                       const int amount,
179                       const ItemColor color,
180                       const BeingId floorItemId,
181                       const PickupT fail);
182 
183         int getLevel() const override final A_WARN_UNUSED;
184 
185         /** Tells that the path has been set by mouse. */
pathSetByMouse()186         void pathSetByMouse()
187         { mPathSetByMouse = true; }
188 
189         /** Tells if the path has been set by mouse. */
isPathSetByMouse()190         bool isPathSetByMouse() const noexcept2 A_WARN_UNUSED
191         { return mPathSetByMouse; }
192 
getMoveState()193         unsigned int getMoveState() const noexcept2 A_WARN_UNUSED
194         { return mMoveState; }
195 
setMoveState(const unsigned int n)196         void setMoveState(const unsigned int n) noexcept2
197         { mMoveState = n; }
198 
199         std::string getPingTime() const A_WARN_UNUSED;
200 
201         void tryPingRequest();
202 
203 #ifdef TMWA_SUPPORT
204         void magicAttack() const;
205 #endif  // TMWA_SUPPORT
206 
207         void specialMove(const unsigned char direction);
208 
209         void moveByDirection(const unsigned char dir);
210 
211         bool pickUpItems(int pickUpType);
212 
213         void move(const int dX, const int dY);
214 
215         void moveToTarget(int dist);
216 
217         void moveToHome();
218 
219         bool isReachable(Being *const being,
220                          const int maxCost) A_WARN_UNUSED;
221 
222         bool isReachable(const int x,
223                          const int y,
224                          const bool allowCollision) const A_WARN_UNUSED;
225 
226         void setHome();
227 
228         void pingRequest();
229 
230         void pingResponse();
231 
232         void setAway(const std::string &message) const;
233 
234         static void setPseudoAway(const std::string &message);
235 
setHalfAway(const bool n)236         void setHalfAway(const bool n)
237         { mInactive = n; }
238 
getHalfAway()239         bool getHalfAway() const noexcept2 A_WARN_UNUSED
240         { return mInactive; }
241 
242         void afkRespond(ChatTab *const tab, const std::string &nick);
243 
244         static void setAfkMessage(std::string message);
245 
246         bool navigateTo(const int x, const int y);
247 
248         void navigateClean();
249 
250         void imitateEmote(const Being *const being,
251                           const unsigned char action) const;
252 
253         void imitateAction(const Being *const being,
254                            const BeingActionT &action);
255 
256         void imitateDirection(const Being *const being,
257                               const unsigned char dir);
258 
259         void imitateOutfit(const Being *const player,
260                            const int sprite) const;
261 
262         void followMoveTo(const Being *const being,
263                           const int x,
264                           const int y);
265 
266         void followMoveTo(const Being *const being,
267                           const int x1,
268                           const int y1,
269                           const int x2,
270                           const int y2);
271 
272         bool allowAction() A_WARN_UNUSED;
273 
274         void setRealPos(const int x, const int y);
275 
isServerBuggy()276         bool isServerBuggy() const noexcept2 A_WARN_UNUSED
277         { return mIsServerBuggy; }
278 
279         void fixPos();
280 
281         void setTileCoords(const int x,
282                            const int y) restrict2 override final;
283 
284         /**
285          * Sets the map the being is on
286          */
287         void setMap(Map *const map) override final;
288 
289         void addMessageToQueue(const std::string &message,
290                                const UserColorIdT color);
291 
292         /**
293          * Called when a option (set with config.addListener()) is changed
294          */
295         void optionChanged(const std::string &value) override final;
296 
297         void playerDeath() override final;
298 
299         /**
300          * set a following player.
301          */
302         void setFollow(const std::string &player);
303 
304         /**
305          * set an imitation player.
306          */
307         void setImitate(const std::string &player);
308 
309         /**
310          * setting the next destination of the following, in case of warp
311          */
312         void setNextDest(const int x, const int y);
313 
getNextDestX()314         int getNextDestX() const noexcept2 A_WARN_UNUSED
315         { return mNextDestX; }
316 
getNextDestY()317         int getNextDestY() const noexcept2 A_WARN_UNUSED
318         { return mNextDestY; }
319 
320         void respawn();
321 
getPickUpTarget()322         const FloorItem *getPickUpTarget() const noexcept2 A_WARN_UNUSED
323         { return mPickUpTarget; }
324 
unSetPickUpTarget()325         void unSetPickUpTarget()
326         { mPickUpTarget = nullptr; }
327 
328         /**
329          * Stop following a player.
330          */
331         void cancelFollow();
332 
333         /**
334          * Get the playername followed by the current player.
335          */
getFollow()336         const std::string &getFollow() const noexcept2 A_WARN_UNUSED
337         { return mPlayerFollowed; }
338 
339         /**
340          * Get the playername imitated by the current player.
341          */
getImitate()342         const std::string &getImitate() const noexcept2 A_WARN_UNUSED
343         { return mPlayerImitated; }
344 
345         /**
346          * Tells the engine whether to check
347          * if the Player Name is to be displayed.
348          */
setCheckNameSetting(const bool checked)349         void setCheckNameSetting(const bool checked)
350         { mUpdateName = checked; }
351 
352         /**
353          * Gets if the engine has to check
354          * if the Player Name is to be displayed.
355          */
getCheckNameSetting()356         bool getCheckNameSetting() const noexcept2 A_WARN_UNUSED
357         { return mUpdateName; }
358 
359         void fixAttackTarget();
360 
361         void updateNavigateList();
362 
363         int getPathLength(const Being *const being) const A_WARN_UNUSED;
364 
365         void targetMoved() const;
366 
setLastHitFrom(const std::string & n)367         void setLastHitFrom(const std::string &n)
368         { mLastHitFrom = n; }
369 
370         void waitFor(const std::string &nick);
371 
372         void checkNewName(Being *const being);
373 
374         unsigned char getBlockWalkMask() const override final
375                                        A_CONST A_WARN_UNUSED;
376 
377         void saveHomes();
378 
379         void removeHome();
380 
381         void stopAdvert();
382 
383         void addXpMessage(const int64_t change);
384 
385         void addHomunXpMessage(const int change);
386 
387         void addJobMessage(const int64_t change);
388 
389         void addHpMessage(const int change);
390 
391         void addSpMessage(const int change);
392 
393         static bool checAttackPermissions(const Being *const target)
394                                           A_WARN_UNUSED;
395 
396         void updateStatus() const;
397 
398         void setTestParticle(const std::string &fileName,
399                              const bool updateHash);
400 
getLastAttackX()401         int getLastAttackX() const override final
402         { return mTarget != nullptr ? mTarget->mX : mLastAttackX; }
403 
getLastAttackY()404         int getLastAttackY() const override final
405         { return mTarget != nullptr ? mTarget->mY : mLastAttackY; }
406 
407         void attributeChanged(const AttributesT id,
408                               const int64_t oldVal,
409                               const int64_t newVal) override final;
410 
411         void updateMusic() const;
412 
setAfkTime(const int v)413         void setAfkTime(const int v) noexcept2
414         { mAfkTime = v; }
415 
setAwayDialog(OkDialog * const dialog)416         void setAwayDialog(OkDialog *const dialog)
417         { mAwayDialog = dialog; }
418 
getAwayListener()419         AwayListener *getAwayListener() const noexcept2 A_WARN_UNUSED
420         { return mAwayListener; }
421 
setRename(const bool r)422         void setRename(const bool r) noexcept2
423         { mAllowRename = r; }
424 
getRename()425         bool getRename() const noexcept2
426         { return mAllowRename; }
427 
428         bool canMove() const;
429 
430         void freezeMoving(const int timeWaitTicks);
431 
432         void failMove(const int x,
433                       const int y);
434 
435     protected:
436         void updateCoords() override final;
437 
438         void handleStatusEffect(const StatusEffect *const effect,
439                                 const int32_t effectId,
440                                 const Enable newStatus,
441                                 const IsStart start) override final;
442 
443         void startWalking(const unsigned char dir);
444 
445         void changeEquipmentBeforeAttack(const Being *const target) const;
446 
447 #ifdef TMWA_SUPPORT
448         static void tryMagic(const std::string &spell,
449                              const int baseMagic,
450                              const int schoolMagic,
451                              const int mana);
452 #endif  // TMWA_SUPPORT
453 
454         void loadHomes();
455 
456         // move state. used if mMoveType == 2
457         unsigned int mMoveState;
458 
459         int mLastTargetX;
460         int mLastTargetY;
461 
462         std::map<std::string, Vector> mHomes;
463 
464         Being *mTarget;
465 
466         /** Follow system **/
467         std::string mPlayerFollowed;
468         std::string mPlayerImitated;
469         int mNextDestX;
470         int mNextDestY;
471 
472         FloorItem *mPickUpTarget;
473 
474         int mLastAction;      // Time stamp of the last action, -1 if none.
475 
476         STD_VECTOR<int32_t> mStatusEffectIcons;
477 
478         typedef std::pair<std::string, UserColorIdT> MessagePair;
479         /** Queued messages*/
480         std::list<MessagePair> mMessages;
481         int mMessageTime;
482         AwayListener *mAwayListener;
483         OkDialog *mAwayDialog;
484 
485         int mPingSendTick;
486         time_t mPingTime;
487         time_t mAfkTime;
488         time_t mActivityTime;
489         int mNavigateX;
490         int mNavigateY;
491         BeingId mNavigateId;
492         int mCrossX;
493         int mCrossY;
494         int mOldX;
495         int mOldY;
496         int mOldTileX;
497         int mOldTileY;
498         Path mNavigatePath;
499 
500         std::string mLastHitFrom;
501         std::string mWaitFor;
502         time_t mAdvertTime;
503         Particle *mTestParticle;
504         std::string mTestParticleName;
505         time_t mTestParticleTime;
506         unsigned long mTestParticleHash;
507         int mSyncPlayerMoveDistance;
508         int mUnfreezeTime;
509         unsigned char mWalkingDir;  // The direction the player is walking in.
510         /** Whether or not the name settings have changed */
511         bool mUpdateName;
512         bool mBlockAdvert;
513         bool mTargetDeadPlayers;
514         Keep mServerAttack;
515         VisibleName::Type mVisibleNames;
516         bool mEnableAdvert;
517         bool mTradebot;
518         bool mTargetOnlyReachable;
519         bool mIsServerBuggy;
520         bool mSyncPlayerMove;
521         bool mDrawPath;
522         bool mAttackMoving;
523         bool mAttackNext;
524         bool mShowJobExp;
525         bool mShowServerPos;
526         bool mNextStep;
527         // temporary disable crazy moves in moves
528         bool mGoingToTarget;
529         // Whether or not to continue to attack
530         bool mKeepAttacking;
531         // Tells if the path was set using mouse
532         bool mPathSetByMouse;
533         bool mWaitPing;
534         bool mShowNavigePath;
535         bool mAllowRename;
536         bool mFreezed;
537 };
538 
539 extern LocalPlayer *localPlayer;
540 
541 #endif  // BEING_LOCALPLAYER_H
542