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