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 
37 #include "gui/windows/okdialog.h"
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 OkDialog *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  {
69  if ((gmstatus & 0x80) != 0)
70  {
71  dstBeing->setGroupId(paths.getIntValue("gmDefaultLevel"));
72  dstBeing->setGM(true);
73  }
74  else
75  {
76  dstBeing->setGroupId(0);
77  dstBeing->setGM(false);
78  }
79  }
80  else
81  {
82  if ((gmstatus & 0x80) != 0)
83  dstBeing->setGM(true);
84  else
85  dstBeing->setGM(false);
86  }
87 }
88 
90 {
91  BLOCK_START("BeingRecv::processBeingChangeLook")
92  if (actorManager == nullptr)
93  {
94  BLOCK_END("BeingRecv::processBeingChangeLook")
95  return;
96  }
97 
98  Being *const dstBeing = actorManager->findBeing(
99  msg.readBeingId("being id"));
100 
101  const uint8_t type = msg.readUInt8("type");
102  const int16_t id = CAST_S16(msg.readUInt8("id"));
103  const int id2 = 1;
104 
105  if ((localPlayer == nullptr) || (dstBeing == nullptr))
106  {
107  BLOCK_END("BeingRecv::processBeingChangeLook")
108  return;
109  }
110  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
111  BLOCK_END("BeingRecv::processBeingChangeLook")
112 }
113 
115 {
116  BLOCK_START("BeingRecv::processBeingChangeLook")
117  if (actorManager == nullptr)
118  {
119  BLOCK_END("BeingRecv::processBeingChangeLook")
120  return;
121  }
122 
123  Being *const dstBeing = actorManager->findBeing(
124  msg.readBeingId("being id"));
125 
126  const uint8_t type = msg.readUInt8("type");
127  int id2 = 0;
128 
129  const int16_t id = msg.readInt16("id1");
130  if (type == 2)
131  {
132  id2 = msg.readInt16("id2");
133  }
134  else
135  {
136  msg.readInt16("id2");
137  id2 = 1;
138  }
139 
140  if ((localPlayer == nullptr) || (dstBeing == nullptr))
141  {
142  BLOCK_END("BeingRecv::processBeingChangeLook")
143  return;
144  }
145  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
146  BLOCK_END("BeingRecv::processBeingChangeLook")
147 }
148 
150  Being *const dstBeing,
151  const uint8_t type,
152  const int id,
153  const int id2)
154 {
155  if (dstBeing->getType() == ActorType::Player)
156  dstBeing->setOtherTime();
157 
158  switch (type)
159  {
160  case 0: // change race
161  dstBeing->setSubtype(fromInt(id, BeingTypeId),
162  dstBeing->getLook());
163  break;
164  case 1: // eAthena LOOK_HAIR
165  {
166  const uint16_t look = CAST_U16(id / 256);
167  const int hair = id % 256;
168  dstBeing->setHairStyle(SPRITE_HAIR_COLOR, hair * -1);
169  dstBeing->setLook(look);
170  break;
171  }
172  case 2: // Weapon ID in id, Shield ID in id2
173  dstBeing->setSpriteId(SPRITE_BODY,
174  id);
175  dstBeing->setWeaponId(id);
176  dstBeing->setSpriteId(SPRITE_FLOOR,
177  id2);
179  break;
180  case 3: // Change lower headgear for eAthena, pants for us
181  dstBeing->setSpriteId(SPRITE_WEAPON,
182  id);
184  break;
185  case 4: // Change upper headgear for eAthena, hat for us
187  id);
189  break;
190  case 5: // Change middle headgear for eathena, armor for us
192  id);
194  break;
195  case 6: // eAthena LOOK_HAIR_COLOR
197  fromInt(id, ItemColor));
198  break;
199  case 7: // Clothes color
200  // ignoring it
201  break;
202  case 8: // eAthena LOOK_SHIELD
203  dstBeing->setSpriteId(SPRITE_FLOOR,
204  id);
206  break;
207  case 9: // eAthena LOOK_SHOES
208  dstBeing->setSpriteId(SPRITE_HAIR,
209  id);
211  break;
212  case 10: // LOOK_GLOVES
213  dstBeing->setSpriteId(SPRITE_SHOES,
214  id);
216  break;
217  case 11: // LOOK_CAPE
218  dstBeing->setSpriteId(SPRITE_SHIELD,
219  id);
221  break;
222  case 12:
223  dstBeing->setSpriteId(SPRITE_HEAD_TOP,
224  id);
226  break;
227  case 13:
228  dstBeing->setSpriteId(SPRITE_HEAD_MID,
229  id);
231  break;
232  case 14:
233  dstBeing->setSpriteId(SPRITE_ROBE,
234  id);
236  break;
237  case 15:
238  dstBeing->setSpriteId(SPRITE_EVOL2,
239  id);
241  break;
242  case 16:
243  dstBeing->setLook(CAST_U16(id));
244  break;
245  default:
247  break;
248  }
249 }
250 
252 {
253  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
254  if ((actorManager == nullptr) || (localPlayer == nullptr))
255  {
256  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
257  return;
258  }
259 
260  // An update about a player, potentially including movement.
261  const BeingId id = msg.readBeingId("account id");
262  const int16_t speed = msg.readInt16("speed");
263  const uint32_t opt1 = msg.readInt16("opt1");
264  const uint32_t opt2 = msg.readInt16("opt2");
265  const uint32_t option = msg.readInt16("option");
266  const int16_t job = msg.readInt16("job");
267  int disguiseId = 0;
268  if (toInt(id, int) < 110000000 && job >= 1000)
269  disguiseId = job;
270 
271  Being *dstBeing = actorManager->findBeing(id);
272  if (dstBeing == nullptr)
273  {
274  if (actorManager->isBlocked(id) == true)
275  {
276  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
277  return;
278  }
279 
280  dstBeing = Ea::BeingRecv::createBeing(id, job);
281 
282  if (dstBeing == nullptr)
283  {
284  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
285  return;
286  }
287  }
288  else if (disguiseId != 0)
289  {
290  actorManager->undelete(dstBeing);
292  }
293 
294  uint8_t dir = dstBeing->getDirectionDelayed();
295  if (dir != 0u)
296  {
297  if (dir != dstBeing->getDirection())
298  dstBeing->setDirection(dir);
299  }
300 
301  if (Party *const party = localPlayer->getParty())
302  {
303  if (party->isMember(id))
304  dstBeing->setParty(party);
305  }
306 
307  dstBeing->setWalkSpeed(speed);
308 
309  const uint8_t hairStyle = msg.readUInt8("hair style");
310  const uint16_t look = msg.readUInt8("look");
311  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
312  const uint16_t weapon = msg.readInt16("weapon");
313  const uint16_t shield = msg.readInt16("shield");
314  const uint16_t headBottom = msg.readInt16("head bottom");
315 
316  const uint16_t headTop = msg.readInt16("head top");
317  const uint16_t headMid = msg.readInt16("head mid");
318  const ItemColor hairColor = fromInt(
319  msg.readUInt8("hair color"), ItemColor);
320  msg.readUInt8("unused");
321  msg.readInt32("unused");
322 
323  const int guild = msg.readInt32("guild");
324 
325  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
326  {
327  if (guild == 0)
328  dstBeing->clearGuilds();
329  else
330  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
331  }
332 
333  msg.readInt16("emblem");
334  dstBeing->setManner(msg.readInt16("manner"));
335  const uint32_t opt3 = msg.readInt16("opt3");
336  dstBeing->setKarma(msg.readUInt8("karma"));
337  // reserving bit for future usage
338  dstBeing->setGender(Being::intToGender(
339  CAST_U8(msg.readUInt8("gender") & 3)));
340 
341  if (disguiseId == 0)
342  {
343  // Set these after the gender, as the sprites may be gender-specific
344  dstBeing->updateSprite(SPRITE_BODY,
345  weapon,
346  std::string());
347  dstBeing->setWeaponId(weapon);
348  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
349  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
350  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
351  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
352  if (hairStyle == 0)
353  {
355  0,
356  std::string());
357  }
358  else
359  {
361  hairStyle * -1,
362  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
363  }
364  dstBeing->setHairColor(hairColor);
365  }
366  localPlayer->imitateOutfit(dstBeing, -1);
367 
368  uint16_t x, y;
369  msg.readCoordinates(x, y, dir, "position");
370  dstBeing->setTileCoords(x, y);
371  dstBeing->setDirection(dir);
372 
373  localPlayer->imitateDirection(dstBeing, dir);
374 
375  const uint16_t gmstatus = msg.readInt16("gm status");
376 
377  setGm(dstBeing, gmstatus);
378 
379  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
380  const int level = CAST_S32(msg.readUInt8("level"));
381  if (level != 0)
382  dstBeing->setLevel(level);
383 
384  msg.readUInt8("unused");
385 
386  dstBeing->setActionTime(tick_time);
387 
388  dstBeing->setStatusEffectOpitons(option,
389  opt1,
390  opt2,
391  opt3);
392 
393  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
394 }
395 
397 {
398  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
399  if ((actorManager == nullptr) || (localPlayer == nullptr))
400  {
401  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
402  return;
403  }
404 
405  // An update about a player, potentially including movement.
406  const BeingId id = msg.readBeingId("account id");
407  const int16_t speed = msg.readInt16("speed");
408  const uint32_t opt1 = msg.readInt16("opt1");
409  const uint32_t opt2 = msg.readInt16("opt2");
410  const uint32_t option = msg.readInt16("option");
411  const int16_t job = msg.readInt16("job");
412  int disguiseId = 0;
413  if (toInt(id, int) < 110000000 && job >= 1000)
414  disguiseId = job;
415 
416  Being *dstBeing = actorManager->findBeing(id);
417  if (dstBeing == nullptr)
418  {
419  if (actorManager->isBlocked(id) == true)
420  {
421  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
422  return;
423  }
424 
425  dstBeing = Ea::BeingRecv::createBeing(id, job);
426 
427  if (dstBeing == nullptr)
428  {
429  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
430  return;
431  }
432  }
433  else if (disguiseId != 0)
434  {
435  actorManager->undelete(dstBeing);
437  }
438 
439  uint8_t dir = dstBeing->getDirectionDelayed();
440  if (dir != 0u)
441  {
442  if (dir != dstBeing->getDirection())
443  dstBeing->setDirection(dir);
444  }
445 
446  if (Party *const party = localPlayer->getParty())
447  {
448  if (party->isMember(id))
449  dstBeing->setParty(party);
450  }
451 
452  dstBeing->setWalkSpeed(speed);
453 
454  const uint8_t hairStyle = msg.readUInt8("hair style");
455  const uint16_t look = msg.readUInt8("look");
456  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
457  const uint16_t weapon = msg.readInt16("weapon");
458  const uint16_t shield = msg.readInt16("shield");
459  const uint16_t headBottom = msg.readInt16("head bottom");
460  const uint16_t headTop = msg.readInt16("head top");
461  const uint16_t headMid = msg.readInt16("head mid");
462  const ItemColor hairColor = fromInt(
463  msg.readUInt8("hair color"), ItemColor);
464  msg.readUInt8("unused");
465  msg.readInt32("unused");
466 
467  const int guild = msg.readInt32("guild");
468 
469  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
470  {
471  if (guild == 0)
472  dstBeing->clearGuilds();
473  else
474  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
475  }
476 
477  msg.readInt16("emblem");
478  dstBeing->setManner(msg.readInt16("manner"));
479  const uint32_t opt3 = msg.readInt16("opt3");
480  dstBeing->setKarma(msg.readUInt8("karma"));
481  // reserving bit for future usage
482  dstBeing->setGender(Being::intToGender(
483  CAST_U8(msg.readUInt8("gender") & 3)));
484 
485  if (disguiseId == 0)
486  {
487  // Set these after the gender, as the sprites may be gender-specific
488  dstBeing->updateSprite(SPRITE_BODY,
489  weapon,
490  std::string());
491  dstBeing->setWeaponId(weapon);
492  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
493  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
494  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
495  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
496  if (hairStyle == 0)
497  {
499  0,
500  std::string());
501  }
502  else
503  {
505  hairStyle * -1,
506  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
507  }
508  dstBeing->setHairColor(hairColor);
509  }
510  localPlayer->imitateOutfit(dstBeing, -1);
511 
512  uint16_t x, y;
513  msg.readCoordinates(x, y, dir, "position");
514  dstBeing->setTileCoords(x, y);
515  dstBeing->setDirection(dir);
516 
517  localPlayer->imitateDirection(dstBeing, dir);
518 
519  const uint16_t gmstatus = msg.readInt16("gm status");
520 
521  setGm(dstBeing, gmstatus);
522 
523  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
524  const int level = CAST_S32(msg.readUInt8("level"));
525  if (level != 0)
526  dstBeing->setLevel(level);
527 
528  dstBeing->setActionTime(tick_time);
529  dstBeing->setStatusEffectOpitons(option,
530  opt1,
531  opt2,
532  opt3);
533 
534  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
535 }
536 
538 {
539  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
540  if ((actorManager == nullptr) || (localPlayer == nullptr))
541  {
542  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
543  return;
544  }
545 
546  // An update about a player, potentially including movement.
547  const BeingId id = msg.readBeingId("account id");
548  const int16_t speed = msg.readInt16("speed");
549  const uint32_t opt1 = msg.readInt16("opt1");
550  const uint32_t opt2 = msg.readInt16("opt2");
551  const uint32_t option = msg.readInt16("option");
552  const int16_t job = msg.readInt16("job");
553  int disguiseId = 0;
554  if (toInt(id, int) < 110000000 && job >= 1000)
555  disguiseId = job;
556 
557  Being *dstBeing = actorManager->findBeing(id);
558  if (dstBeing == nullptr)
559  {
560  if (actorManager->isBlocked(id) == true)
561  {
562  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
563  return;
564  }
565 
566  dstBeing = Ea::BeingRecv::createBeing(id, job);
567 
568  if (dstBeing == nullptr)
569  {
570  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
571  return;
572  }
573  }
574  else if (disguiseId != 0)
575  {
576  actorManager->undelete(dstBeing);
578  }
579 
580  const uint8_t dir = dstBeing->getDirectionDelayed();
581  if (dir != 0u)
582  {
583  if (dir != dstBeing->getDirection())
584  dstBeing->setDirection(dir);
585  }
586 
587  if (Party *const party = localPlayer->getParty())
588  {
589  if (party->isMember(id))
590  dstBeing->setParty(party);
591  }
592 
593  dstBeing->setWalkSpeed(speed);
594 
595  const uint8_t hairStyle = msg.readUInt8("hair style");
596  const uint16_t look = msg.readUInt8("look");
597  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
598  const uint16_t weapon = msg.readInt16("weapon");
599  const uint16_t shield = msg.readInt16("shield");
600  const uint16_t headBottom = msg.readInt16("head bottom");
601 
602  msg.readInt32("tick");
603 
604  const uint16_t headTop = msg.readInt16("head top");
605  const uint16_t headMid = msg.readInt16("head mid");
606  const ItemColor hairColor = fromInt(
607  msg.readUInt8("hair color"), ItemColor);
608  msg.readUInt8("unused");
609  msg.readInt32("unused");
610 
611  const int guild = msg.readInt32("guild");
612 
613  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
614  {
615  if (guild == 0)
616  dstBeing->clearGuilds();
617  else
618  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
619  }
620 
621  msg.readInt16("emblem");
622  dstBeing->setManner(msg.readInt16("manner"));
623  const uint32_t opt3 = msg.readInt16("opt3");
624  dstBeing->setKarma(msg.readUInt8("karma"));
625  // reserving bit for future usage
626  dstBeing->setGender(Being::intToGender(
627  CAST_U8(msg.readUInt8("gender") & 3)));
628 
629  if (disguiseId == 0)
630  {
631  // Set these after the gender, as the sprites may be gender-specific
632  dstBeing->updateSprite(SPRITE_BODY,
633  weapon,
634  std::string());
635  dstBeing->setWeaponId(weapon);
636  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
637  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
638  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
639  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
640  if (hairStyle == 0)
641  {
643  0,
644  std::string());
645  }
646  else
647  {
649  hairStyle * -1,
650  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
651  }
652  dstBeing->setHairColor(hairColor);
653  }
654  localPlayer->imitateOutfit(dstBeing, -1);
655 
656  uint16_t srcX, srcY, dstX, dstY;
657  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "moving path");
658 
659  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
660 
661  dstBeing->setTileCoords(srcX, srcY);
662  dstBeing->setDestination(dstX, dstY);
663 
664  // because server don't send direction in move packet,
665  // we fixing it
666 
667  if (srcX != dstX || srcY != dstY)
668  {
669  const int d = dstBeing->calcDirection(dstX, dstY);
670 
671  if ((d != 0) && dstBeing->getDirection() != d)
672  dstBeing->setDirectionDelayed(CAST_U8(d));
673  }
674 
677  if (localPlayer->getDirection() != dstBeing->getDirection())
678  {
679  localPlayer->imitateDirection(dstBeing,
680  dstBeing->getDirection());
681  }
682 
683  const uint16_t gmstatus = msg.readInt16("gm status");
684 
685  setGm(dstBeing, gmstatus);
686 
687  msg.readUInt8("unused");
688 
689  const int level = CAST_S32(msg.readUInt8("level"));
690  if (level != 0)
691  dstBeing->setLevel(level);
692 
693  msg.readUInt8("unused");
694 
695  if (dstBeing->getType() != ActorType::Player)
696  dstBeing->setActionTime(tick_time);
697 
698  dstBeing->setStatusEffectOpitons(option,
699  opt1,
700  opt2,
701  opt3);
702 
703  if (dstBeing->getType() == ActorType::Player)
704  dstBeing->setMoveTime();
705  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
706 }
707 
709 {
710  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
711  if (actorManager == nullptr)
712  {
713  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
714  return;
715  }
716 
717  BeingId spawnId;
718 
719  // Information about a being in range
720  const BeingId id = msg.readBeingId("being id");
721  if (id == Ea::BeingRecv::mSpawnId)
722  spawnId = Ea::BeingRecv::mSpawnId;
723  else
724  spawnId = BeingId_zero;
726  int16_t speed = msg.readInt16("speed");
727  const uint32_t opt1 = msg.readInt16("opt1");
728  const uint32_t opt2 = msg.readInt16("opt2");
729  const uint32_t option = msg.readInt16("option");
730  const int16_t job = msg.readInt16("class");
731  int disguiseId = 0;
732  if (id == localPlayer->getId() && job >= 1000)
733  disguiseId = job;
734 
735  Being *dstBeing = actorManager->findBeing(id);
736 
737  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
738  && !dstBeing->isAlive())
739  {
740  actorManager->destroy(dstBeing);
741  actorManager->erase(dstBeing);
742  dstBeing = nullptr;
743  }
744 
745  if (dstBeing == nullptr)
746  {
747  // Being with id >= 110000000 and job 0 are better
748  // known as ghosts, so don't create those.
749  if (job == 0 && toInt(id, int) >= 110000000)
750  {
751  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
752  return;
753  }
754 
755  if (actorManager->isBlocked(id) == true)
756  {
757  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
758  return;
759  }
760 
761  dstBeing = Ea::BeingRecv::createBeing(id, job);
762 
763  if (dstBeing == nullptr)
764  {
765  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
766  return;
767  }
768  }
769  else
770  {
771  if (dstBeing->getType() == ActorType::Npc)
772  {
773  actorManager->undelete(dstBeing);
775  }
776  }
777 
778  if (dstBeing->getType() == ActorType::Player)
779  dstBeing->setMoveTime();
780 
781  if (spawnId != BeingId_zero)
782  {
783  dstBeing->setAction(BeingAction::SPAWN, 0);
784  }
785  else
786  {
787  dstBeing->clearPath();
788  dstBeing->setActionTime(tick_time);
789  dstBeing->setAction(BeingAction::STAND, 0);
790  }
791 
792  // Prevent division by 0 when calculating frame
793  if (speed == 0)
794  speed = 150;
795 
796  const uint8_t hairStyle = msg.readUInt8("hair style");
797  const uint16_t look = msg.readUInt8("look");
798  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
799  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
800  localPlayer->checkNewName(dstBeing);
801  dstBeing->setWalkSpeed(speed);
802  const uint16_t weapon = msg.readInt16("weapon");
803  const uint16_t headBottom = msg.readInt16("head bottom");
804 
805  const uint16_t shield = msg.readInt16("shield");
806  const uint16_t headTop = msg.readInt16("head top");
807  const uint16_t headMid = msg.readInt16("head mid");
808  const ItemColor hairColor = fromInt(msg.readUInt8("hair color"),
809  ItemColor);
810  msg.readUInt8("unused");
811  const uint16_t shoes = msg.readInt16("shoes / clothes color");
812 
813  uint16_t gloves;
814  if (dstBeing->getType() == ActorType::Monster)
815  {
817  {
818  const int hp = msg.readInt32("hp");
819  const int maxHP = msg.readInt32("max hp");
820  if ((hp != 0) && (maxHP != 0))
821  {
822  dstBeing->setMaxHP(maxHP);
823  const int oldHP = dstBeing->getHP();
824  if ((oldHP == 0) || oldHP > hp)
825  dstBeing->setHP(hp);
826  }
827  }
828  else
829  {
830  msg.readInt32("unused");
831  msg.readInt32("unused");
832  }
833  gloves = 0;
834  }
835  else
836  {
837  gloves = msg.readInt16("gloves / head dir");
838  msg.readInt32("guild");
839  msg.readInt16("guild emblem");
840  }
841 
842  dstBeing->setManner(msg.readInt16("manner"));
843  const uint32_t opt3 = msg.readInt16("opt3");
845  && dstBeing->getType() == ActorType::Monster)
846  {
847  const int attackRange = CAST_S32(
848  msg.readUInt8("attack range (was karma)"));
849  dstBeing->setAttackRange(attackRange);
850  }
851  else
852  {
853  dstBeing->setKarma(msg.readUInt8("karma"));
854  }
855  uint8_t gender = msg.readUInt8("gender");
856 
857  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
858  {
859  // reserving bits for future usage
860  gender &= 3;
861  dstBeing->setGender(Being::intToGender(gender));
862  // Set these after the gender, as the sprites may be gender-specific
863  if (hairStyle == 0)
864  {
865  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
866  }
867  else
868  {
870  hairStyle * -1,
871  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
872  }
873  dstBeing->setHairColor(hairColor);
874  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
875  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
876  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
877  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
878  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
879  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
880  dstBeing->setWeaponId(weapon);
881  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
882  }
883  else if (dstBeing->getType() == ActorType::Npc
885  {
886  setServerGender(dstBeing, gender);
887  }
888 
889  uint8_t dir;
890  uint16_t x, y;
891  msg.readCoordinates(x, y, dir, "position");
892  dstBeing->setTileCoords(x, y);
893 
894  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
895  {
896  const int num = socialWindow->getPortalIndex(x, y);
897  if (num >= 0)
898  {
900  OutfitWindow::keyName(num)));
901  }
902  else
903  {
904  dstBeing->setName("");
905  }
906  }
907 
908  dstBeing->setDirection(dir);
909 
910  msg.readUInt8("unknown");
911  msg.readUInt8("unknown");
912  msg.readUInt8("unknown");
913  msg.readUInt8("unknown");
914  msg.readUInt8("unknown");
915 
916  dstBeing->setStatusEffectOpitons(option,
917  opt1,
918  opt2,
919  opt3);
920  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
921 }
922 
924 {
925  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
926  if (actorManager == nullptr)
927  {
928  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
929  return;
930  }
931 
932  BeingId spawnId;
933 
934  // Information about a being in range
935  const BeingId id = msg.readBeingId("being id");
936  if (id == Ea::BeingRecv::mSpawnId)
937  spawnId = Ea::BeingRecv::mSpawnId;
938  else
939  spawnId = BeingId_zero;
941  int16_t speed = msg.readInt16("speed");
942  const uint32_t opt1 = msg.readInt16("opt1");
943  const uint32_t opt2 = msg.readInt16("opt2");
944  const uint32_t option = msg.readInt16("option");
945  const int16_t job = msg.readInt16("class");
946  int disguiseId = 0;
947  if (id == localPlayer->getId() && job >= 1000)
948  disguiseId = job;
949 
950  Being *dstBeing = actorManager->findBeing(id);
951 
952  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
953  && !dstBeing->isAlive())
954  {
955  actorManager->destroy(dstBeing);
956  actorManager->erase(dstBeing);
957  dstBeing = nullptr;
958  }
959 
960  if (dstBeing == nullptr)
961  {
962  // Being with id >= 110000000 and job 0 are better
963  // known as ghosts, so don't create those.
964  if (job == 0 && toInt(id, int) >= 110000000)
965  {
966  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
967  return;
968  }
969 
970  if (actorManager->isBlocked(id) == true)
971  {
972  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
973  return;
974  }
975 
976  dstBeing = Ea::BeingRecv::createBeing(id, job);
977 
978  if (dstBeing == nullptr)
979  {
980  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
981  return;
982  }
983  }
984  else
985  {
986  if (dstBeing->getType() == ActorType::Npc)
987  {
988  actorManager->undelete(dstBeing);
990  }
991  }
992 
993  if (dstBeing->getType() == ActorType::Player)
994  dstBeing->setMoveTime();
995 
996  if (spawnId != BeingId_zero)
997  dstBeing->setAction(BeingAction::SPAWN, 0);
998 
999  // Prevent division by 0 when calculating frame
1000  if (speed == 0)
1001  speed = 150;
1002 
1003  const uint8_t hairStyle = msg.readUInt8("hair style");
1004  const uint16_t look = msg.readUInt8("look");
1005  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
1006  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
1007  localPlayer->checkNewName(dstBeing);
1008  dstBeing->setWalkSpeed(speed);
1009  const uint16_t weapon = msg.readInt16("weapon");
1010  const uint16_t headBottom = msg.readInt16("head bottom");
1011 
1012  msg.readInt32("tick");
1013 
1014  const uint16_t shield = msg.readInt16("shield");
1015  const uint16_t headTop = msg.readInt16("head top");
1016  const uint16_t headMid = msg.readInt16("head mid");
1017  const ItemColor hairColor = fromInt(
1018  msg.readUInt8("hair color"), ItemColor);
1019  msg.readUInt8("unused");
1020  const uint16_t shoes = msg.readInt16("shoes / clothes color");
1021 
1022  uint16_t gloves;
1023  if (dstBeing->getType() == ActorType::Monster)
1024  {
1026  {
1027  const int hp = msg.readInt32("hp");
1028  const int maxHP = msg.readInt32("max hp");
1029  if ((hp != 0) && (maxHP != 0))
1030  {
1031  dstBeing->setMaxHP(maxHP);
1032  const int oldHP = dstBeing->getHP();
1033  if ((oldHP == 0) || oldHP > hp)
1034  dstBeing->setHP(hp);
1035  }
1036  }
1037  else
1038  {
1039  msg.readInt32("unused");
1040  msg.readInt32("unused");
1041  }
1042  gloves = 0;
1043  }
1044  else
1045  {
1046  gloves = msg.readInt16("gloves / head dir");
1047  msg.readInt32("guild");
1048  msg.readInt16("guild emblem");
1049  }
1050 
1051  dstBeing->setManner(msg.readInt16("manner"));
1052  const uint32_t opt3 = msg.readInt16("opt3");
1054  && dstBeing->getType() == ActorType::Monster)
1055  {
1056  const int attackRange = CAST_S32(
1057  msg.readUInt8("attack range (was karma)"));
1058  dstBeing->setAttackRange(attackRange);
1059  }
1060  else
1061  {
1062  dstBeing->setKarma(msg.readUInt8("karma"));
1063  }
1064  uint8_t gender = msg.readUInt8("gender");
1065 
1066  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
1067  {
1068  // reserving bits for future usage
1069  gender &= 3;
1070  dstBeing->setGender(Being::intToGender(gender));
1071  // Set these after the gender, as the sprites may be gender-specific
1072  if (hairStyle == 0)
1073  {
1074  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
1075  }
1076  else
1077  {
1078  dstBeing->updateSprite(SPRITE_HAIR_COLOR,
1079  hairStyle * -1,
1080  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
1081  }
1082  dstBeing->setHairColor(hairColor);
1083  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
1084  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
1085  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
1086  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
1087  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
1088  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
1089  dstBeing->setWeaponId(weapon);
1090  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
1091  }
1092  else if (dstBeing->getType() == ActorType::Npc
1094  {
1095  setServerGender(dstBeing, gender);
1096  }
1097 
1098  uint16_t srcX, srcY, dstX, dstY;
1099  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1100  if (disguiseId == 0)
1101  {
1102  dstBeing->setAction(BeingAction::STAND, 0);
1103  dstBeing->setTileCoords(srcX, srcY);
1104  if (serverFeatures->haveMove3())
1105  dstBeing->setCachedDestination(dstX, dstY);
1106  else
1107  dstBeing->setDestination(dstX, dstY);
1108  }
1109 
1110  msg.readUInt8("unknown");
1111  msg.readUInt8("unknown");
1112  msg.readUInt8("unknown");
1113  msg.readUInt8("unknown");
1114  msg.readUInt8("unknown");
1115 
1116  dstBeing->setStatusEffectOpitons(option,
1117  opt1,
1118  opt2,
1119  opt3);
1120  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
1121 }
1122 
1124 {
1125  BLOCK_START("BeingRecv::processBeingSpawn")
1126  // skipping this packet
1127  Ea::BeingRecv::mSpawnId = msg.readBeingId("being id");
1128  msg.readInt16("speed");
1129  msg.readInt16("opt1");
1130  msg.readInt16("opt2");
1131  msg.readInt16("option");
1132  msg.readInt16("disguise");
1133  msg.skip(25, "unused");
1134  BLOCK_END("BeingRecv::processBeingSpawn")
1135 }
1136 
1138 {
1139  msg.readInt32("src id");
1140  msg.readInt32("dst id");
1141  msg.readInt16("dst x");
1142  msg.readInt16("dst y");
1143  msg.readInt16("skill num");
1144  msg.readInt32("skill get p1");
1145  msg.readInt32("cast time");
1146 }
1147 
1149 {
1150  BLOCK_START("BeingRecv::processBeingStatusChange")
1151  if (actorManager == nullptr)
1152  {
1153  BLOCK_END("BeingRecv::processBeingStatusChange")
1154  return;
1155  }
1156 
1157  // Status change
1158  const uint16_t status = msg.readInt16("status");
1159  const BeingId id = msg.readBeingId("being id");
1160  const Enable flag = fromBool(
1161  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1162 
1163  Being *const dstBeing = actorManager->findBeing(id);
1164  if (dstBeing != nullptr)
1165  {
1166  // dont know on legacy servers is effect really started
1167  // or not. Because this always sending IsStart_true
1168  dstBeing->setStatusEffect(status, flag, IsStart_true);
1169  }
1170  BLOCK_END("BeingRecv::processBeingStatusChange")
1171 }
1172 
1174 {
1175  BLOCK_START("BeingRecv::processBeingMove2")
1176  if (actorManager == nullptr)
1177  {
1178  BLOCK_END("BeingRecv::processBeingMove2")
1179  return;
1180  }
1181 
1182  /*
1183  * A simplified movement packet, used by the
1184  * later versions of eAthena for both mobs and
1185  * players
1186  */
1187  Being *const dstBeing = actorManager->findBeing(
1188  msg.readBeingId("being id"));
1189 
1190  /*
1191  * This packet doesn't have enough info to actually
1192  * create a new being, so if the being isn't found,
1193  * we'll just pretend the packet didn't happen
1194  */
1195 
1196  if (dstBeing == nullptr)
1197  {
1198  BLOCK_END("BeingRecv::processBeingMove2")
1199  return;
1200  }
1201 
1202  uint16_t srcX, srcY, dstX, 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::OTHER);
1510  break;
1511  default:
1513  break;
1514  }
1515 }
1516 
1517 } // namespace TmwAthena
static bool enabled
virtual unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:74
uint16_t getLook() const
Definition: being.h:915
const ItemInfo & get(const int id)
Definition: itemdb.cpp:814
#define CAST_U8
Definition: cast.h:26
void setAttackRange(const int range)
Definition: being.h:836
Being * createBeing(const BeingId id, const int job)
Definition: beingrecv.cpp:500
BeingId mSpawnId
Definition: beingrecv.cpp:58
Definition: party.h:61
volatile int tick_time
Definition: timer.cpp:52
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:538
virtual BeingId readBeingId(const char *const str)=0
OutfitWindow * outfitWindow
void setTileCoords(const int x, const int y)
Definition: being.cpp:4980
#define fromInt(val, name)
Definition: intdefines.h:45
void setGuildName(const std::string &name)
Definition: being.cpp:1194
void processBeingChangeLookContinue(const Net::MessageIn &msg, Being *const dstBeing, const uint8_t type, const int id, const int id2)
Definition: beingrecv.cpp:149
BeingId getId() const
Definition: actorsprite.h:63
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1314
void setOtherTime()
Definition: being.h:711
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:1204
#define BLOCK_START(name)
Definition: perfomance.h:78
uint8_t calcDirection(const int dstX, const int dstY) const
Definition: being.cpp:1738
virtual void setGender(const GenderT gender)
Definition: being.cpp:3554
int BeingId
Definition: beingid.h:29
virtual int16_t readInt16(const char *const str)=0
virtual void setGroupId(const int id)
Definition: being.h:1080
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:323
uint16_t ItemColor
Definition: itemcolor.h:29
bool msg(InputEvent &event)
Definition: chat.cpp:38
uint8_t getDirection() const
Definition: being.h:487
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:89
void setWalkSpeed(const int speed)
Definition: being.h:445
void processPlayerStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1245
uint32_t party
virtual void readCoordinates(uint16_t &x, uint16_t &y, uint8_t &direction, const char *const str)
Definition: messagein.cpp:131
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:936
void setPartyName(const std::string &name)
Definition: being.cpp:5216
void addToCache() const
Definition: being.cpp:3486
virtual void setDirection(const uint8_t direction)
Definition: being.cpp:1661
void setHP(const int hp)
Definition: being.cpp:4309
void processBeingSpawn(Net::MessageIn &msg)
Definition: beingrecv.cpp:1123
void processBeingMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:923
#define toInt(val, name)
Definition: intdefines.h:46
void setDirectionDelayed(const uint8_t direction)
Definition: being.h:495
static std::string getKeyShortString(const std::string &key)
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1148
#define CAST_U16
Definition: cast.h:28
Net::ServerFeatures * serverFeatures
Definition: net.cpp:94
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:1260
OkDialog * deathNotice
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:254
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:739
virtual bool haveServerHp() const =0
virtual void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:163
#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:745
void processPvpSet(Net::MessageIn &msg)
Definition: beingrecv.cpp:1415
LocalPlayer * localPlayer
void processPlayerMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:537
virtual void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:201
GuildManager * guildManager
uint8_t getDirectionDelayed() const
Definition: being.h:498
void handleSkill(Being *const victim, const int damage, const int skillId, const int skillLevel)
Definition: being.cpp:1048
bool isAlive() const
Definition: being.h:481
static bool getEnableGuildBot()
Definition: guildmanager.h:55
BeingActionT getCurrentAction() const
Definition: being.h:475
void processPlayerUpdate2(Net::MessageIn &msg)
Definition: beingrecv.cpp:396
Being * findBeing(const BeingId id) const
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:1137
Net::BeingHandler * beingHandler
Definition: net.cpp:92
void stopAttack(const bool keepAttack)
virtual bool haveMonsterAttackRange() const =0
void processPlayerUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:251
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:2762
void setGM(const bool gm)
Definition: being.cpp:3639
virtual void setAction(const BeingActionT &action, const int attackId)
Definition: being.cpp:1525
int getHP() const
Definition: being.h:752
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1173
void setHairStyle(const unsigned int slot, const int id)
Definition: being.cpp:3345
void processBeingVisible(Net::MessageIn &msg)
Definition: beingrecv.cpp:708
SocialWindow * socialWindow
void setManner(const int manner)
Definition: being.h:1034
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:665
virtual void scheduleDelete()
Definition: window.cpp:826
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:2161
static std::string keyName(const int number)
void updateSprite(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2744
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:369
void setKarma(const int karma)
Definition: being.h:1028
void erase(ActorSprite *const actor)
void setParty(Party *const party)
Definition: being.cpp:1278
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:1134
virtual int32_t readInt32(const char *const str)=0
void recalcSpritesOrder()
Definition: being.cpp:4334
void setTeamId(const uint16_t teamId)
Definition: being.cpp:5157
virtual std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:219
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:4974
#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:356
void setHairColor(const unsigned int slot, const ItemColor color)
Definition: being.cpp:3362
static uint8_t fromServerDirection(const uint8_t serverDir)
Definition: messagein.cpp:101
virtual bool haveMove3() const =0
void processBeingChangeLook2(Net::MessageIn &msg)
Definition: beingrecv.cpp:114
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:64
void setWeaponId(const int id)
Definition: being.cpp:3108
EffectManager * effectManager
void setGuild(Guild *const guild)
Definition: being.cpp:1325
ActorManager * actorManager
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void setLevel(const int n)
Definition: being.h:594
Being * getTarget() const
void setMoveTime()
Definition: being.h:699
void clearPath()
Definition: being.cpp:552
void setMaxHP(const int hp)
Definition: being.cpp:4318