ManaPlus
beingrecv.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 "net/tmwa/beingrecv.h"
25 
26 #include "actormanager.h"
27 #include "configuration.h"
28 #include "effectmanager.h"
29 #include "guild.h"
30 #include "party.h"
31 
32 #include "being/localplayer.h"
33 
35 
36 #include "input/keyboardconfig.h"
37 
40 
41 #include "net/beinghandler.h"
42 #include "net/serverfeatures.h"
43 
44 #include "net/messagein.h"
45 
46 #include "net/ea/beingrecv.h"
47 
48 #include "net/tmwa/guildmanager.h"
49 #include "net/tmwa/sprite.h"
50 
51 #include "resources/iteminfo.h"
52 
53 #include "resources/db/itemdb.h"
54 
55 #include "utils/timer.h"
56 
57 #include "debug.h"
58 
59 extern Window *deathNotice;
60 
61 namespace TmwAthena
62 {
63 
64 static void setGm(Being *const dstBeing,
65  const uint16_t gmstatus)
66 {
67  if (dstBeing != localPlayer &&
68  gmstatus == 0x80)
69  {
70  dstBeing->setGroupId(paths.getIntValue("gmDefaultLevel"));
71  }
72  else
73  {
74  dstBeing->setGroupId(gmstatus);
75  }
76 }
77 
79 {
80  BLOCK_START("BeingRecv::processBeingChangeLook")
81  if (actorManager == nullptr)
82  {
83  BLOCK_END("BeingRecv::processBeingChangeLook")
84  return;
85  }
86 
87  Being *const dstBeing = actorManager->findBeing(
88  msg.readBeingId("being id"));
89 
90  const uint8_t type = msg.readUInt8("type");
91  const int16_t id = CAST_S16(msg.readUInt8("id"));
92  const int id2 = 1;
93 
94  if ((localPlayer == nullptr) || (dstBeing == nullptr))
95  {
96  BLOCK_END("BeingRecv::processBeingChangeLook")
97  return;
98  }
99  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
100  BLOCK_END("BeingRecv::processBeingChangeLook")
101 }
102 
104 {
105  BLOCK_START("BeingRecv::processBeingChangeLook")
106  if (actorManager == nullptr)
107  {
108  BLOCK_END("BeingRecv::processBeingChangeLook")
109  return;
110  }
111 
112  Being *const dstBeing = actorManager->findBeing(
113  msg.readBeingId("being id"));
114 
115  const uint8_t type = msg.readUInt8("type");
116  int id2 = 0;
117 
118  const int16_t id = msg.readInt16("id1");
119  if (type == 2)
120  {
121  id2 = msg.readInt16("id2");
122  }
123  else
124  {
125  msg.readInt16("id2");
126  id2 = 1;
127  }
128 
129  if ((localPlayer == nullptr) || (dstBeing == nullptr))
130  {
131  BLOCK_END("BeingRecv::processBeingChangeLook")
132  return;
133  }
134  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
135  BLOCK_END("BeingRecv::processBeingChangeLook")
136 }
137 
139  Being *const dstBeing,
140  const uint8_t type,
141  const int id,
142  const int id2)
143 {
144  if (dstBeing->getType() == ActorType::Player)
145  dstBeing->setOtherTime();
146 
147  switch (type)
148  {
149  case 0: // change race
150  dstBeing->setSubtype(fromInt(id, BeingTypeId),
151  dstBeing->getLook());
152  break;
153  case 1: // eAthena LOOK_HAIR
154  {
155  const uint16_t look = CAST_U16(id / 256);
156  const int hair = id % 256;
157  dstBeing->setHairStyle(SPRITE_HAIR_COLOR, hair * -1);
158  dstBeing->setLook(look);
159  break;
160  }
161  case 2: // Weapon ID in id, Shield ID in id2
162  dstBeing->setSpriteId(SPRITE_BODY,
163  id);
164  dstBeing->setWeaponId(id);
165  dstBeing->setSpriteId(SPRITE_FLOOR,
166  id2);
168  break;
169  case 3: // Change lower headgear for eAthena, pants for us
170  dstBeing->setSpriteId(SPRITE_WEAPON,
171  id);
173  break;
174  case 4: // Change upper headgear for eAthena, hat for us
176  id);
178  break;
179  case 5: // Change middle headgear for eathena, armor for us
181  id);
183  break;
184  case 6: // eAthena LOOK_HAIR_COLOR
186  fromInt(id, ItemColor));
187  break;
188  case 7: // Clothes color
189  // ignoring it
190  break;
191  case 8: // eAthena LOOK_SHIELD
192  dstBeing->setSpriteId(SPRITE_FLOOR,
193  id);
195  break;
196  case 9: // eAthena LOOK_SHOES
197  dstBeing->setSpriteId(SPRITE_HAIR,
198  id);
200  break;
201  case 10: // LOOK_GLOVES
202  dstBeing->setSpriteId(SPRITE_SHOES,
203  id);
205  break;
206  case 11: // LOOK_CAPE
207  dstBeing->setSpriteId(SPRITE_SHIELD,
208  id);
210  break;
211  case 12:
212  dstBeing->setSpriteId(SPRITE_HEAD_TOP,
213  id);
215  break;
216  case 13:
217  dstBeing->setSpriteId(SPRITE_HEAD_MID,
218  id);
220  break;
221  case 14:
222  dstBeing->setSpriteId(SPRITE_ROBE,
223  id);
225  break;
226  case 15:
227  dstBeing->setSpriteId(SPRITE_EVOL2,
228  id);
230  break;
231  case 16:
232  dstBeing->setLook(CAST_U16(id));
233  break;
234  default:
236  break;
237  }
238 }
239 
241 {
242  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
243  if ((actorManager == nullptr) || (localPlayer == nullptr))
244  {
245  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
246  return;
247  }
248 
249  // An update about a player, potentially including movement.
250  const BeingId id = msg.readBeingId("account id");
251  const int16_t speed = msg.readInt16("speed");
252  const uint32_t opt1 = msg.readInt16("opt1");
253  const uint32_t opt2 = msg.readInt16("opt2");
254  const uint32_t option = msg.readInt16("option");
255  const int16_t job = msg.readInt16("job");
256  int disguiseId = 0;
257  if (toInt(id, int) < 110000000 && job >= 1000)
258  disguiseId = job;
259 
260  Being *dstBeing = actorManager->findBeing(id);
261  if (dstBeing == nullptr)
262  {
263  if (actorManager->isBlocked(id) == true)
264  {
265  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
266  return;
267  }
268 
269  dstBeing = Ea::BeingRecv::createBeing(id, job);
270 
271  if (dstBeing == nullptr)
272  {
273  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
274  return;
275  }
276  }
277  else if (disguiseId != 0)
278  {
279  actorManager->undelete(dstBeing);
281  }
282 
283  uint8_t dir = dstBeing->getDirectionDelayed();
284  if (dir != 0U)
285  {
286  if (dir != dstBeing->getDirection())
287  dstBeing->setDirection(dir);
288  }
289 
290  if (Party *const party = localPlayer->getParty())
291  {
292  if (party->isMember(id))
293  dstBeing->setParty(party);
294  }
295 
296  dstBeing->setWalkSpeed(speed);
297 
298  const uint8_t hairStyle = msg.readUInt8("hair style");
299  const uint16_t look = msg.readUInt8("look");
300  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
301  const uint16_t weapon = msg.readInt16("weapon");
302  const uint16_t shield = msg.readInt16("shield");
303  const uint16_t headBottom = msg.readInt16("head bottom");
304 
305  const uint16_t headTop = msg.readInt16("head top");
306  const uint16_t headMid = msg.readInt16("head mid");
307  const ItemColor hairColor = fromInt(
308  msg.readUInt8("hair color"), ItemColor);
309  msg.readUInt8("unused");
310  msg.readInt32("unused");
311 
312  const int guild = msg.readInt32("guild");
313 
314  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
315  {
316  if (guild == 0)
317  dstBeing->clearGuilds();
318  else
319  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
320  }
321 
322  msg.readInt16("emblem");
323  dstBeing->setManner(msg.readInt16("manner"));
324  const uint32_t opt3 = msg.readInt16("opt3");
325  dstBeing->setKarma(msg.readUInt8("karma"));
326  // reserving bit for future usage
327  dstBeing->setGender(Being::intToGender(
328  CAST_U8(msg.readUInt8("gender") & 3)));
329 
330  if (disguiseId == 0)
331  {
332  // Set these after the gender, as the sprites may be gender-specific
333  dstBeing->updateSprite(SPRITE_BODY,
334  weapon,
335  std::string());
336  dstBeing->setWeaponId(weapon);
337  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
338  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
339  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
340  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
341  if (hairStyle == 0)
342  {
344  0,
345  std::string());
346  }
347  else
348  {
350  hairStyle * -1,
351  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
352  }
353  dstBeing->setHairColor(hairColor);
354  }
355  localPlayer->imitateOutfit(dstBeing, -1);
356 
357  uint16_t x;
358  uint16_t y;
359  msg.readCoordinates(x, y, dir, "position");
360  dstBeing->setTileCoords(x, y);
361  dstBeing->setDirection(dir);
362 
363  localPlayer->imitateDirection(dstBeing, dir);
364 
365  const uint16_t gmstatus = msg.readInt16("gm status");
366 
367  setGm(dstBeing, gmstatus);
368 
369  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
370  const int level = CAST_S32(msg.readUInt8("level"));
371  if (level != 0)
372  dstBeing->setLevel(level);
373 
374  msg.readUInt8("unused");
375 
376  dstBeing->setActionTime(tick_time);
377 
378  dstBeing->setStatusEffectOpitons(option,
379  opt1,
380  opt2,
381  opt3);
382 
383  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
384 }
385 
387 {
388  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
389  if ((actorManager == nullptr) || (localPlayer == nullptr))
390  {
391  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
392  return;
393  }
394 
395  // An update about a player, potentially including movement.
396  const BeingId id = msg.readBeingId("account id");
397  const int16_t speed = msg.readInt16("speed");
398  const uint32_t opt1 = msg.readInt16("opt1");
399  const uint32_t opt2 = msg.readInt16("opt2");
400  const uint32_t option = msg.readInt16("option");
401  const int16_t job = msg.readInt16("job");
402  int disguiseId = 0;
403  if (toInt(id, int) < 110000000 && job >= 1000)
404  disguiseId = job;
405 
406  Being *dstBeing = actorManager->findBeing(id);
407  if (dstBeing == nullptr)
408  {
409  if (actorManager->isBlocked(id) == true)
410  {
411  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
412  return;
413  }
414 
415  dstBeing = Ea::BeingRecv::createBeing(id, job);
416 
417  if (dstBeing == nullptr)
418  {
419  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
420  return;
421  }
422  }
423  else if (disguiseId != 0)
424  {
425  actorManager->undelete(dstBeing);
427  }
428 
429  uint8_t dir = dstBeing->getDirectionDelayed();
430  if (dir != 0U)
431  {
432  if (dir != dstBeing->getDirection())
433  dstBeing->setDirection(dir);
434  }
435 
436  if (Party *const party = localPlayer->getParty())
437  {
438  if (party->isMember(id))
439  dstBeing->setParty(party);
440  }
441 
442  dstBeing->setWalkSpeed(speed);
443 
444  const uint8_t hairStyle = msg.readUInt8("hair style");
445  const uint16_t look = msg.readUInt8("look");
446  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
447  const uint16_t weapon = msg.readInt16("weapon");
448  const uint16_t shield = msg.readInt16("shield");
449  const uint16_t headBottom = msg.readInt16("head bottom");
450  const uint16_t headTop = msg.readInt16("head top");
451  const uint16_t headMid = msg.readInt16("head mid");
452  const ItemColor hairColor = fromInt(
453  msg.readUInt8("hair color"), ItemColor);
454  msg.readUInt8("unused");
455  msg.readInt32("unused");
456 
457  const int guild = msg.readInt32("guild");
458 
459  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
460  {
461  if (guild == 0)
462  dstBeing->clearGuilds();
463  else
464  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
465  }
466 
467  msg.readInt16("emblem");
468  dstBeing->setManner(msg.readInt16("manner"));
469  const uint32_t opt3 = msg.readInt16("opt3");
470  dstBeing->setKarma(msg.readUInt8("karma"));
471  // reserving bit for future usage
472  dstBeing->setGender(Being::intToGender(
473  CAST_U8(msg.readUInt8("gender") & 3)));
474 
475  if (disguiseId == 0)
476  {
477  // Set these after the gender, as the sprites may be gender-specific
478  dstBeing->updateSprite(SPRITE_BODY,
479  weapon,
480  std::string());
481  dstBeing->setWeaponId(weapon);
482  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
483  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
484  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
485  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
486  if (hairStyle == 0)
487  {
489  0,
490  std::string());
491  }
492  else
493  {
495  hairStyle * -1,
496  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
497  }
498  dstBeing->setHairColor(hairColor);
499  }
500  localPlayer->imitateOutfit(dstBeing, -1);
501 
502  uint16_t x;
503  uint16_t y;
504  msg.readCoordinates(x, y, dir, "position");
505  dstBeing->setTileCoords(x, y);
506  dstBeing->setDirection(dir);
507 
508  localPlayer->imitateDirection(dstBeing, dir);
509 
510  const uint16_t gmstatus = msg.readInt16("gm status");
511 
512  setGm(dstBeing, gmstatus);
513 
514  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
515  const int level = CAST_S32(msg.readUInt8("level"));
516  if (level != 0)
517  dstBeing->setLevel(level);
518 
519  dstBeing->setActionTime(tick_time);
520  dstBeing->setStatusEffectOpitons(option,
521  opt1,
522  opt2,
523  opt3);
524 
525  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
526 }
527 
529 {
530  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
531  if ((actorManager == nullptr) || (localPlayer == nullptr))
532  {
533  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
534  return;
535  }
536 
537  // An update about a player, potentially including movement.
538  const BeingId id = msg.readBeingId("account id");
539  const int16_t speed = msg.readInt16("speed");
540  const uint32_t opt1 = msg.readInt16("opt1");
541  const uint32_t opt2 = msg.readInt16("opt2");
542  const uint32_t option = msg.readInt16("option");
543  const int16_t job = msg.readInt16("job");
544  int disguiseId = 0;
545  if (toInt(id, int) < 110000000 && job >= 1000)
546  disguiseId = job;
547 
548  Being *dstBeing = actorManager->findBeing(id);
549  if (dstBeing == nullptr)
550  {
551  if (actorManager->isBlocked(id) == true)
552  {
553  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
554  return;
555  }
556 
557  dstBeing = Ea::BeingRecv::createBeing(id, job);
558 
559  if (dstBeing == nullptr)
560  {
561  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
562  return;
563  }
564  }
565  else if (disguiseId != 0)
566  {
567  actorManager->undelete(dstBeing);
569  }
570 
571  const uint8_t dir = dstBeing->getDirectionDelayed();
572  if (dir != 0U)
573  {
574  if (dir != dstBeing->getDirection())
575  dstBeing->setDirection(dir);
576  }
577 
578  if (Party *const party = localPlayer->getParty())
579  {
580  if (party->isMember(id))
581  dstBeing->setParty(party);
582  }
583 
584  dstBeing->setWalkSpeed(speed);
585 
586  const uint8_t hairStyle = msg.readUInt8("hair style");
587  const uint16_t look = msg.readUInt8("look");
588  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
589  const uint16_t weapon = msg.readInt16("weapon");
590  const uint16_t shield = msg.readInt16("shield");
591  const uint16_t headBottom = msg.readInt16("head bottom");
592 
593  msg.readInt32("tick");
594 
595  const uint16_t headTop = msg.readInt16("head top");
596  const uint16_t headMid = msg.readInt16("head mid");
597  const ItemColor hairColor = fromInt(
598  msg.readUInt8("hair color"), ItemColor);
599  msg.readUInt8("unused");
600  msg.readInt32("unused");
601 
602  const int guild = msg.readInt32("guild");
603 
604  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
605  {
606  if (guild == 0)
607  dstBeing->clearGuilds();
608  else
609  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
610  }
611 
612  msg.readInt16("emblem");
613  dstBeing->setManner(msg.readInt16("manner"));
614  const uint32_t opt3 = msg.readInt16("opt3");
615  dstBeing->setKarma(msg.readUInt8("karma"));
616  // reserving bit for future usage
617  dstBeing->setGender(Being::intToGender(
618  CAST_U8(msg.readUInt8("gender") & 3)));
619 
620  if (disguiseId == 0)
621  {
622  // Set these after the gender, as the sprites may be gender-specific
623  dstBeing->updateSprite(SPRITE_BODY,
624  weapon,
625  std::string());
626  dstBeing->setWeaponId(weapon);
627  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
628  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
629  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
630  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
631  if (hairStyle == 0)
632  {
634  0,
635  std::string());
636  }
637  else
638  {
640  hairStyle * -1,
641  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
642  }
643  dstBeing->setHairColor(hairColor);
644  }
645  localPlayer->imitateOutfit(dstBeing, -1);
646 
647  uint16_t srcX;
648  uint16_t srcY;
649  uint16_t dstX;
650  uint16_t dstY;
651  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "moving path");
652 
653  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
654 
655  dstBeing->setTileCoords(srcX, srcY);
656  dstBeing->setDestination(dstX, dstY);
657 
658  // because server don't send direction in move packet,
659  // we fixing it
660 
661  if (srcX != dstX || srcY != dstY)
662  {
663  const int d = dstBeing->calcDirection(dstX, dstY);
664 
665  if ((d != 0) && dstBeing->getDirection() != d)
666  dstBeing->setDirectionDelayed(CAST_U8(d));
667  }
668 
671  if (localPlayer->getDirection() != dstBeing->getDirection())
672  {
673  localPlayer->imitateDirection(dstBeing,
674  dstBeing->getDirection());
675  }
676 
677  const uint16_t gmstatus = msg.readInt16("gm status");
678 
679  setGm(dstBeing, gmstatus);
680 
681  msg.readUInt8("unused");
682 
683  const int level = CAST_S32(msg.readUInt8("level"));
684  if (level != 0)
685  dstBeing->setLevel(level);
686 
687  msg.readUInt8("unused");
688 
689  if (dstBeing->getType() != ActorType::Player)
690  dstBeing->setActionTime(tick_time);
691 
692  dstBeing->setStatusEffectOpitons(option,
693  opt1,
694  opt2,
695  opt3);
696 
697  if (dstBeing->getType() == ActorType::Player)
698  dstBeing->setMoveTime();
699  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
700 }
701 
703 {
704  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
705  if (actorManager == nullptr)
706  {
707  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
708  return;
709  }
710 
711  BeingId spawnId;
712 
713  // Information about a being in range
714  const BeingId id = msg.readBeingId("being id");
715  if (id == Ea::BeingRecv::mSpawnId)
716  spawnId = Ea::BeingRecv::mSpawnId;
717  else
718  spawnId = BeingId_zero;
720  int16_t speed = msg.readInt16("speed");
721  const uint32_t opt1 = msg.readInt16("opt1");
722  const uint32_t opt2 = msg.readInt16("opt2");
723  const uint32_t option = msg.readInt16("option");
724  const int16_t job = msg.readInt16("class");
725  int disguiseId = 0;
726  if (id == localPlayer->getId() && job >= 1000)
727  disguiseId = job;
728 
729  Being *dstBeing = actorManager->findBeing(id);
730 
731  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
732  && !dstBeing->isAlive())
733  {
734  actorManager->destroy(dstBeing);
735  actorManager->erase(dstBeing);
736  dstBeing = nullptr;
737  }
738 
739  if (dstBeing == nullptr)
740  {
741  // Being with id >= 110000000 and job 0 are better
742  // known as ghosts, so don't create those.
743  if (job == 0 && toInt(id, int) >= 110000000)
744  {
745  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
746  return;
747  }
748 
749  if (actorManager->isBlocked(id) == true)
750  {
751  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
752  return;
753  }
754 
755  dstBeing = Ea::BeingRecv::createBeing(id, job);
756 
757  if (dstBeing == nullptr)
758  {
759  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
760  return;
761  }
762  }
763  else
764  {
765  if (dstBeing->getType() == ActorType::Npc)
766  {
767  actorManager->undelete(dstBeing);
769  }
770  }
771 
772  if (dstBeing->getType() == ActorType::Player)
773  dstBeing->setMoveTime();
774 
775  if (spawnId != BeingId_zero)
776  {
777  dstBeing->setAction(BeingAction::SPAWN, 0);
778  }
779  else
780  {
781  dstBeing->clearPath();
782  dstBeing->setActionTime(tick_time);
783  dstBeing->setAction(BeingAction::STAND, 0);
784  }
785 
786  // Prevent division by 0 when calculating frame
787  if (speed == 0)
788  speed = 150;
789 
790  const uint8_t hairStyle = msg.readUInt8("hair style");
791  const uint16_t look = msg.readUInt8("look");
792  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
793  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
794  localPlayer->checkNewName(dstBeing);
795  dstBeing->setWalkSpeed(speed);
796  const uint16_t weapon = msg.readInt16("weapon");
797  const uint16_t headBottom = msg.readInt16("head bottom");
798 
799  const uint16_t shield = msg.readInt16("shield");
800  const uint16_t headTop = msg.readInt16("head top");
801  const uint16_t headMid = msg.readInt16("head mid");
802  const ItemColor hairColor = fromInt(msg.readUInt8("hair color"),
803  ItemColor);
804  msg.readUInt8("unused");
805  const uint16_t shoes = msg.readInt16("shoes / clothes color");
806 
807  uint16_t gloves;
808  if (dstBeing->getType() == ActorType::Monster)
809  {
811  {
812  const int hp = msg.readInt32("hp");
813  const int maxHP = msg.readInt32("max hp");
814  if ((hp != 0) && (maxHP != 0))
815  {
816  dstBeing->setMaxHP(maxHP);
817  const int oldHP = dstBeing->getHP();
818  if ((oldHP == 0) || oldHP > hp)
819  dstBeing->setHP(hp);
820  }
821  }
822  else
823  {
824  msg.readInt32("unused");
825  msg.readInt32("unused");
826  }
827  gloves = 0;
828  }
829  else
830  {
831  gloves = msg.readInt16("gloves / head dir");
832  msg.readInt32("guild");
833  msg.readInt16("guild emblem");
834  }
835 
836  dstBeing->setManner(msg.readInt16("manner"));
837  const uint32_t opt3 = msg.readInt16("opt3");
839  && dstBeing->getType() == ActorType::Monster)
840  {
841  const int attackRange = CAST_S32(
842  msg.readUInt8("attack range (was karma)"));
843  dstBeing->setAttackRange(attackRange);
844  }
845  else
846  {
847  dstBeing->setKarma(msg.readUInt8("karma"));
848  }
849  uint8_t gender = msg.readUInt8("gender");
850 
851  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
852  {
853  // reserving bits for future usage
854  gender &= 3;
855  dstBeing->setGender(Being::intToGender(gender));
856  // Set these after the gender, as the sprites may be gender-specific
857  if (hairStyle == 0)
858  {
859  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
860  }
861  else
862  {
864  hairStyle * -1,
865  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
866  }
867  dstBeing->setHairColor(hairColor);
868  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
869  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
870  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
871  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
872  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
873  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
874  dstBeing->setWeaponId(weapon);
875  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
876  }
877  else if (dstBeing->getType() == ActorType::Npc
879  {
880  setServerGender(dstBeing, gender);
881  }
882 
883  uint8_t dir;
884  uint16_t x;
885  uint16_t y;
886  msg.readCoordinates(x, y, dir, "position");
887  dstBeing->setTileCoords(x, y);
888 
889  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
890  {
891  const int num = socialWindow->getPortalIndex(x, y);
892  if (num >= 0)
893  {
895  OutfitWindow::keyName(num)));
896  }
897  else
898  {
899  dstBeing->setName("");
900  }
901  }
902 
903  dstBeing->setDirection(dir);
904 
905  msg.readUInt8("unknown");
906  msg.readUInt8("unknown");
907  msg.readUInt8("unknown");
908  msg.readUInt8("unknown");
909  msg.readUInt8("unknown");
910 
911  dstBeing->setStatusEffectOpitons(option,
912  opt1,
913  opt2,
914  opt3);
915  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
916 }
917 
919 {
920  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
921  if (actorManager == nullptr)
922  {
923  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
924  return;
925  }
926 
927  BeingId spawnId;
928 
929  // Information about a being in range
930  const BeingId id = msg.readBeingId("being id");
931  if (id == Ea::BeingRecv::mSpawnId)
932  spawnId = Ea::BeingRecv::mSpawnId;
933  else
934  spawnId = BeingId_zero;
936  int16_t speed = msg.readInt16("speed");
937  const uint32_t opt1 = msg.readInt16("opt1");
938  const uint32_t opt2 = msg.readInt16("opt2");
939  const uint32_t option = msg.readInt16("option");
940  const int16_t job = msg.readInt16("class");
941  int disguiseId = 0;
942  if (id == localPlayer->getId() && job >= 1000)
943  disguiseId = job;
944 
945  Being *dstBeing = actorManager->findBeing(id);
946 
947  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
948  && !dstBeing->isAlive())
949  {
950  actorManager->destroy(dstBeing);
951  actorManager->erase(dstBeing);
952  dstBeing = nullptr;
953  }
954 
955  if (dstBeing == nullptr)
956  {
957  // Being with id >= 110000000 and job 0 are better
958  // known as ghosts, so don't create those.
959  if (job == 0 && toInt(id, int) >= 110000000)
960  {
961  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
962  return;
963  }
964 
965  if (actorManager->isBlocked(id) == true)
966  {
967  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
968  return;
969  }
970 
971  dstBeing = Ea::BeingRecv::createBeing(id, job);
972 
973  if (dstBeing == nullptr)
974  {
975  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
976  return;
977  }
978  }
979  else
980  {
981  if (dstBeing->getType() == ActorType::Npc)
982  {
983  actorManager->undelete(dstBeing);
985  }
986  }
987 
988  if (dstBeing->getType() == ActorType::Player)
989  dstBeing->setMoveTime();
990 
991  if (spawnId != BeingId_zero)
992  dstBeing->setAction(BeingAction::SPAWN, 0);
993 
994  // Prevent division by 0 when calculating frame
995  if (speed == 0)
996  speed = 150;
997 
998  const uint8_t hairStyle = msg.readUInt8("hair style");
999  const uint16_t look = msg.readUInt8("look");
1000  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
1001  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
1002  localPlayer->checkNewName(dstBeing);
1003  dstBeing->setWalkSpeed(speed);
1004  const uint16_t weapon = msg.readInt16("weapon");
1005  const uint16_t headBottom = msg.readInt16("head bottom");
1006 
1007  msg.readInt32("tick");
1008 
1009  const uint16_t shield = msg.readInt16("shield");
1010  const uint16_t headTop = msg.readInt16("head top");
1011  const uint16_t headMid = msg.readInt16("head mid");
1012  const ItemColor hairColor = fromInt(
1013  msg.readUInt8("hair color"), ItemColor);
1014  msg.readUInt8("unused");
1015  const uint16_t shoes = msg.readInt16("shoes / clothes color");
1016 
1017  uint16_t gloves;
1018  if (dstBeing->getType() == ActorType::Monster)
1019  {
1021  {
1022  const int hp = msg.readInt32("hp");
1023  const int maxHP = msg.readInt32("max hp");
1024  if ((hp != 0) && (maxHP != 0))
1025  {
1026  dstBeing->setMaxHP(maxHP);
1027  const int oldHP = dstBeing->getHP();
1028  if ((oldHP == 0) || oldHP > hp)
1029  dstBeing->setHP(hp);
1030  }
1031  }
1032  else
1033  {
1034  msg.readInt32("unused");
1035  msg.readInt32("unused");
1036  }
1037  gloves = 0;
1038  }
1039  else
1040  {
1041  gloves = msg.readInt16("gloves / head dir");
1042  msg.readInt32("guild");
1043  msg.readInt16("guild emblem");
1044  }
1045 
1046  dstBeing->setManner(msg.readInt16("manner"));
1047  const uint32_t opt3 = msg.readInt16("opt3");
1049  && dstBeing->getType() == ActorType::Monster)
1050  {
1051  const int attackRange = CAST_S32(
1052  msg.readUInt8("attack range (was karma)"));
1053  dstBeing->setAttackRange(attackRange);
1054  }
1055  else
1056  {
1057  dstBeing->setKarma(msg.readUInt8("karma"));
1058  }
1059  uint8_t gender = msg.readUInt8("gender");
1060 
1061  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
1062  {
1063  // reserving bits for future usage
1064  gender &= 3;
1065  dstBeing->setGender(Being::intToGender(gender));
1066  // Set these after the gender, as the sprites may be gender-specific
1067  if (hairStyle == 0)
1068  {
1069  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
1070  }
1071  else
1072  {
1073  dstBeing->updateSprite(SPRITE_HAIR_COLOR,
1074  hairStyle * -1,
1075  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
1076  }
1077  dstBeing->setHairColor(hairColor);
1078  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
1079  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
1080  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
1081  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
1082  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
1083  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
1084  dstBeing->setWeaponId(weapon);
1085  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
1086  }
1087  else if (dstBeing->getType() == ActorType::Npc
1089  {
1090  setServerGender(dstBeing, gender);
1091  }
1092 
1093  uint16_t srcX;
1094  uint16_t srcY;
1095  uint16_t dstX;
1096  uint16_t dstY;
1097  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1098  if (disguiseId == 0)
1099  {
1100  dstBeing->setAction(BeingAction::STAND, 0);
1101  dstBeing->setTileCoords(srcX, srcY);
1102  if (serverFeatures->haveMove3())
1103  dstBeing->setCachedDestination(dstX, dstY);
1104  else
1105  dstBeing->setDestination(dstX, dstY);
1106  }
1107 
1108  msg.readUInt8("unknown");
1109  msg.readUInt8("unknown");
1110  msg.readUInt8("unknown");
1111  msg.readUInt8("unknown");
1112  msg.readUInt8("unknown");
1113 
1114  dstBeing->setStatusEffectOpitons(option,
1115  opt1,
1116  opt2,
1117  opt3);
1118  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
1119 }
1120 
1122 {
1123  BLOCK_START("BeingRecv::processBeingSpawn")
1124  // skipping this packet
1125  Ea::BeingRecv::mSpawnId = msg.readBeingId("being id");
1126  msg.readInt16("speed");
1127  msg.readInt16("opt1");
1128  msg.readInt16("opt2");
1129  msg.readInt16("option");
1130  msg.readInt16("disguise");
1131  msg.skip(25, "unused");
1132  BLOCK_END("BeingRecv::processBeingSpawn")
1133 }
1134 
1136 {
1137  msg.readInt32("src id");
1138  msg.readInt32("dst id");
1139  msg.readInt16("dst x");
1140  msg.readInt16("dst y");
1141  msg.readInt16("skill num");
1142  msg.readInt32("skill get p1");
1143  msg.readInt32("cast time");
1144 }
1145 
1147 {
1148  BLOCK_START("BeingRecv::processBeingStatusChange")
1149  if (actorManager == nullptr)
1150  {
1151  BLOCK_END("BeingRecv::processBeingStatusChange")
1152  return;
1153  }
1154 
1155  // Status change
1156  const uint16_t status = msg.readInt16("status");
1157  const BeingId id = msg.readBeingId("being id");
1158  const Enable flag = fromBool(
1159  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1160 
1161  Being *const dstBeing = actorManager->findBeing(id);
1162  if (dstBeing != nullptr)
1163  {
1164  // dont know on legacy servers is effect really started
1165  // or not. Because this always sending IsStart_true
1166  dstBeing->setStatusEffect(status, flag, IsStart_true);
1167  }
1168  BLOCK_END("BeingRecv::processBeingStatusChange")
1169 }
1170 
1172 {
1173  BLOCK_START("BeingRecv::processBeingMove2")
1174  if (actorManager == nullptr)
1175  {
1176  BLOCK_END("BeingRecv::processBeingMove2")
1177  return;
1178  }
1179 
1180  /*
1181  * A simplified movement packet, used by the
1182  * later versions of eAthena for both mobs and
1183  * players
1184  */
1185  Being *const dstBeing = actorManager->findBeing(
1186  msg.readBeingId("being id"));
1187 
1188  /*
1189  * This packet doesn't have enough info to actually
1190  * create a new being, so if the being isn't found,
1191  * we'll just pretend the packet didn't happen
1192  */
1193 
1194  if (dstBeing == nullptr)
1195  {
1196  BLOCK_END("BeingRecv::processBeingMove2")
1197  return;
1198  }
1199 
1200  uint16_t srcX;
1201  uint16_t srcY;
1202  uint16_t dstX;
1203  uint16_t dstY;
1204  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1205  msg.readInt32("tick");
1206 
1207  dstBeing->setAction(BeingAction::STAND, 0);
1208  dstBeing->setTileCoords(srcX, srcY);
1209  dstBeing->setDestination(dstX, dstY);
1210  if (dstBeing->getType() == ActorType::Player)
1211  dstBeing->setMoveTime();
1212  BLOCK_END("BeingRecv::processBeingMove2")
1213 }
1214 
1216 {
1217  BLOCK_START("BeingRecv::processBeingChangeDirection")
1218  if (actorManager == nullptr)
1219  {
1220  BLOCK_END("BeingRecv::processBeingChangeDirection")
1221  return;
1222  }
1223 
1224  Being *const dstBeing = actorManager->findBeing(
1225  msg.readBeingId("being id"));
1226 
1227  if (dstBeing == nullptr)
1228  {
1229  DEBUGLOGSTR("invisible player?");
1230  msg.readInt16("unused");
1231  msg.readUInt8("direction");
1232  BLOCK_END("BeingRecv::processBeingChangeDirection");
1233  return;
1234  }
1235 
1236  msg.readInt16("unused");
1237 
1238  const uint8_t dir = Net::MessageIn::fromServerDirection(
1239  CAST_U8(msg.readUInt8("direction") & 0x0FU));
1240  dstBeing->setDirection(dir);
1241  if (localPlayer != nullptr)
1242  localPlayer->imitateDirection(dstBeing, dir);
1243  BLOCK_END("BeingRecv::processBeingChangeDirection")
1244 }
1245 
1247 {
1248  BLOCK_START("BeingRecv::processPlayerStop")
1249  if (actorManager == nullptr)
1250  {
1251  BLOCK_END("BeingRecv::processPlayerStop")
1252  return;
1253  }
1254 
1255  // Change in players' flags
1256  const BeingId id = msg.readBeingId("account id");
1257  Being *const dstBeing = actorManager->findBeing(id);
1258  if (dstBeing == nullptr)
1259  {
1260  DEBUGLOGSTR("invisible player?");
1261  msg.readInt16("stun mode");
1262  msg.readInt16("status effect");
1263  msg.readInt16("opt?");
1264  msg.readUInt8("Unused?");
1265  return;
1266  }
1267 
1268  const uint32_t opt1 = msg.readInt16("opt1");
1269  const uint32_t opt2 = msg.readInt16("opt2");
1270  const uint32_t option = msg.readInt16("option");
1271  msg.readUInt8("Unused?");
1272 
1273  dstBeing->setStatusEffectOpitons(option,
1274  opt1,
1275  opt2);
1276  BLOCK_END("BeingRecv::processPlayerStop")
1277 }
1278 
1280 {
1281  BLOCK_START("BeingRecv::processBeingResurrect")
1282  if (actorManager == nullptr || localPlayer == nullptr)
1283  {
1284  BLOCK_END("BeingRecv::processBeingResurrect")
1285  return;
1286  }
1287 
1288  // A being changed mortality status
1289 
1290  const BeingId id = msg.readBeingId("being id");
1291  Being *const dstBeing = actorManager->findBeing(id);
1292  if (dstBeing == nullptr)
1293  {
1294  DEBUGLOGSTR("insible player?");
1295  msg.readInt16("flag?");
1296  BLOCK_END("BeingRecv::processBeingResurrect")
1297  return;
1298  }
1299 
1300  // If this is player's current target, clear it.
1301  if (dstBeing == localPlayer->getTarget())
1302  localPlayer->stopAttack(false);
1303  if (dstBeing == localPlayer &&
1304  deathNotice != nullptr)
1305  {
1307  deathNotice = nullptr;
1308  }
1309 
1310  if (msg.readInt16("flag?") == 1)
1311  dstBeing->setAction(BeingAction::STAND, 0);
1312  BLOCK_END("BeingRecv::processBeingResurrect")
1313 }
1314 
1316 {
1317  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo")
1318  if (actorManager == nullptr)
1319  {
1320  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1321  return;
1322  }
1323 
1324  Being *const dstBeing = actorManager->findBeing(
1325  msg.readBeingId("being id"));
1326 
1327  if (dstBeing != nullptr)
1328  {
1329  dstBeing->setPartyName(msg.readString(24, "party name"));
1330  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
1331  {
1332  dstBeing->setGuildName(msg.readString(24, "guild name"));
1333  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1334  }
1335  else
1336  {
1337  msg.readString(24, "guild name");
1338  msg.readString(24, "guild pos");
1339  }
1340  dstBeing->addToCache();
1341  msg.readString(24, "?");
1342  }
1343  else
1344  {
1345  msg.readString(24, "party name");
1346  msg.readString(24, "guild name");
1347  msg.readString(24, "guild pos");
1348  msg.readString(24, "?");
1349  }
1350  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1351 }
1352 
1354 {
1355  BLOCK_START("BeingRecv::processBeingSelfEffect")
1356  if ((effectManager == nullptr) || (actorManager == nullptr))
1357  {
1358  BLOCK_END("BeingRecv::processBeingSelfEffect")
1359  return;
1360  }
1361 
1362  const BeingId id = msg.readBeingId("being id");
1363  Being *const being = actorManager->findBeing(id);
1364  if (being == nullptr)
1365  {
1366  DEBUGLOGSTR("insible player?");
1367  msg.readInt32("effect type");
1368  BLOCK_END("BeingRecv::processBeingSelfEffect")
1369  return;
1370  }
1371 
1372  const int effectType = msg.readInt32("effect type");
1373 
1375  effectManager->trigger(effectType, being, 0);
1376 
1377  // +++ need dehard code effectType == 3
1378  if (effectType == 3 && being->getType() == ActorType::Player
1379  && (socialWindow != nullptr))
1380  { // reset received damage
1381  socialWindow->resetDamage(being->getName());
1382  }
1383  BLOCK_END("BeingRecv::processBeingSelfEffect")
1384 }
1385 
1387 {
1388  msg.readInt32("skill id");
1389 }
1390 
1392 {
1393  BLOCK_START("BeingRecv::processIpResponse")
1394  if (actorManager == nullptr)
1395  {
1396  BLOCK_END("BeingRecv::processIpResponse")
1397  return;
1398  }
1399 
1400  Being *const dstBeing = actorManager->findBeing(
1401  msg.readBeingId("being id"));
1402  if (dstBeing != nullptr)
1403  {
1404  const std::string ip = ipToString(msg.readInt32("ip address"));
1405  dstBeing->setIp(ip);
1406  }
1407  else
1408  {
1409  msg.readInt32("ip address");
1410  DEBUGLOGSTR("invisible player?");
1411  }
1412 
1413  BLOCK_END("BeingRecv::processIpResponse")
1414 }
1415 
1417 {
1418  BLOCK_START("BeingRecv::processPvpSet")
1419  const BeingId id = msg.readBeingId("being id");
1420  const int rank = msg.readInt32("rank");
1421  int teamId = 0;
1422  teamId = msg.readInt32("team");
1423  if (actorManager != nullptr)
1424  {
1425  Being *const dstBeing = actorManager->findBeing(id);
1426  if (dstBeing != nullptr)
1427  {
1428  dstBeing->setPvpRank(rank);
1429  dstBeing->setTeamId(CAST_U16(teamId));
1430  dstBeing->addToCache();
1431  }
1432  }
1433  BLOCK_END("BeingRecv::processPvpSet")
1434 }
1435 
1437  Being *const being,
1438  const uint8_t type)
1439 {
1440  if (being == nullptr)
1441  return;
1442  switch (type)
1443  {
1444  case 0:
1445  being->setAction(BeingAction::STAND, 0);
1447  break;
1448 
1449  case 1:
1450  if (being->getCurrentAction() != BeingAction::DEAD)
1451  {
1452  being->setAction(BeingAction::DEAD, 0);
1453  being->recalcSpritesOrder();
1454  }
1455  break;
1456 
1457  case 2:
1458  being->setAction(BeingAction::SIT, 0);
1460  break;
1461 
1462  default:
1464  break;
1465  }
1466 }
1467 
1469 {
1470  BLOCK_START("BeingRecv::processSkillDamage")
1471  if (actorManager == nullptr)
1472  {
1473  BLOCK_END("BeingRecv::processSkillDamage")
1474  return;
1475  }
1476 
1477  const int id = msg.readInt16("skill id");
1478  Being *const srcBeing = actorManager->findBeing(
1479  msg.readBeingId("src being id"));
1480  Being *const dstBeing = actorManager->findBeing(
1481  msg.readBeingId("dst being id"));
1482  msg.readInt32("tick");
1483  msg.readInt32("src speed");
1484  msg.readInt32("dst speed");
1485  const int param1 = msg.readInt32("damage");
1486  const int level = msg.readInt16("skill level");
1487  msg.readInt16("div");
1488  msg.readUInt8("skill hit/type?");
1489  if (srcBeing != nullptr)
1490  srcBeing->handleSkill(dstBeing, param1, id, level);
1491  if (dstBeing != nullptr)
1492  dstBeing->takeDamage(srcBeing, param1, AttackType::SKILL, id, level);
1493  BLOCK_END("BeingRecv::processSkillDamage")
1494 }
1495 
1497  const uint8_t gender)
1498 {
1499  if (being == nullptr)
1500  return;
1501  switch (gender)
1502  {
1503  case 2:
1504  being->setGender(Gender::FEMALE);
1505  break;
1506  case 3:
1507  being->setGender(Gender::MALE);
1508  break;
1509  default:
1511  break;
1512  }
1513 }
1514 
1515 } // namespace TmwAthena
ActorManager * actorManager
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_U16
Definition: cast.h:29
#define CAST_S16
Definition: cast.h:28
#define CAST_S32
Definition: cast.h:30
#define CAST_U8
Definition: cast.h:27
Being * findBeing(const BeingId id) const
void destroy(ActorSprite *const actor)
void undelete(const ActorSprite *const actor)
bool isBlocked(const BeingId id) const
void erase(ActorSprite *const actor)
void setStatusEffectOpitons(const uint32_t option, const uint32_t opt1, const uint32_t opt2, const uint32_t opt3)
BeingId getId() const
Definition: actorsprite.h:64
void setStatusEffect(const int32_t index, const Enable active, const IsStart start)
Definition: being.h:96
void setKarma(const int karma)
Definition: being.h:1031
void setHairStyle(const unsigned int slot, const int id)
Definition: being.cpp:3372
void setWeaponId(const int id)
Definition: being.cpp:3135
Party * getParty() const
Definition: being.h:330
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 setGuildName(const std::string &name)
Definition: being.cpp:1196
void setMoveTime()
Definition: being.h:706
void setParty(Party *const party)
Definition: being.cpp:1307
uint8_t getDirectionDelayed() const
Definition: being.h:505
virtual void setTileCoords(const int x, const int y)
Definition: being.cpp:5010
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:941
uint8_t getDirection() const
Definition: being.h:494
void setLevel(const int n)
Definition: being.h:601
void updateSprite(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2771
void setHP(const int hp)
Definition: being.cpp:4334
void setWalkSpeed(const int speed)
Definition: being.h:452
int getHP() const
Definition: being.h:759
void setPvpRank(const unsigned int rank)
Definition: being.h:752
uint8_t calcDirection(const int dstX, const int dstY) const
Definition: being.cpp:1767
void setLook(const uint16_t look)
Definition: being.cpp:5004
void recalcSpritesOrder()
Definition: being.cpp:4359
void setName(const std::string &name)
Definition: being.cpp:1136
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:371
void takeDamage(Being *const attacker, const int amount, const AttackTypeT type, const int attackId, const int level)
Definition: being.cpp:667
void setOtherTime()
Definition: being.h:718
void setHairColor(const unsigned int slot, const ItemColor color)
Definition: being.cpp:3389
void setMaxHP(const int hp)
Definition: being.cpp:4343
const std::string & getName() const
Definition: being.h:232
bool isAlive() const
Definition: being.h:488
void setSpriteId(const unsigned int slot, const int id)
Definition: being.cpp:2789
void setTeamId(const uint16_t teamId)
Definition: being.cpp:5187
void setGuildPos(const std::string &pos)
Definition: being.cpp:1233
void setPartyName(const std::string &name)
Definition: being.cpp:5246
virtual void setGender(const GenderT gender)
Definition: being.cpp:3581
void setDirectionDelayed(const uint8_t direction)
Definition: being.h:502
void setActionTime(const int actionTime)
Definition: being.h:135
virtual void setGroupId(const int id)
Definition: being.cpp:5587
uint16_t getLook() const
Definition: being.h:922
BeingActionT getCurrentAction() const
Definition: being.h:482
void setIp(const std::string &ip)
Definition: being.h:746
void setAttackRange(const int range)
Definition: being.h:843
void setCachedDestination(const int dstX, const int dstY)
Definition: being.h:149
void handleSkill(Being *const victim, const int damage, const int skillId, const int skillLevel)
Definition: being.cpp:1050
void setManner(const int manner)
Definition: being.h:1037
void clearPath()
Definition: being.cpp:554
ActorTypeT getType() const
Definition: being.h:116
void setGuild(Guild *const guild)
Definition: being.cpp:1354
void setDestination(const int dstX, const int dstY)
Definition: being.cpp:540
void addToCache() const
Definition: being.cpp:3513
void clearGuilds()
Definition: being.cpp:1289
int getIntValue(const std::string &key) const
bool trigger(const int id, Being *const being, const int rotation)
static bool getEnableGuildBot()
Definition: guildmanager.h:56
static Guild * getGuild(const int16_t id)
Definition: guild.cpp:374
static std::string getKeyShortString(const std::string &key)
void followMoveTo(const Being *const being, const int x, const int y)
Being * getTarget() const
void imitateDirection(const Being *const being, const unsigned char dir)
void stopAttack(const bool keepAttack)
void imitateOutfit(const Being *const player, const int sprite) const
void checkNewName(Being *const being)
void imitateAction(const Being *const being, const BeingActionT &action)
virtual void requestNameById(const BeingId id) const =0
static uint8_t fromServerDirection(const uint8_t serverDir)
Definition: messagein.cpp:266
virtual bool haveNpcGender() const =0
virtual bool haveMove3() const =0
virtual bool haveMonsterAttackRange() const =0
virtual bool haveServerHp() const =0
static std::string keyName(const int number)
static bool enabled
Definition: party.h:63
void resetDamage(const std::string &name)
int getPortalIndex(const int x, const int y)
Definition: window.h:102
virtual void scheduleDelete()
Definition: window.cpp:831
Configuration paths
Window * deathNotice
EffectManager * effectManager
bool Enable
Definition: enable.h:30
GuildManager * guildManager
#define toInt(val, name)
Definition: intdefines.h:47
#define fromInt(val, name)
Definition: intdefines.h:46
const bool IsStart_true
Definition: isstart.h:30
uint16_t ItemColor
Definition: itemcolor.h:30
LocalPlayer * localPlayer
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:59
#define DEBUGLOGSTR(str)
Definition: logger.h:45
uint32_t guild
uint32_t party
volatile int tick_time
Definition: timer.cpp:53
bool msg(InputEvent &event)
Definition: chat.cpp:39
void processBeingChangeLookContinue(const Net::MessageIn &msg, Being *const dstBeing, const uint8_t type, const int id, const int id2, const int *const cards)
Definition: beingrecv.cpp:263
void applyPlayerAction(Net::MessageIn &msg, Being *const being, const uint8_t type)
Definition: beingrecv.cpp:2397
Being * createBeing(const BeingId id, const int job)
Definition: beingrecv.cpp:507
BeingId mSpawnId
Definition: beingrecv.cpp:58
@ UNSPECIFIED
Definition: gender.h:33
@ MALE
Definition: gender.h:31
@ FEMALE
Definition: gender.h:32
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
void processPlayerUpdate2(Net::MessageIn &msg)
Definition: beingrecv.cpp:386
void processBeingResurrect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1279
void applyPlayerAction(Net::MessageIn &msg, Being *const being, const uint8_t type)
Definition: beingrecv.cpp:1436
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:1135
void processIpResponse(Net::MessageIn &msg)
Definition: beingrecv.cpp:1391
void processSkillDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:1468
void processBeingMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:918
void processPlayerMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:528
void processPlayerUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:240
void processPvpSet(Net::MessageIn &msg)
Definition: beingrecv.cpp:1416
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1146
void processBeingVisible(Net::MessageIn &msg)
Definition: beingrecv.cpp:702
void processBeingSelfEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1353
void processSkillCastCancel(Net::MessageIn &msg)
Definition: beingrecv.cpp:1386
void processBeingSpawn(Net::MessageIn &msg)
Definition: beingrecv.cpp:1121
void processPlayerStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1246
void processBeingChangeLook(Net::MessageIn &msg)
Definition: beingrecv.cpp:78
void processBeingChangeLook2(Net::MessageIn &msg)
Definition: beingrecv.cpp:103
void processBeingChangeLookContinue(const Net::MessageIn &msg, Being *const dstBeing, const uint8_t type, const int id, const int id2)
Definition: beingrecv.cpp:138
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1171
void setServerGender(Being *const being, const uint8_t gender)
Definition: beingrecv.cpp:1496
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1315
void processBeingChangeDirection(Net::MessageIn &msg)
Definition: beingrecv.cpp:1215
static void setGm(Being *const dstBeing, const uint16_t gmstatus)
Definition: beingrecv.cpp:64
@ SPRITE_HAIR_COLOR
Definition: sprite.h:35
@ SPRITE_WEAPON
Definition: sprite.h:31
@ SPRITE_FLOOR
Definition: sprite.h:40
@ SPRITE_HEAD_TOP
Definition: sprite.h:33
@ SPRITE_SHOES
Definition: sprite.h:38
@ SPRITE_SHIELD
Definition: sprite.h:37
@ SPRITE_HEAD_MID
Definition: sprite.h:34
@ SPRITE_EVOL2
Definition: sprite.h:42
@ SPRITE_BODY
Definition: sprite.h:39
@ SPRITE_CLOTHES_COLOR
Definition: sprite.h:36
@ SPRITE_ROBE
Definition: sprite.h:41
@ SPRITE_HEAD_BOTTOM
Definition: sprite.h:32
Net::ServerFeatures * serverFeatures
Definition: net.cpp:101
OutfitWindow * outfitWindow
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
SocialWindow * socialWindow
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:86