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/eathena/beingrecv.h"
24 
25 #include "actormanager.h"
26 #include "effectmanager.h"
27 #include "game.h"
28 #include "notifymanager.h"
29 #include "party.h"
30 
31 #include "being/mercenaryinfo.h"
32 
33 #include "const/utils/timer.h"
34 
36 
38 
39 #include "input/keyboardconfig.h"
40 
41 #include "gui/viewport.h"
42 
46 
47 #include "net/character.h"
48 #include "net/charserverhandler.h"
49 #include "net/messagein.h"
50 #include "net/serverfeatures.h"
51 
52 #include "net/ea/beingrecv.h"
53 
55 #include "net/eathena/sp.h"
56 #include "net/eathena/sprite.h"
57 
58 #include "resources/claninfo.h"
59 #include "resources/iteminfo.h"
60 
61 #include "resources/db/clandb.h"
62 #include "resources/db/itemdb.h"
63 
64 #include "resources/map/map.h"
65 
66 #include "utils/checkutils.h"
67 #include "utils/foreach.h"
68 #include "utils/timer.h"
69 
70 #include "debug.h"
71 
72 extern int serverVersion;
73 extern Window *deathNotice;
74 extern bool packets_re;
75 extern bool packets_main;
76 extern bool packets_zero;
77 extern int itemIdLen;
78 
79 namespace EAthena
80 {
81 
82 static void setBasicFields(Being *restrict const dstBeing,
83  const uint8_t gender,
84  const int hairStyle,
85  const ItemColor hairColor,
86  const uint32_t weapon,
87  const uint16_t headBottom,
88  const uint16_t headMid,
89  const uint16_t headTop,
90  const uint16_t shoes,
91  const uint16_t gloves,
92  const bool notMove) A_NONNULL(1);
93 static void setBasicFields(Being *restrict const dstBeing,
94  const uint8_t gender,
95  const int hairStyle,
96  const ItemColor hairColor,
97  const uint32_t weapon,
98  const uint16_t headBottom,
99  const uint16_t headMid,
100  const uint16_t headTop,
101  const uint16_t shoes,
102  const uint16_t gloves,
103  const bool updateSlots)
104 {
105  const ActorTypeT actorType = dstBeing->getType();
106  switch (actorType)
107  {
108  case ActorType::Player:
109  dstBeing->setGender(Being::intToGender(gender));
110  dstBeing->setHairColor(hairColor);
111  // Set these after the gender, as the sprites may be gender-specific
112  if (hairStyle == 0)
113  {
114  dstBeing->updateSprite(SPRITE_HAIR_COLOR,
115  0,
116  std::string());
117  }
118  else
119  {
120  dstBeing->updateSprite(SPRITE_HAIR_COLOR,
121  hairStyle * -1,
122  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
123  }
124  if (updateSlots)
125  {
126  dstBeing->updateSprite(SPRITE_WEAPON,
127  headBottom,
128  std::string());
129  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM,
130  headMid,
131  std::string());
132  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR,
133  headTop,
134  std::string());
135  dstBeing->updateSprite(SPRITE_HAIR,
136  shoes,
137  std::string());
138  dstBeing->updateSprite(SPRITE_SHOES,
139  gloves,
140  std::string());
141  dstBeing->updateSprite(SPRITE_BODY,
142  weapon,
143  std::string());
144  dstBeing->setWeaponId(weapon);
145  }
146  break;
147  case ActorType::Npc:
149  {
150  dstBeing->setGender(Being::intToGender(gender));
151  }
152  if (dstBeing->getAllowNpcEquipment())
153  {
154  dstBeing->setHairColor(hairColor);
155  dstBeing->setHairStyle(SPRITE_HAIR_COLOR, -hairStyle);
156  // for npc not checking updateSlots flag,
157  // probably because npc missing visible packet if moving
158  dstBeing->updateSprite(SPRITE_WEAPON,
159  headBottom,
160  std::string());
161  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM,
162  headMid,
163  std::string());
164  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR,
165  headTop,
166  std::string());
167  dstBeing->updateSprite(SPRITE_HAIR,
168  shoes,
169  std::string());
170  dstBeing->updateSprite(SPRITE_SHOES,
171  gloves,
172  std::string());
173  dstBeing->updateSprite(SPRITE_BODY,
174  weapon,
175  std::string());
176  dstBeing->setWeaponId(weapon);
177  }
178  break;
179  default:
180  case ActorType::Monster:
181  case ActorType::Portal:
182  case ActorType::Pet:
187  break;
189  case ActorType::Avatar:
190  case ActorType::Unknown:
191  reportAlways("Wrong being type detected: %d",
192  CAST_S32(actorType));
193  break;
194  }
195 }
196 
198 {
199  if (actorManager == nullptr)
200  return;
201 
202  Being *const dstBeing = actorManager->findBeing(
203  msg.readBeingId("being id"));
204  const uint8_t type = msg.readUInt8("type");
205 
206  const int id = msg.readItemId("id1");
207  unsigned int id2 = msg.readItemId("id2");
208  if (type != 2)
209  id2 = 1;
210 
211  if (localPlayer == nullptr || dstBeing == nullptr)
212  return;
213 
214  processBeingChangeLookContinue(msg, dstBeing, type, id, id2, nullptr);
215 }
216 
218 {
219  Being *dstBeing = nullptr;
220  int cards[maxCards];
221 
222  if (actorManager == nullptr)
223  { // here can be look from char server
225  const BeingId id = msg.readBeingId("being id");
226 
227  FOR_EACH (Net::Characters::iterator, it, chars)
228  {
229  const Net::Character *const character = *it;
230  if (character->dummy != nullptr &&
231  character->dummy->getId() == id)
232  {
233  dstBeing = character->dummy;
234  break;
235  }
236  }
237  }
238  else
239  {
240  dstBeing = actorManager->findBeing(
241  msg.readBeingId("being id"));
242  }
243 
244  const uint8_t type = msg.readUInt8("type");
245 
246  const int id = msg.readInt16("id1");
247  unsigned int id2 = msg.readInt16("id2");
248  if (type != 2)
249  id2 = 1;
250 
251  for (int f = 0; f < maxCards; f ++)
252  cards[f] = msg.readUInt16("card"); // +++ probably need use int32
253 
254  if (dstBeing == nullptr)
255  return;
256 
257  processBeingChangeLookContinue(msg, dstBeing, type, id, id2, &cards[0]);
258 }
259 
261  Being *const dstBeing,
262  const uint8_t type,
263  const int id,
264  const int id2,
265  const int *const cards)
266 {
267  if (dstBeing->getType() == ActorType::Player)
268  dstBeing->setOtherTime();
269 
270  switch (type)
271  {
272  // here should be used SPRITE_* constants
273  // but for now they conflicting with sprites
274  // SPRITE_* is same with server LOOK_*
275  case 0: // change race
276  dstBeing->setSubtype(fromInt(id, BeingTypeId),
277  dstBeing->getLook());
278  break;
279  case 1: // eAthena LOOK_HAIR
280  dstBeing->setHairColor(fromInt(id, ItemColor));
282  id * -1);
283  break;
284  case 2: // LOOK_WEAPON Weapon ID in id, Shield ID in id2
285  dstBeing->setSpriteCards(SPRITE_BODY,
286  id,
287  CardsList(cards));
288  dstBeing->setWeaponId(id);
289  dstBeing->setSpriteId(SPRITE_FLOOR,
290  id2);
291  if (localPlayer != nullptr)
293  break;
294  case 3: // LOOK_HEAD_BOTTOM
295  dstBeing->setSpriteCards(SPRITE_WEAPON,
296  id,
297  CardsList(cards));
298  if (localPlayer != nullptr)
300  break;
301  case 4: // LOOK_HEAD_TOP Change upper headgear for eAthena, hat for us
303  id,
304  CardsList(cards));
305  if (localPlayer != nullptr)
307  break;
308  case 5: // LOOK_HEAD_MID Change middle headgear for eathena,
309  // armor for us
311  id,
312  CardsList(cards));
313  if (localPlayer != nullptr)
315  break;
316  case 6: // eAthena LOOK_HAIR_COLOR
317  dstBeing->setHairColor(fromInt(id, ItemColor));
319  ItemDB::get(dstBeing->getSpriteID(
320  SPRITE_HAIR_COLOR)).getDyeColorsString(
321  fromInt(id, ItemColor)));
322  break;
323  case 7: // Clothes color. Now used as look
324  dstBeing->setLook(CAST_U8(id));
325  break;
326  case 8: // eAthena LOOK_SHIELD
327  dstBeing->setSpriteCards(SPRITE_FLOOR,
328  id,
329  CardsList(cards));
330  if (localPlayer != nullptr)
332  break;
333  case 9: // eAthena LOOK_SHOES
334  dstBeing->setSpriteCards(SPRITE_HAIR,
335  id,
336  CardsList(cards));
337  if (localPlayer != nullptr)
339  break;
340  case 10: // LOOK_GLOVES
341  dstBeing->setSpriteCards(SPRITE_SHOES,
342  id,
343  CardsList(cards));
344  if (localPlayer != nullptr)
346  break;
347  case 11: // LOOK_FLOOR
348  dstBeing->setSpriteCards(SPRITE_SHIELD,
349  id,
350  CardsList(cards));
351  if (localPlayer != nullptr)
353  break;
354  case 12: // LOOK_ROBE
356  id,
357  CardsList(cards));
358  if (localPlayer != nullptr)
360  break;
361  case 13: // COSTUME_HEAD_TOP
363  id,
364  CardsList(cards));
365  if (localPlayer != nullptr)
367  break;
368  case 14: // COSTUME_HEAD_MID
369  dstBeing->setSpriteCards(SPRITE_ROBE,
370  id,
371  CardsList(cards));
372  if (localPlayer != nullptr)
374  break;
375  case 15: // COSTUME_HEAD_LOW
376  dstBeing->setSpriteCards(SPRITE_EVOL2,
377  id,
378  CardsList(cards));
379  if (localPlayer != nullptr)
381  break;
382  case 16: // COSTUME_GARMENT
383  dstBeing->setSpriteCards(SPRITE_EVOL3,
384  id,
385  CardsList(cards));
386  if (localPlayer != nullptr)
388  break;
389  case 17: // ARMOR
390  dstBeing->setSpriteCards(SPRITE_EVOL4,
391  id,
392  CardsList(cards));
393  if (localPlayer != nullptr)
395  break;
396  case 18:
397  dstBeing->setSpriteCards(SPRITE_EVOL5,
398  id,
399  CardsList(cards));
400  if (localPlayer != nullptr)
402  break;
403  case 19:
404  dstBeing->setSpriteCards(SPRITE_EVOL6,
405  id,
406  CardsList(cards));
407  if (localPlayer != nullptr)
409  break;
410  default:
412  break;
413  }
414 }
415 
417 {
418  if (actorManager == nullptr)
419  return;
420 
421  // need set type based on id
423  if (msg.getVersion() >= 20091103)
424  {
425  msg.readInt16("len");
426  type = static_cast<BeingTypeT>(
427  msg.readUInt8("object type"));
428  }
429 
430  // Information about a being in range
431  const BeingId id = msg.readBeingId("being id");
432  if (msg.getVersion() >= 20131223)
433  msg.readBeingId("char id");
434  BeingId spawnId;
435  if (id == Ea::BeingRecv::mSpawnId)
436  spawnId = Ea::BeingRecv::mSpawnId;
437  else
438  spawnId = BeingId_zero;
440 
441  int16_t speed = msg.readInt16("speed");
442  const uint32_t opt1 = msg.readInt16("opt1");
443  // probably wrong effect usage
444  const uint32_t opt2 = msg.readInt16("opt2");
445  uint32_t option;
446  if (msg.getVersion() >= 20080102)
447  option = msg.readInt32("option");
448  else
449  option = msg.readInt16("option");
450  const int16_t job = msg.readInt16("class");
451 
452  Being *dstBeing = actorManager->findBeing(id);
453 
454  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
455  && !dstBeing->isAlive())
456  {
457  actorManager->destroy(dstBeing);
458  actorManager->erase(dstBeing);
459  dstBeing = nullptr;
460  }
461 
462  if (dstBeing == nullptr)
463  {
464  if (actorManager->isBlocked(id) == true)
465  return;
466 
467  dstBeing = createBeing2(msg, id, job, type);
468  if (dstBeing == nullptr)
469  return;
470  }
471  else
472  {
473  // undeleting marked for deletion being
474  if (dstBeing->getType() == ActorType::Npc)
475  actorManager->undelete(dstBeing);
476  }
477 
478  if (dstBeing->getType() == ActorType::Player)
479  dstBeing->setMoveTime();
480 
481  if (spawnId != BeingId_zero)
482  {
483  dstBeing->setAction(BeingAction::SPAWN, 0);
484  }
485  else
486  {
487  dstBeing->clearPath();
488  dstBeing->setActionTime(tick_time);
489  dstBeing->setAction(BeingAction::STAND, 0);
490  }
491 
492  // Prevent division by 0 when calculating frame
493  if (speed == 0)
494  speed = 150;
495 
496  dstBeing->setWalkSpeed(speed);
497  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
498  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
499  localPlayer->checkNewName(dstBeing);
500 
501  const int hairStyle = msg.readInt16("hair style");
502  uint32_t weapon;
503  if (msg.getVersion() >= 7)
504  {
505  weapon = msg.readItemId("weapon");
506  msg.readItemId("shield");
507  }
508  else
509  {
510  weapon = CAST_U32(msg.readInt16("weapon"));
511  }
512  const uint16_t headBottom = msg.readInt16("head bottom");
513  if (msg.getVersion() < 7)
514  msg.readInt16("shield");
515  const uint16_t headTop = msg.readInt16("head top");
516  const uint16_t headMid = msg.readInt16("head mid");
517  const ItemColor hairColor = fromInt(msg.readInt16("hair color"),
518  ItemColor);
519  const uint16_t shoes = msg.readInt16("shoes or clothes color?");
520 
521  const uint16_t gloves = msg.readInt16("head dir / gloves");
522  // may be use robe as gloves?
523  if (msg.getVersion() >= 20101124)
524  msg.readInt16("robe");
525  msg.readInt32("guild id");
526  msg.readInt16("guild emblem");
527  dstBeing->setManner(msg.readInt16("manner"));
528  uint32_t opt3;
529  if (msg.getVersion() >= 7)
530  opt3 = msg.readInt32("opt3");
531  else
532  opt3 = msg.readInt16("opt3");
533  dstBeing->setKarma(msg.readUInt8("karma"));
534  const uint8_t gender = CAST_U8(msg.readUInt8("gender") & 3);
535 
536  setBasicFields(dstBeing,
537  gender,
538  hairStyle,
539  hairColor,
540  weapon,
541  headBottom,
542  headMid,
543  headTop,
544  shoes,
545  gloves,
546  true);
547 
548  uint8_t dir;
549  uint16_t x, y;
550  msg.readCoordinates(x, y, dir, "position");
551  msg.readInt8("xs");
552  msg.readInt8("ys");
553  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
554  dstBeing->setTileCoords(x, y);
555 
556  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
557  {
558  const int num = socialWindow->getPortalIndex(x, y);
559  if (num >= 0)
560  {
562  OutfitWindow::keyName(num)));
563  }
564  else
565  {
566  dstBeing->setName("");
567  }
568  }
569 
570  dstBeing->setDirection(dir);
571 
572  const int level = CAST_S32(msg.readInt16("level"));
573  if (level != 0)
574  dstBeing->setLevel(level);
575  if (msg.getVersion() >= 20080102)
576  msg.readInt16("font");
577 
578  if (msg.getVersion() >= 20120221)
579  {
580  const int maxHP = msg.readInt32("max hp");
581  const int hp = msg.readInt32("hp");
582  dstBeing->setMaxHP(maxHP);
583  dstBeing->setHP(hp);
584  msg.readInt8("is boss");
585  }
586 
587  if (msg.getVersion() >= 20150513)
588  {
589  msg.readInt16("body2");
590  }
591  if (msg.getVersion() >= 20131223)
592  {
593  msg.readString(24, "name");
594  }
595 
596  dstBeing->setStatusEffectOpitons(option,
597  opt1,
598  opt2,
599  opt3);
600 }
601 
603 {
604  if (actorManager == nullptr)
605  return;
606 
607  if (msg.getVersion() >= 20091103)
608  msg.readInt16("len");
609  BeingTypeT type;
610  if (msg.getVersion() >= 20071106)
611  {
612  type = static_cast<BeingTypeT>(
613  msg.readUInt8("object type"));
614  }
615  else
616  {
617  // need detect type based on id
618  type = BeingType::MONSTER;
619  }
620 
621  // Information about a being in range
622  const BeingId id = msg.readBeingId("being id");
623  if (msg.getVersion() >= 20131223)
624  msg.readBeingId("char id");
625  BeingId spawnId;
626  if (id == Ea::BeingRecv::mSpawnId)
627  spawnId = Ea::BeingRecv::mSpawnId;
628  else
629  spawnId = BeingId_zero;
631  int16_t speed = msg.readInt16("speed");
632  const uint32_t opt1 = msg.readInt16("opt1");
633  // probably wrong effect usage
634  const uint32_t opt2 = msg.readInt16("opt2");
635  uint32_t option;
636  if (msg.getVersion() >= 7)
637  option = msg.readInt32("option");
638  else
639  option = msg.readInt16("option");
640  const int16_t job = msg.readInt16("class");
641 
642  Being *dstBeing = actorManager->findBeing(id);
643 
644  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
645  && !dstBeing->isAlive())
646  {
647  actorManager->destroy(dstBeing);
648  actorManager->erase(dstBeing);
649  dstBeing = nullptr;
650  }
651 
652  if (dstBeing == nullptr)
653  {
654  if (actorManager->isBlocked(id) == true)
655  return;
656 
657  dstBeing = createBeing2(msg, id, job, type);
658  if (dstBeing == nullptr)
659  return;
660  }
661  else
662  {
663  // undeleting marked for deletion being
664  if (dstBeing->getType() == ActorType::Npc)
665  actorManager->undelete(dstBeing);
666  }
667 
668  if (dstBeing->getType() == ActorType::Player)
669  dstBeing->setMoveTime();
670 
671  if (spawnId != BeingId_zero)
672  dstBeing->setAction(BeingAction::SPAWN, 0);
673 
674  // Prevent division by 0 when calculating frame
675  if (speed == 0)
676  speed = 150;
677 
678  dstBeing->setWalkSpeed(speed);
679  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
680  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
681  localPlayer->checkNewName(dstBeing);
682 
683  const int hairStyle = msg.readInt16("hair style");
684  uint32_t weapon;
685  if (msg.getVersion() >= 7)
686  {
687  weapon = msg.readItemId("weapon");
688  msg.readItemId("shield");
689  }
690  else
691  {
692  weapon = CAST_U32(msg.readInt16("weapon"));
693  }
694  const uint16_t headBottom = msg.readInt16("head bottom");
695  msg.readInt32("tick");
696  if (msg.getVersion() < 7)
697  msg.readInt16("shield");
698  const uint16_t headTop = msg.readInt16("head top");
699  const uint16_t headMid = msg.readInt16("head mid");
700  const ItemColor hairColor = fromInt(
701  msg.readInt16("hair color"), ItemColor);
702  const uint16_t shoes = msg.readInt16("shoes or clothes color?");
703 
704  const uint16_t gloves = msg.readInt16("head dir / gloves");
705  // may be use robe as gloves?
706  if (msg.getVersion() >= 20101124)
707  msg.readInt16("robe");
708  msg.readInt32("guild id");
709  msg.readInt16("guild emblem");
710  dstBeing->setManner(msg.readInt16("manner"));
711  uint32_t opt3;
712  if (msg.getVersion() >= 7)
713  opt3 = msg.readInt32("opt3");
714  else
715  opt3 = msg.readInt16("opt3");
716  dstBeing->setKarma(msg.readUInt8("karma"));
717  const uint8_t gender = CAST_U8(msg.readUInt8("gender") & 3);
718 
719  setBasicFields(dstBeing,
720  gender,
721  hairStyle,
722  hairColor,
723  weapon,
724  headBottom,
725  headMid,
726  headTop,
727  shoes,
728  gloves,
730 
731  uint16_t srcX, srcY, dstX, dstY;
732  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
733  msg.readUInt8("(sx<<4) | (sy&0x0f)");
734  msg.readInt8("xs");
735  msg.readInt8("ys");
736  dstBeing->setAction(BeingAction::STAND, 0);
737  dstBeing->setTileCoords(srcX, srcY);
738  if (localPlayer != nullptr)
739  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
740  if (serverFeatures->haveMove3())
741  dstBeing->setCachedDestination(dstX, dstY);
742  else
743  dstBeing->setDestination(dstX, dstY);
744 
745  // because server don't send direction in move packet, we fixing it
746 
747  uint8_t d = 0;
748  if (localPlayer != nullptr &&
749  srcX == dstX &&
750  srcY == dstY)
751  { // if player did one step from invisible area to visible,
752  // move path is broken
753  int x2 = localPlayer->getTileX();
754  int y2 = localPlayer->getTileY();
755  if (abs(x2 - srcX) > abs(y2 - srcY))
756  y2 = srcY;
757  else
758  x2 = srcX;
759  d = dstBeing->calcDirection(x2, y2);
760  }
761  else
762  {
763  d = dstBeing->calcDirection(dstX, dstY);
764  }
765  if ((d != 0u) && dstBeing->getDirection() != d)
766  dstBeing->setDirection(d);
767 
768  const int level = CAST_S32(msg.readInt16("level"));
769  if (level != 0)
770  dstBeing->setLevel(level);
771  if (msg.getVersion() >= 20080102)
772  msg.readInt16("font");
773  if (msg.getVersion() >= 20120221)
774  {
775  const int maxHP = msg.readInt32("max hp");
776  const int hp = msg.readInt32("hp");
777  dstBeing->setMaxHP(maxHP);
778  dstBeing->setHP(hp);
779  msg.readInt8("is boss");
780  }
781  if (msg.getVersion() >= 20150513)
782  {
783  msg.readInt16("body2");
784  }
785  if (msg.getVersion() >= 20131223)
786  {
787  msg.readString(24, "name");
788  }
789 
790  dstBeing->setStatusEffectOpitons(option,
791  opt1,
792  opt2,
793  opt3);
794 }
795 
797 {
798  if (actorManager == nullptr)
799  return;
800 
801  // need get type from id
803  if (msg.getVersion() >= 20091103)
804  {
805  msg.readInt16("len");
806  type = static_cast<BeingTypeT>(
807  msg.readUInt8("object type"));
808  }
809 
810  // Information about a being in range
811  const BeingId id = msg.readBeingId("being id");
812  if (msg.getVersion() >= 20131223)
813  {
814  msg.readBeingId("char id");
815  }
817  const BeingId spawnId = id;
818  int16_t speed = msg.readInt16("speed");
819  const uint32_t opt1 = msg.readInt16("opt1");
820  // probably wrong effect usage
821  const uint32_t opt2 = msg.readInt16("opt2");
822  uint32_t option;
823  if (msg.getVersion() >= 20080102)
824  option = msg.readInt32("option");
825  else
826  option = msg.readInt16("option");
827  const int16_t job = msg.readInt16("class");
828 
829  Being *dstBeing = actorManager->findBeing(id);
830 
831  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
832  && !dstBeing->isAlive())
833  {
834  actorManager->destroy(dstBeing);
835  actorManager->erase(dstBeing);
836  dstBeing = nullptr;
837  }
838 
839  if (dstBeing == nullptr)
840  {
841  if (actorManager->isBlocked(id) == true)
842  return;
843 
844  dstBeing = createBeing2(msg, id, job, type);
845  if (dstBeing == nullptr)
846  return;
847  }
848  else
849  {
850  // undeleting marked for deletion being
851  if (dstBeing->getType() == ActorType::Npc)
852  actorManager->undelete(dstBeing);
853  }
854 
855  if (dstBeing->getType() == ActorType::Player)
856  dstBeing->setMoveTime();
857 
858  if (spawnId != BeingId_zero)
859  dstBeing->setAction(BeingAction::SPAWN, 0);
860 
861  // Prevent division by 0 when calculating frame
862  if (speed == 0)
863  speed = 150;
864 
865  dstBeing->setWalkSpeed(speed);
866  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
867  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
868  localPlayer->checkNewName(dstBeing);
869 
870  const int hairStyle = msg.readInt16("hair style");
871  uint32_t weapon;
872  if (msg.getVersion() >= 7)
873  {
874  weapon = msg.readItemId("weapon");
875  msg.readItemId("shield");
876  }
877  else
878  {
879  weapon = CAST_U32(msg.readInt16("weapon"));
880  }
881  const uint16_t headBottom = msg.readInt16("head bottom");
882  if (msg.getVersion() < 7)
883  msg.readInt16("shield");
884  const uint16_t headTop = msg.readInt16("head top");
885  const uint16_t headMid = msg.readInt16("head mid");
886  const ItemColor hairColor = fromInt(
887  msg.readInt16("hair color"), ItemColor);
888  const uint16_t shoes = msg.readInt16("shoes or clothes color?");
889  const uint16_t gloves = msg.readInt16("head dir / gloves");
890  // may be use robe as gloves?
891  if (msg.getVersion() >= 20101124)
892  msg.readInt16("robe");
893  msg.readInt32("guild id");
894  msg.readInt16("guild emblem");
895  dstBeing->setManner(msg.readInt16("manner"));
896  uint32_t opt3;
897  if (msg.getVersion() >= 7)
898  opt3 = msg.readInt32("opt3");
899  else
900  opt3 = msg.readInt16("opt3");
901 
902  dstBeing->setKarma(msg.readUInt8("karma"));
903  const uint8_t gender = CAST_U8(msg.readUInt8("gender") & 3);
904 
905  setBasicFields(dstBeing,
906  gender,
907  hairStyle,
908  hairColor,
909  weapon,
910  headBottom,
911  headMid,
912  headTop,
913  shoes,
914  gloves,
915  true);
916 
917  uint8_t dir;
918  uint16_t x, y;
919  msg.readCoordinates(x, y, dir, "position");
920  msg.readInt8("xs");
921  msg.readInt8("ys");
922  dstBeing->setTileCoords(x, y);
923 
924  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
925  {
926  const int num = socialWindow->getPortalIndex(x, y);
927  if (num >= 0)
928  {
930  OutfitWindow::keyName(num)));
931  }
932  else
933  {
934  dstBeing->setName("");
935  }
936  }
937 
938  dstBeing->setDirection(dir);
939 
940  const int level = CAST_S32(msg.readInt16("level"));
941  if (level != 0)
942  dstBeing->setLevel(level);
943  if (msg.getVersion() >= 20080102)
944  msg.readInt16("font");
945  if (msg.getVersion() >= 20120221)
946  {
947  const int maxHP = msg.readInt32("max hp");
948  const int hp = msg.readInt32("hp");
949  dstBeing->setMaxHP(maxHP);
950  dstBeing->setHP(hp);
951  msg.readInt8("is boss");
952  }
953  if (msg.getVersion() >= 20150513)
954  {
955  msg.readInt16("body2");
956  }
957  if (msg.getVersion() >= 20131223)
958  {
959  msg.readString(24, "name");
960  }
961 
962  dstBeing->setStatusEffectOpitons(option,
963  opt1,
964  opt2,
965  opt3);
966 }
967 
969 {
970  const int16_t type = msg.readInt16("type");
971  const int flags = msg.readInt32("flags");
972  if (type == 0x28)
973  {
974  // +++ need get other flags from here
975  MapTypeProperty2 props;
976  props.data = CAST_U32(flags);
977  const Game *const game = Game::instance();
978  if (game == nullptr)
979  return;
980  Map *const map = game->getCurrentMap();
981  if (map == nullptr)
982  return;
983  map->setPvpMode(props.bits.party | (props.bits.guild * 2));
984  }
985 }
986 
988 {
989  const int16_t type = msg.readInt16("type");
990  if (type == 19)
992  else
994 }
995 
997 {
998  const BeingId srcId = msg.readBeingId("src id");
999  const BeingId dstId = msg.readBeingId("dst id");
1000  const int dstX = msg.readInt16("dst x");
1001  const int dstY = msg.readInt16("dst y");
1002  const int skillId = msg.readInt16("skill id");
1003  msg.readInt32("property"); // can be used to trigger effect
1004  const int castTime = msg.readInt32("cast time");
1005  if (msg.getVersion() >= 20091124)
1006  msg.readInt8("dispossable");
1007 
1009  srcId, dstId,
1010  dstX, dstY,
1011  skillId,
1012  1,
1013  0,
1015  castTime);
1016 }
1017 
1019 {
1020  msg.readInt16("len"); // for now unused
1021  const BeingId srcId = msg.readBeingId("src id");
1022  const BeingId dstId = msg.readBeingId("dst id");
1023  const int dstX = msg.readInt16("dst x");
1024  const int dstY = msg.readInt16("dst y");
1025  const int skillId = msg.readInt16("skill id");
1026  const int skillLevel = msg.readInt16("skill level");
1027  msg.readInt32("property"); // can be used to trigger effect
1028  const int castTime = msg.readInt32("cast time");
1029  const int range = msg.readInt32("skill range");
1030  const SkillType2::SkillType2 inf2 =
1031  static_cast<SkillType2::SkillType2>(msg.readInt32("inf2"));
1032 
1034  srcId, dstId,
1035  dstX, dstY,
1036  skillId,
1037  skillLevel,
1038  range,
1039  inf2,
1040  castTime);
1041 }
1042 
1044  const BeingId srcId,
1045  const BeingId dstId,
1046  const int dstX,
1047  const int dstY,
1048  const int skillId,
1049  const int skillLevel,
1050  const int range,
1051  const SkillType2::SkillType2 inf2,
1052  const int castTime)
1053 {
1054  if (effectManager == nullptr ||
1055  actorManager == nullptr)
1056  return;
1057 
1058  if (srcId == BeingId_zero)
1059  {
1061  return;
1062  }
1063  Being *const srcBeing = actorManager->findBeing(srcId);
1064  if (dstId != BeingId_zero)
1065  { // being to being
1066  Being *const dstBeing = actorManager->findBeing(dstId);
1067  if (srcBeing != nullptr)
1068  {
1069  srcBeing->handleSkillCasting(dstBeing, skillId, skillLevel);
1070  if (dstBeing != nullptr)
1071  {
1072  srcBeing->addCast(dstBeing->getTileX(),
1073  dstBeing->getTileY(),
1074  skillId,
1075  skillLevel,
1076  range,
1077  castTime / MILLISECONDS_IN_A_TICK);
1078  }
1079  }
1080  }
1081  else if (dstX != 0 || dstY != 0)
1082  { // being to position
1083  if (srcBeing != nullptr)
1084  srcBeing->setAction(BeingAction::CAST, skillId);
1086  skillLevel,
1087  dstX, dstY,
1088  castTime);
1089  if (srcBeing != nullptr)
1090  {
1091  srcBeing->addCast(dstX, dstY,
1092  skillId,
1093  skillLevel,
1094  range,
1095  castTime / MILLISECONDS_IN_A_TICK);
1096  }
1097  }
1098  if ((localPlayer != nullptr) &&
1099  srcBeing == localPlayer &&
1100  (inf2 & SkillType2::FreeCastAny) == 0)
1101  {
1103  }
1104 }
1105 
1107 {
1108  BLOCK_START("BeingRecv::processBeingStatusChange")
1109  if (actorManager == nullptr)
1110  {
1111  BLOCK_END("BeingRecv::processBeingStatusChange")
1112  return;
1113  }
1114 
1115  // Status change
1116  const uint16_t status = msg.readInt16("status");
1117  const BeingId id = msg.readBeingId("being id");
1118  const Enable flag = fromBool(
1119  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1120  if (msg.getVersion() >= 20120618)
1121  msg.readInt32("total");
1122  if (msg.getVersion() >= 20090121)
1123  {
1124  msg.readInt32("left");
1125  msg.readInt32("val1");
1126  msg.readInt32("val2");
1127  msg.readInt32("val3");
1128  }
1129 
1130  const IsStart start = msg.getVersion() == 20090121 ?
1132 
1133  Being *const dstBeing = actorManager->findBeing(id);
1134  if (dstBeing != nullptr)
1135  dstBeing->setStatusEffect(status, flag, start);
1136  BLOCK_END("BeingRecv::processBeingStatusChange")
1137 }
1138 
1140 {
1141  BLOCK_START("BeingRecv::processBeingMove2")
1142  if (actorManager == nullptr)
1143  {
1144  BLOCK_END("BeingRecv::processBeingMove2")
1145  return;
1146  }
1147 
1148  /*
1149  * A simplified movement packet, used by the
1150  * later versions of eAthena for both mobs and
1151  * players
1152  */
1153  Being *const dstBeing = actorManager->findBeing(
1154  msg.readBeingId("being id"));
1155 
1156  uint16_t srcX, srcY, dstX, dstY;
1157  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1158  msg.readUInt8("(sx<<4) | (sy&0x0f)");
1159  msg.readInt32("tick");
1160 
1161  /*
1162  * This packet doesn't have enough info to actually
1163  * create a new being, so if the being isn't found,
1164  * we'll just pretend the packet didn't happen
1165  */
1166 
1167  if (dstBeing == nullptr)
1168  {
1169  BLOCK_END("BeingRecv::processBeingMove2")
1170  return;
1171  }
1172 
1173  dstBeing->setTileCoords(srcX, srcY);
1174  if (localPlayer != nullptr)
1175  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
1176  if (serverFeatures->haveMove3())
1177  dstBeing->setCachedDestination(dstX, dstY);
1178  else
1179  dstBeing->setDestination(dstX, dstY);
1180  if (dstBeing->getType() == ActorType::Player)
1181  dstBeing->setMoveTime();
1182  BLOCK_END("BeingRecv::processBeingMove2")
1183 }
1184 
1186 {
1187  BLOCK_START("BeingRecv::processBeingAction2")
1188  if (actorManager == nullptr)
1189  {
1190  BLOCK_END("BeingRecv::processBeingAction2")
1191  return;
1192  }
1193 
1194  Being *const srcBeing = actorManager->findBeing(
1195  msg.readBeingId("src being id"));
1196  Being *const dstBeing = actorManager->findBeing(
1197  msg.readBeingId("dst being id"));
1198 
1199  msg.readInt32("tick");
1200  const int srcSpeed = msg.readInt32("src speed");
1201  msg.readInt32("dst speed");
1202  int param1;
1203  if (msg.getVersion() >= 20071113)
1204  param1 = msg.readInt32("damage");
1205  else
1206  param1 = msg.readInt16("damage");
1207  if (msg.getVersion() >= 20131223)
1208  msg.readUInt8("is sp damaged");
1209  msg.readInt16("count");
1210  const AttackTypeT type = static_cast<AttackTypeT>(
1211  msg.readUInt8("action"));
1212  if (msg.getVersion() >= 20071113)
1213  msg.readInt32("left damage");
1214  else
1215  msg.readInt16("left damage");
1216 
1217  switch (type)
1218  {
1219  case AttackType::HIT: // Damage
1220  case AttackType::CRITICAL: // Critical Damage
1221  case AttackType::MULTI: // Critical Damage
1223  case AttackType::REFLECT: // Reflected Damage
1224  case AttackType::FLEE: // Lucky Dodge
1225  case AttackType::SPLASH:
1226  case AttackType::SKILL:
1227  case AttackType::REPEATE:
1228  if (srcBeing != nullptr)
1229  {
1230  if (srcSpeed != 0 && srcBeing->getType() == ActorType::Player)
1231  srcBeing->setAttackDelay(srcSpeed);
1232  // attackid=1, type
1233  srcBeing->handleAttack(dstBeing, param1, 1);
1234  if (srcBeing->getType() == ActorType::Player)
1235  srcBeing->setAttackTime();
1236  }
1237  if (dstBeing != nullptr)
1238  {
1239  // level not present, using 1
1240  dstBeing->takeDamage(srcBeing, param1,
1241  static_cast<AttackTypeT>(type), 1, 1);
1242  }
1243  break;
1244 
1245  case AttackType::PICKUP:
1246  break;
1247 
1249  break;
1250 
1251  case AttackType::SIT:
1252  if (srcBeing != nullptr)
1253  {
1254  srcBeing->setAction(BeingAction::SIT, 0);
1255  if (srcBeing->getType() == ActorType::Player)
1256  {
1257  srcBeing->setMoveTime();
1258  if (localPlayer != nullptr)
1260  }
1261  }
1262  break;
1263 
1264  case AttackType::STAND:
1265  if (srcBeing != nullptr)
1266  {
1267  srcBeing->setAction(BeingAction::STAND, 0);
1268  if (srcBeing->getType() == ActorType::Player)
1269  {
1270  srcBeing->setMoveTime();
1271  if (localPlayer != nullptr)
1272  {
1273  localPlayer->imitateAction(srcBeing,
1275  }
1276  }
1277  }
1278  break;
1279  default:
1280  case AttackType::MISS:
1281  case AttackType::SKILLMISS:
1283  break;
1284  }
1285  BLOCK_END("BeingRecv::processBeingAction2")
1286 }
1287 
1289 {
1290  if (actorManager == nullptr)
1291  return;
1292  Being *const dstBeing = actorManager->findBeing(
1293  msg.readBeingId("being id"));
1294  int hp;
1295  int maxHP;
1296  if (msg.getVersion() >= 20100126)
1297  {
1298  hp = msg.readInt32("hp");
1299  maxHP = msg.readInt32("max hp");
1300  }
1301  else
1302  {
1303  hp = msg.readInt16("hp");
1304  maxHP = msg.readInt16("max hp");
1305  }
1306  if (dstBeing != nullptr)
1307  {
1308  dstBeing->setHP(hp);
1309  dstBeing->setMaxHP(maxHP);
1310  }
1311 }
1312 
1314 {
1315  if (actorManager == nullptr)
1316  return;
1317  Being *const dstBeing = actorManager->findBeing(
1318  msg.readBeingId("monster id"));
1319  const int hp = msg.readInt32("hp");
1320  const int maxHP = msg.readInt32("max hp");
1321  if (dstBeing != nullptr)
1322  {
1323  dstBeing->setHP(hp);
1324  dstBeing->setMaxHP(maxHP);
1325  }
1326 }
1327 
1329 {
1330  const int id = msg.readInt16("skill id");
1331  msg.readInt16("inf");
1332  msg.readInt16("unused");
1333  const int level = msg.readInt16("skill level");
1334  msg.readInt16("sp");
1335  msg.readInt16("range");
1336  msg.readString(24, "skill name");
1337  msg.readInt8("unused");
1338 
1339  if (localPlayer != nullptr)
1340  {
1341  localPlayer->handleSkill(localPlayer, 0, id, level);
1343  }
1344 }
1345 
1347 {
1349  // +++ here need window with rank tables.
1350  msg.readInt16("rank type");
1351  for (int f = 0; f < 10; f ++)
1352  msg.readString(24, "name");
1353  for (int f = 0; f < 10; f ++)
1354  msg.readInt32("points");
1355  msg.readInt32("my points");
1356 }
1357 
1359 {
1361  // +++ here need window with rank tables.
1362  for (int f = 0; f < 10; f ++)
1363  msg.readString(24, "name");
1364  for (int f = 0; f < 10; f ++)
1365  msg.readInt32("points");
1366 }
1367 
1369 {
1371  // +++ here need window with rank tables.
1372  for (int f = 0; f < 10; f ++)
1373  msg.readString(24, "name");
1374  for (int f = 0; f < 10; f ++)
1375  msg.readInt32("points");
1376 }
1377 
1379 {
1381  // +++ here need window with rank tables.
1382  for (int f = 0; f < 10; f ++)
1383  msg.readString(24, "name");
1384  for (int f = 0; f < 10; f ++)
1385  msg.readInt32("points");
1386 }
1387 
1389 {
1391  // +++ here need window with rank tables.
1392  for (int f = 0; f < 10; f ++)
1393  msg.readString(24, "name");
1394  for (int f = 0; f < 10; f ++)
1395  msg.readInt32("points");
1396 }
1397 
1399 {
1400  BLOCK_START("BeingRecv::processBeingChangeDirection")
1401  if (actorManager == nullptr)
1402  {
1403  BLOCK_END("BeingRecv::processBeingChangeDirection")
1404  return;
1405  }
1406 
1407  Being *const dstBeing = actorManager->findBeing(
1408  msg.readBeingId("being id"));
1409 
1410  msg.readInt16("head direction");
1411 
1412  const uint8_t dir = Net::MessageIn::fromServerDirection(
1413  CAST_U8(msg.readUInt8("player direction") & 0x0FU));
1414 
1415  if (dstBeing == nullptr)
1416  {
1417  BLOCK_END("BeingRecv::processBeingChangeDirection")
1418  return;
1419  }
1420 
1421  dstBeing->setDirection(dir);
1422  if (localPlayer != nullptr)
1423  localPlayer->imitateDirection(dstBeing, dir);
1424  BLOCK_END("BeingRecv::processBeingChangeDirection")
1425 }
1426 
1428 {
1429  if ((effectManager == nullptr) || (actorManager == nullptr))
1430  return;
1431 
1432  const BeingId id = msg.readBeingId("being id");
1433  Being *const being = actorManager->findBeing(id);
1434  if (being == nullptr)
1435  {
1436  msg.readInt32("effect type");
1437  return;
1438  }
1439 
1440  const int effectType = msg.readInt32("effect type");
1441 
1443  effectManager->trigger(effectType, being, 0);
1444 
1445  // +++ need dehard code effectType == 3
1446  if (effectType == 3 && being->getType() == ActorType::Player
1447  && (socialWindow != nullptr))
1448  { // reset received damage
1449  socialWindow->resetDamage(being->getName());
1450  }
1451 }
1452 
1454 {
1455  // +++ add new type of permanent effects?
1456  const int cnt = (msg.readInt16("len") - 9) / 2;
1457  if (cnt > 0)
1458  {
1460  }
1461  msg.readBeingId("being id");
1462  msg.readUInt8("enable");
1463  for (int f = 0; f < cnt; f ++)
1464  msg.readInt16("hat effect");
1465 }
1466 
1468 {
1470  // +++ need somhow show this effects.
1471  // type is not same with self/misc effect.
1472  msg.readBeingId("account id");
1473  msg.readInt32("effect type");
1474  msg.readInt32("num"); // effect variable
1475 }
1476 
1478 {
1480  // +++ need play this effect.
1481  msg.readString(24, "sound effect name");
1482  msg.readUInt8("type");
1483  msg.readInt32("unused");
1484  msg.readInt32("source being id");
1485 }
1486 
1488 {
1490  msg.readInt16("skill id");
1491  msg.readInt32("src id");
1492  msg.readInt16("val");
1493  msg.readInt16("x");
1494  msg.readInt16("y");
1495  msg.readInt32("tick");
1496 }
1497 
1499 {
1500  if (msg.getVersion() >= 20110718)
1501  msg.readInt16("len");
1502  const BeingId id = msg.readBeingId("skill unit id");
1503  const BeingId creatorId = msg.readBeingId("creator accound id");
1504  const int x = msg.readInt16("x");
1505  const int y = msg.readInt16("y");
1506  int job = 0;
1507  if (msg.getVersion() >= 20121212)
1508  job = msg.readInt32("job");
1509  if (msg.getVersion() >= 20110718)
1510  msg.readUInt8("radius");
1511  msg.readUInt8("visible");
1512  int level = 0;
1513  if (msg.getVersion() >= 20130731)
1514  level = msg.readUInt8("level");
1515  Being *const dstBeing = createBeing2(msg,
1516  id,
1517  job,
1519  if (dstBeing == nullptr)
1520  return;
1521  dstBeing->setAction(BeingAction::STAND, 0);
1522  dstBeing->setTileCoords(x, y);
1523  dstBeing->setLevel(level);
1524  dstBeing->setCreatorId(creatorId);
1525 }
1526 
1528 {
1529  BLOCK_START("BeingRecv::processPlayerStop")
1530  if (actorManager == nullptr)
1531  {
1532  BLOCK_END("BeingRecv::processPlayerStop")
1533  return;
1534  }
1535 
1536  // Change in players' flags
1537  const BeingId id = msg.readBeingId("account id");
1538  Being *const dstBeing = actorManager->findBeing(id);
1539  if (dstBeing == nullptr)
1540  {
1541  msg.readInt16("opt1");
1542  msg.readInt16("opt2");
1543  if (msg.getVersion() >= 7)
1544  msg.readInt32("option");
1545  else
1546  msg.readInt16("option");
1547  msg.readUInt8("karma");
1548  return;
1549  }
1550 
1551  const uint32_t opt1 = msg.readInt16("opt1");
1552  const uint32_t opt2 = msg.readInt16("opt2");
1553  uint32_t option;
1554  if (msg.getVersion() >= 7)
1555  option = msg.readInt32("option");
1556  else
1557  option = msg.readInt16("option");
1558  dstBeing->setKarma(msg.readUInt8("karma"));
1559 
1560  dstBeing->setStatusEffectOpitons(option,
1561  opt1,
1562  opt2);
1563  BLOCK_END("BeingRecv::processPlayerStop")
1564 }
1565 
1567 {
1568  if (actorManager == nullptr)
1569  return;
1570 
1571  // look like this function unused on server
1572 
1573  const BeingId id = msg.readBeingId("account id");
1574  Being *const dstBeing = actorManager->findBeing(id);
1575  if (dstBeing == nullptr)
1576  return;
1577 
1578  const uint32_t option = msg.readInt32("option");
1579  dstBeing->setLevel(msg.readInt32("level"));
1580  msg.readInt32("showEFST");
1581  dstBeing->setStatusEffectOpiton0(option);
1582 }
1583 
1585 {
1586  BLOCK_START("BeingRecv::processBeingResurrect")
1587  if (actorManager == nullptr ||
1588  localPlayer == nullptr)
1589  {
1590  BLOCK_END("BeingRecv::processBeingResurrect")
1591  return;
1592  }
1593 
1594  // A being changed mortality status
1595 
1596  const BeingId id = msg.readBeingId("being id");
1597  msg.readInt16("unused");
1598  Being *const dstBeing = actorManager->findBeing(id);
1599  if (dstBeing == nullptr)
1600  {
1601  DEBUGLOGSTR("insible player?");
1602  BLOCK_END("BeingRecv::processBeingResurrect")
1603  return;
1604  }
1605 
1606  // If this is player's current target, clear it.
1607  if (dstBeing == localPlayer->getTarget())
1608  localPlayer->stopAttack(false);
1609  if (dstBeing == localPlayer &&
1610  deathNotice != nullptr)
1611  {
1612  deathNotice->scheduleDelete();
1613  deathNotice = nullptr;
1614  }
1615 
1616  dstBeing->setAction(BeingAction::STAND, 0);
1617  BLOCK_END("BeingRecv::processBeingResurrect")
1618 }
1619 
1621 {
1622  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo")
1623  if (actorManager == nullptr)
1624  {
1625  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1626  return;
1627  }
1628 
1629  const BeingId beingId = msg.readBeingId("being id");
1630  const std::string name = msg.readString(24, "char name");
1631  actorManager->updateNameId(name, beingId);
1632  Being *const dstBeing = actorManager->findBeing(beingId);
1633  if (dstBeing != nullptr)
1634  {
1635  if (beingId == localPlayer->getId())
1636  {
1638  }
1639  dstBeing->setName(name);
1640  dstBeing->setPartyName(msg.readString(24, "party name"));
1641  dstBeing->setGuildName(msg.readString(24, "guild name"));
1642  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1643  dstBeing->addToCache();
1644  }
1645  else
1646  {
1647  msg.readString(24, "party name");
1648  msg.readString(24, "guild name");
1649  msg.readString(24, "guild pos");
1650  }
1651  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1652 }
1653 
1655 {
1656  const BeingId id = msg.readBeingId("skill unit id");
1657  if (actorManager == nullptr)
1658  return;
1659  Being *const dstBeing = actorManager->findBeing(id);
1660  if (dstBeing == nullptr)
1661  return;
1662  actorManager->destroy(dstBeing);
1663 }
1664 
1666 {
1667  uint16_t x, y;
1668  uint8_t dir;
1669  if (msg.getVersion() < 20071106)
1670  {
1671  msg.readBeingId("npc id");
1672  msg.skip(8, "unused");
1673  msg.readInt16("class?"); // 111
1674  msg.skip(30, "unused");
1675  msg.readCoordinates(x, y, dir, "position");
1676  msg.readUInt8("sx");
1677  msg.readUInt8("sy");
1678  msg.skip(3, "unused");
1679  return;
1680  }
1681  const BeingTypeT type = static_cast<BeingTypeT>(
1682  msg.readUInt8("object type"));
1683  const BeingId id = msg.readBeingId("npc id");
1684  msg.skip(8, "unused");
1685  const uint16_t job = msg.readInt16("class?"); // 111
1686  msg.skip(30, "unused");
1687  msg.readCoordinates(x, y, dir, "position");
1688  msg.readUInt8("sx");
1689  msg.readUInt8("sy");
1690  msg.skip(3, "unused");
1691 
1692  Being *const dstBeing = createBeing2(msg, id, job, type);
1693  if (dstBeing == nullptr)
1694  return;
1695  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
1696  dstBeing->setTileCoords(x, y);
1697  dstBeing->setDirection(dir);
1698 }
1699 
1701 {
1702  const BeingId id = msg.readBeingId("account id");
1703  const int type = msg.readInt16("type");
1704  const int value = msg.readInt32("value");
1705 
1706  if (actorManager == nullptr)
1707  return;
1708  Being *const dstBeing = actorManager->findBeing(id);
1709  if (dstBeing == nullptr)
1710  return;
1711 
1712  if (type != Sp::MANNER)
1713  {
1715  return;
1716  }
1717  dstBeing->setManner(value);
1718 }
1719 
1721 {
1722  BLOCK_START("BeingRecv::processBeingSelfEffect")
1723  if ((effectManager == nullptr) || (actorManager == nullptr))
1724  {
1725  BLOCK_END("BeingRecv::processBeingSelfEffect")
1726  return;
1727  }
1728 
1729  const BeingId id = msg.readBeingId("being id");
1730  Being *const being = actorManager->findBeing(id);
1731  if (being == nullptr)
1732  {
1733  DEBUGLOGSTR("insible player?");
1734  msg.readInt32("effect type");
1735  BLOCK_END("BeingRecv::processBeingSelfEffect")
1736  return;
1737  }
1738 
1739  const int effectType = msg.readInt32("effect type");
1741  effectManager->trigger(effectType, being, 0);
1742 
1743  BLOCK_END("BeingRecv::processBeingSelfEffect")
1744 }
1745 
1747 {
1748  if (actorManager == nullptr)
1749  return;
1750  const int len = msg.readInt16("len");
1751  if (len < 12)
1752  return;
1753  Being *const dstBeing = actorManager->findBeing(
1754  msg.readBeingId("monster id"));
1755  const int attackRange = msg.readInt32("range");
1756  if (dstBeing != nullptr)
1757  dstBeing->setAttackRange(attackRange);
1758 }
1759 
1761 {
1762  if (actorManager == nullptr)
1763  return;
1764  const int len = msg.readInt16("len");
1765  if (len < 14)
1766  return;
1767 
1768  Being *const dstBeing = actorManager->findBeing(
1769  msg.readBeingId("player id"));
1770  const int groupId = msg.readInt32("group id");
1771  uint16_t mount = 0;
1772  mount = msg.readInt16("mount");
1773  int language = -1;
1774  if (len > 14)
1775  language = msg.readInt16("language");
1776  int clanId = 0;
1777  if (len > 16)
1778  clanId = msg.readInt32("clan id");
1779  if (dstBeing != nullptr)
1780  {
1781  if (dstBeing != localPlayer)
1782  {
1783  dstBeing->setGroupId(groupId);
1784  }
1785  dstBeing->setHorse(mount);
1786  dstBeing->setLanguageId(language);
1787  if (clanId != 0)
1788  {
1789  const ClanInfo *const info = ClanDb::get(clanId);
1790  if (info == nullptr)
1791  dstBeing->setClanName(std::string());
1792  else
1793  dstBeing->setClanName(info->name);
1794  }
1795  else
1796  {
1797  dstBeing->setClanName(std::string());
1798  }
1799  if (dstBeing == localPlayer)
1801  }
1802 }
1803 
1805 {
1807 
1808  msg.readInt16("class");
1809  msg.readInt16("level");
1810  msg.readInt16("size");
1811  msg.readInt32("hp");
1812  msg.readInt16("def");
1813  msg.readInt16("race");
1814  msg.readInt16("mdef");
1815  msg.readInt16("ele");
1816 }
1817 
1819 {
1821 
1822  msg.readBeingId("being id");
1823  msg.readUInt8("type");
1824  msg.readInt32("class");
1825 }
1826 
1828 {
1829  if (actorManager == nullptr)
1830  return;
1831  Being *const dstBeing = actorManager->findBeing(
1832  msg.readBeingId("being id"));
1833  const int balls = msg.readInt16("spirits amount");
1834  if (dstBeing != nullptr)
1835  dstBeing->setSpiritBalls(balls);
1836 }
1837 
1839 {
1841 
1842  msg.readInt32("src being id");
1843  msg.readInt32("dst being id");
1844  msg.readInt32("flag");
1845 }
1846 
1848 {
1850 
1851  msg.readBeingId("being id");
1852  msg.readInt32("wait");
1853 }
1854 
1856 {
1858 
1859  msg.readBeingId("being id");
1860 }
1861 
1863 {
1864  if (actorManager == nullptr)
1865  return;
1866  Being *const dstBeing = actorManager->findBeing(
1867  msg.readBeingId("being id"));
1868  const int x = msg.readInt16("x");
1869  const int y = msg.readInt16("y");
1870  if (dstBeing == nullptr)
1871  return;
1872  if (localPlayer == dstBeing)
1873  {
1874  localPlayer->stopAttack(false);
1876  if (viewport != nullptr)
1878  }
1879 
1880  dstBeing->setAction(BeingAction::STAND, 0);
1881  dstBeing->setTileCoords(x, y);
1882 }
1883 
1885 {
1887 
1888  msg.readString(24, "map name");
1889  msg.readInt32("monster id");
1890  msg.readUInt8("start");
1891  msg.readUInt8("result");
1892 }
1893 
1895 {
1897 
1898  msg.readUInt8("which");
1899 }
1900 
1902 {
1904 
1905  msg.readUInt8("info type");
1906  msg.readInt32("x");
1907  msg.readInt32("y");
1908  msg.readInt16("min hours");
1909  msg.readInt16("min minutes");
1910  msg.readInt16("max hours");
1911  msg.readInt16("max minutes");
1912  msg.readString(24, "monster name"); // really can be used 51 byte?
1913 }
1914 
1916 {
1918 
1919  msg.readBeingId("account id");
1920  msg.readInt16("font");
1921 }
1922 
1924 {
1926 
1927  msg.readBeingId("account id");
1928  msg.readInt16("shields");
1929  msg.readInt16("unused");
1930 }
1931 
1933 {
1935 
1936  msg.readBeingId("account id");
1937  msg.readInt16("charm type");
1938  msg.readInt16("charm count");
1939 }
1940 
1942 {
1944 
1945  const int count = (msg.readInt16("len") - 45) / (21 + itemIdLen * 5);
1946  msg.readString(24, "name");
1947  msg.readInt16("job");
1948  msg.readInt16("head");
1949  msg.readInt16("accessory");
1950  msg.readInt16("accessory2");
1951  msg.readInt16("accessory3");
1952  if (msg.getVersion() >= 20101124)
1953  msg.readInt16("robe");
1954  msg.readInt16("hair color");
1955  msg.readInt16("body color");
1956  msg.readUInt8("gender");
1957  for (int f = 0; f < count; f ++)
1958  {
1959  msg.readInt16("index");
1960  msg.readItemId("item id");
1961  msg.readUInt8("item type");
1962  msg.readInt32("location");
1963  msg.readInt32("wear state");
1964  msg.readInt8("refine");
1965  for (int d = 0; d < maxCards; d ++)
1966  msg.readItemId("card");
1967  msg.readInt32("hire expire date (?)");
1968  msg.readInt16("equip type");
1969  msg.readInt16("item sprite number");
1970  msg.readUInt8("flags");
1971  }
1972 }
1973 
1975 {
1976  BLOCK_START("BeingRecv::processPvpSet")
1977  const BeingId id = msg.readBeingId("being id");
1978  const int rank = msg.readInt32("rank");
1979  msg.readInt32("num");
1980  if (actorManager != nullptr)
1981  {
1982  Being *const dstBeing = actorManager->findBeing(id);
1983  if (dstBeing != nullptr)
1984  dstBeing->setPvpRank(rank);
1985  }
1986  BLOCK_END("BeingRecv::processPvpSet")
1987 }
1988 
1990 {
1991  BLOCK_START("BeingRecv::processNameResponse2")
1992  if ((actorManager == nullptr) || (localPlayer == nullptr))
1993  {
1994  BLOCK_END("BeingRecv::processNameResponse2")
1995  return;
1996  }
1997 
1998  const int len = msg.readInt16("len");
1999  const BeingId beingId = msg.readBeingId("account id");
2000  const std::string str = msg.readString(len - 8, "name");
2001  actorManager->updateNameId(str, beingId);
2002  Being *const dstBeing = actorManager->findBeing(beingId);
2003  if (dstBeing != nullptr)
2004  {
2005  if (beingId == localPlayer->getId())
2006  {
2008  }
2009  else
2010  {
2011  dstBeing->setName(str);
2012  dstBeing->updateGuild();
2013  dstBeing->addToCache();
2014 
2015  if (dstBeing->getType() == ActorType::Player)
2016  dstBeing->updateColors();
2017 
2018  if (localPlayer != nullptr)
2019  {
2020  const Party *const party = localPlayer->getParty();
2021  if (party != nullptr && party->isMember(dstBeing->getId()))
2022  {
2023  PartyMember *const member = party->getMember(
2024  dstBeing->getId());
2025 
2026  if (member != nullptr)
2027  member->setName(dstBeing->getName());
2028  }
2029  localPlayer->checkNewName(dstBeing);
2030  }
2031  }
2032  }
2033  BLOCK_END("BeingRecv::processNameResponse2")
2034 }
2035 
2037  const BeingId id,
2038  const int32_t job,
2039  const BeingTypeT beingType)
2040 {
2041  if (actorManager == nullptr)
2042  return nullptr;
2043 
2045  switch (beingType)
2046  {
2047  case BeingType::PC:
2048  type = ActorType::Player;
2049  break;
2050  case BeingType::NPC:
2051  case BeingType::NPC_EVENT:
2052  type = ActorType::Npc;
2053  break;
2054  case BeingType::MONSTER:
2055  type = ActorType::Monster;
2056  break;
2057  case BeingType::MERSOL:
2058  type = ActorType::Mercenary;
2059  break;
2060  case BeingType::PET:
2061  type = ActorType::Pet;
2062  break;
2063  case BeingType::HOMUN:
2064  type = ActorType::Homunculus;
2065  break;
2066  case BeingType::SKILL:
2067  type = ActorType::SkillUnit;
2068  break;
2069  case BeingType::ELEMENTAL:
2070  type = ActorType::Elemental;
2071  break;
2072  case BeingType::ITEM:
2073  logger->log("not supported object type: %d, job: %d",
2074  CAST_S32(beingType), CAST_S32(job));
2075  break;
2076  case BeingType::CHAT:
2077  default:
2078  UNIMPLEMENTEDPACKETFIELD(CAST_S32(beingType));
2079  type = ActorType::Monster;
2080  logger->log("not supported object type: %d, job: %d",
2081  CAST_S32(beingType), CAST_S32(job));
2082  break;
2083  }
2084  if (job == 45 && beingType == BeingType::NPC_EVENT)
2085  type = ActorType::Portal;
2086 
2087  Being *const being = actorManager->createBeing(
2088  id, type, fromInt(job, BeingTypeId));
2089  if (beingType == BeingType::MERSOL)
2090  {
2091  const MercenaryInfo *const info = PlayerInfo::getMercenary();
2092  if ((info != nullptr) && info->id == id)
2094  }
2095  else if (beingType == BeingType::PET)
2096  {
2097  if (PlayerInfo::getPetBeingId() == id)
2098  PlayerInfo::setPetBeing(being);
2099  }
2100  return being;
2101 }
2102 
2104 {
2105  msg.readInt32("id?");
2106 }
2107 
2109 {
2110  if ((packets_re == true && msg.getVersion() >= 20180221) ||
2111  (packets_main == true && msg.getVersion() >= 20180307) ||
2112  (packets_zero == true && msg.getVersion() >= 20180328))
2113  {
2114  const int flag = msg.readInt16("flag");
2115  // name request errors
2116  if (flag != 3)
2117  return;
2118  }
2119  const int id = msg.readInt32("char id");
2120  if (actorManager == nullptr)
2121  {
2122  msg.readString(24, "name");
2123  return;
2124  }
2125  actorManager->addChar(id, msg.readString(24, "name"));
2126 }
2127 
2129 {
2130  const BeingId id = msg.readBeingId("graffiti id");
2131  const BeingId creatorId = msg.readBeingId("creator id");
2132  const int x = msg.readInt16("x");
2133  const int y = msg.readInt16("y");
2134  const int job = msg.readUInt8("job");
2135  msg.readUInt8("visible");
2136  msg.readUInt8("is content");
2137  const std::string text = msg.readString(80, "text");
2138 
2139  Being *const dstBeing = createBeing2(msg, id, job, BeingType::SKILL);
2140  if (dstBeing == nullptr)
2141  return;
2142 
2143  dstBeing->setAction(BeingAction::STAND, 0);
2144  dstBeing->setTileCoords(x, y);
2145  dstBeing->setShowName(true);
2146  dstBeing->setName(text);
2147  dstBeing->setCreatorId(creatorId);
2148 }
2149 
2151 {
2152  BLOCK_START("BeingRecv::processSkillDamage")
2153  if (actorManager == nullptr)
2154  {
2155  BLOCK_END("BeingRecv::processSkillDamage")
2156  return;
2157  }
2158 
2159  const int id = msg.readInt16("skill id");
2160  Being *const srcBeing = actorManager->findBeing(
2161  msg.readBeingId("src being id"));
2162  Being *const dstBeing = actorManager->findBeing(
2163  msg.readBeingId("dst being id"));
2164  msg.readInt32("tick");
2165  msg.readInt32("src speed");
2166  msg.readInt32("dst speed");
2167  int param1;
2168  if (msg.getVersion() >= 3)
2169  param1 = msg.readInt32("damage");
2170  else
2171  param1 = msg.readInt16("damage");
2172  const int level = msg.readInt16("skill level");
2173  msg.readInt16("div");
2174  msg.readUInt8("skill hit/type?");
2175  if (srcBeing != nullptr)
2176  srcBeing->handleSkill(dstBeing, param1, id, level);
2177  if (dstBeing != nullptr)
2178  dstBeing->takeDamage(srcBeing, param1, AttackType::SKILL, id, level);
2179  BLOCK_END("BeingRecv::processSkillDamage")
2180 }
2181 
2183 {
2185  // 0 position
2186  // 1 no position
2187  // 3 monster
2188  msg.readUInt8("navigate type");
2189  msg.readUInt8("transportation flag");
2190  msg.readUInt8("hide window");
2191  msg.readString(16, "map name");
2192  msg.readInt16("x");
2193  msg.readInt16("y");
2194  msg.readInt16("mob id");
2195 }
2196 
2198  Being *const being,
2199  const uint8_t type)
2200 {
2201  if (being == nullptr)
2202  return;
2203  switch (type)
2204  {
2205  case 0:
2206  being->setAction(BeingAction::STAND, 0);
2208  break;
2209 
2210  case 1:
2211  if (being->getCurrentAction() != BeingAction::DEAD)
2212  {
2213  being->setAction(BeingAction::DEAD, 0);
2214  being->recalcSpritesOrder();
2215  }
2216  break;
2217 
2218  case 2:
2219  being->setAction(BeingAction::SIT, 0);
2221  break;
2222 
2223  default:
2225  break;
2226  }
2227 }
2228 
2229 } // namespace EAthena
void processBeingFont(Net::MessageIn &msg)
Definition: beingrecv.cpp:1915
#define CAST_U32
Definition: cast.h:30
int getSpriteID(const int slot) const
Definition: being.cpp:4894
void processBeingAction2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1185
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
static bool enabled
unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:103
uint16_t getLook() const
Definition: being.h:921
void processBeingSlide(Net::MessageIn &msg)
Definition: beingrecv.cpp:1862
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
const ClanInfo * get(const int clanId)
Definition: clandb.cpp:121
bool packets_re
Definition: client.cpp:131
uint16_t readUInt16(const char *const str)
Definition: messagein.cpp:152
int getTileY() const
Definition: being.h:173
#define CAST_U8
Definition: cast.h:26
void setShowName(const bool doShowName)
Definition: being.cpp:1165
void setPetBeing(Being *const being)
Definition: playerinfo.cpp:556
void setAttackRange(const int range)
Definition: being.h:842
BeingId mSpawnId
Definition: beingrecv.cpp:58
Definition: party.h:61
void setLanguageId(const int lang)
Definition: being.cpp:5555
void processSkillGroundNoDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:1487
volatile int tick_time
Definition: timer.cpp:52
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:223
void setDestination(const int dstX, const int dstY)
Definition: being.cpp:539
OutfitWindow * outfitWindow
void setPvpMode(const int mode)
Definition: map.cpp:1356
void setTileCoords(const int x, const int y)
Definition: being.cpp:5010
void processBeingSpecialEffectNum(Net::MessageIn &msg)
Definition: beingrecv.cpp:1467
#define fromInt(val, name)
Definition: intdefines.h:45
void updateColors()
Definition: being.cpp:2663
void setGuildName(const std::string &name)
Definition: being.cpp:1195
void processBeingHatEffects(Net::MessageIn &msg)
Definition: beingrecv.cpp:1453
void processNavigateTo(Net::MessageIn &msg)
Definition: beingrecv.cpp:2182
BeingId getId() const
Definition: actorsprite.h:63
void setOtherTime()
Definition: being.h:717
void processBeingHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1288
void destroy(ActorSprite *const actor)
void processBossMapInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1901
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
int BeingId
Definition: beingid.h:29
void processPkRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1388
void processBeingChangeLookCards(Net::MessageIn &msg)
Definition: beingrecv.cpp:217
void processClassChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1818
void processGraffiti(Net::MessageIn &msg)
Definition: beingrecv.cpp:2128
void processBeingVisible(Net::MessageIn &msg)
Definition: beingrecv.cpp:416
virtual bool haveNpcGender() const =0
#define BLOCK_END(name)
Definition: perfomance.h:79
void setAttackDelay(const int n)
Definition: being.h:769
ActorType ::T ActorTypeT
Definition: actortype.h:42
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
void processBeingMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:602
void processBeingViewEquipment(Net::MessageIn &msg)
Definition: beingrecv.cpp:1941
void processGladiatorFeelRequest(Net::MessageIn &msg)
Definition: beingrecv.cpp:1894
void notify(const unsigned int message)
#define A_NONNULL(...)
Definition: localconsts.h:159
void setClanName(const std::string &name)
Definition: being.cpp:1222
void setWalkSpeed(const int speed)
Definition: being.h:451
uint32_t party
Map * getCurrentMap() const
Definition: game.h:106
void readCoordinates(uint16_t &x, uint16_t &y, uint8_t &direction, const char *const str)
Definition: messagein.cpp:279
signed char readInt8(const char *const str)
Definition: messagein.cpp:116
void setSpiritBalls(const unsigned int balls)
Definition: being.cpp:5474
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:942
void processMobInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1746
void processComboDelay(Net::MessageIn &msg)
Definition: beingrecv.cpp:1847
void playCastingDstTileEffect(const int id, const int level, const int x, const int y, const int delay) const
void setPartyName(const std::string &name)
Definition: being.cpp:5246
bool isMember(const PartyMember *const member) const
Definition: party.cpp:229
void processSolveCharName(Net::MessageIn &msg)
Definition: beingrecv.cpp:2108
void setSpriteColor(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2890
void setHairColorSpriteID(const unsigned int slot, const int id)
Definition: being.cpp:3291
void processNameResponse2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1989
bool packets_zero
Definition: client.cpp:132
Logger * logger
Definition: logger.cpp:88
BeingType ::T BeingTypeT
Definition: beingtype.h:40
MercenaryInfo * getMercenary()
Definition: playerinfo.cpp:545
void freezeMoving(const int timeWaitTicks)
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 processPlayerStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1527
int16_t readInt16(const char *const str)
Definition: messagein.cpp:130
static std::string getKeyShortString(const std::string &key)
MapTypeProperty2Bits bits
Net::ServerFeatures * serverFeatures
Definition: net.cpp:97
void returnCamera()
Definition: viewport.cpp:1110
void processAlchemistRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1368
void processBeingSoundEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1477
void setHorse(const int horseId)
Definition: being.cpp:5425
void updateGuild()
Definition: being.cpp:1332
#define CAST_S32
Definition: cast.h:29
void setActionTime(const int actionTime)
Definition: being.h:134
void processBeingResurrect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1584
void setStatusEffectOpiton0(const uint32_t option)
void processMonsterHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1313
void processSkillDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:2150
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 processTaekwonRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1378
bool info(InputEvent &event)
Definition: commands.cpp:56
void processMonsterInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1804
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:311
void navigateClean()
std::list< Character * > Characters
Definition: character.h:60
#define DEBUGLOGSTR(str)
Definition: logger.h:44
Definition: game.h:62
const bool IsStart_true
Definition: isstart.h:29
void pingResponse()
void undelete(const ActorSprite *const actor)
void setPvpRank(const unsigned int rank)
Definition: being.h:751
int getVersion() const
Definition: messagein.h:133
void processBeingSpecialEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1427
LocalPlayer * localPlayer
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:349
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
void addCast(const int dstX, const int dstY, const int skillId, const int skillLevel, const int range, const int waitTimeTicks)
Definition: being.cpp:5369
BeingActionT getCurrentAction() const
Definition: being.h:481
Being * findBeing(const BeingId id) const
void stopAttack(const bool keepAttack)
PartyMember * getMember(const BeingId id) const
Definition: party.cpp:98
static const int MILLISECONDS_IN_A_TICK
Definition: timer.h:29
ActorTypeT getType() const
Definition: being.h:115
bool isBlocked(const BeingId id) const
void processPlayerStatusChange2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1566
void setName(const std::string &name)
Definition: avatar.h:58
void imitateOutfit(const Being *const player, const int sprite) const
void resetDamage(const std::string &name)
bool Enable
Definition: enable.h:29
int serverVersion
Definition: client.cpp:123
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
void processWddingEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1855
void processSkillAutoCast(Net::MessageIn &msg)
Definition: beingrecv.cpp:1328
void processBeingSpawn(Net::MessageIn &msg)
Definition: beingrecv.cpp:796
const bool IsStart_false
Definition: isstart.h:29
SocialWindow * socialWindow
AttackType ::T AttackTypeT
Definition: attacktype.h:46
void setManner(const int manner)
Definition: being.h:1040
const std::string & getName() const
Definition: being.h:231
void processBeingRemoveSkill(Net::MessageIn &msg)
Definition: beingrecv.cpp:1654
void imitateDirection(const Being *const being, const unsigned char dir)
Definition: map.h:71
void processBladeStop(Net::MessageIn &msg)
Definition: beingrecv.cpp:1838
void processBeingSelfEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1720
void takeDamage(Being *const attacker, const int amount, const AttackTypeT type, const int attackId, const int level)
Definition: being.cpp:666
int readItemId(const char *const str)
Definition: messagein.cpp:216
virtual void scheduleDelete()
Definition: window.cpp:826
void checkNewName(Being *const being)
void processSkillCasting2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1018
void processSkillEntry(Net::MessageIn &msg)
Definition: beingrecv.cpp:1498
std::string name
Definition: claninfo.h:41
SkillDialog * skillDialog
Definition: skilldialog.cpp:65
void imitateAction(const Being *const being, const BeingActionT &action)
void applyPlayerAction(Net::MessageIn &msg, Being *const being, const uint8_t type)
Definition: beingrecv.cpp:2197
static std::string keyName(const int number)
void setCreatorId(const BeingId id)
Definition: being.h:1028
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:370
void setKarma(const int karma)
Definition: being.h:1034
bool packets_main
Definition: client.cpp:130
void erase(ActorSprite *const actor)
void processBeingChangeLook2(Net::MessageIn &msg)
Definition: beingrecv.cpp:197
void setStatusEffectOpitons(const uint32_t option, const uint32_t opt1, const uint32_t opt2, const uint32_t opt3)
void processMapTypeProperty(Net::MessageIn &msg)
Definition: beingrecv.cpp:968
void followMoveTo(const Being *const being, const int x, const int y)
void processPvpSet(Net::MessageIn &msg)
Definition: beingrecv.cpp:1974
void processBeingChangeDirection(Net::MessageIn &msg)
Definition: beingrecv.cpp:1398
void setName(const std::string &name)
Definition: being.cpp:1135
void handleSkillCasting(Being *const victim, const int skillId, const int skillLevel)
Definition: being.cpp:1024
static Net::Characters mCharacters
void processSpiritBalls(Net::MessageIn &msg)
Definition: beingrecv.cpp:1827
Window * deathNotice
Definition: sp.h:34
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1620
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1139
void processMapType(Net::MessageIn &msg)
Definition: beingrecv.cpp:987
void processSkillCastingContinue(Net::MessageIn &msg, const BeingId srcId, const BeingId dstId, const int dstX, const int dstY, const int skillId, const int skillLevel, const int range, const SkillType2::SkillType2 inf2, const int castTime)
Definition: beingrecv.cpp:1043
static Game * instance()
Definition: game.h:81
void recalcSpritesOrder()
Definition: being.cpp:4359
void setMercenaryBeing(Being *const being)
Definition: playerinfo.cpp:522
void processRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1346
#define restrict
Definition: localconsts.h:156
std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:367
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1106
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
BeingId getPetBeingId()
Definition: playerinfo.cpp:577
int getTileX() const
Definition: being.h:167
void setLook(const uint16_t look)
Definition: being.cpp:5004
const BeingId BeingId_zero
Definition: beingid.h:29
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
void log(const char *const log_text,...)
Definition: logger.cpp:264
virtual bool haveMove3() const =0
void setServerLanguage(const int lang)
Definition: playerinfo.cpp:664
void updateNameId(const std::string &name, const BeingId beingId)
Being * createBeing2(Net::MessageIn &msg, const BeingId id, const int32_t job, const BeingTypeT beingType)
Definition: beingrecv.cpp:2036
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
void processBlacksmithRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1358
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:996
void processSkillCancel(Net::MessageIn &msg)
Definition: beingrecv.cpp:2103
int itemIdLen
Definition: client.cpp:129
virtual void setGroupId(const int id)
Definition: being.cpp:5587
void processBeingStatUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:1700
void setStatusEffect(const int32_t index, const Enable active, const IsStart start)
bool trigger(const int id, Being *const being, const int rotation)
void handleAttack(Being *const victim, const int damage, const int attackId)
Definition: being.cpp:962
void processBeingCharm(Net::MessageIn &msg)
Definition: beingrecv.cpp:1932
int BeingTypeId
Definition: beingtypeid.h:29
Definition: being.h:93
static void setBasicFields(Being *const dstBeing, const uint8_t gender, const int hairStyle, const ItemColor hairColor, const uint32_t weapon, const uint16_t headBottom, const uint16_t headMid, const uint16_t headTop, const uint16_t shoes, const uint16_t gloves, const bool notMove)
Definition: beingrecv.cpp:93
void setWeaponId(const int id)
Definition: being.cpp:3135
EffectManager * effectManager
#define reportAlways(...)
Definition: checkutils.h:252
void addChar(const int32_t id, const std::string &name)
LocalPlayer * dummy
Definition: character.h:55
void processStarsKill(Net::MessageIn &msg)
Definition: beingrecv.cpp:1884
Being * createBeing(const BeingId id, const ActorTypeT type, const BeingTypeId subtype)
void setSpriteCards(const unsigned int slot, const int id, const CardsList &cards)
Definition: being.cpp:3048
#define maxCards
Definition: cards.h:24
ActorManager * actorManager
void processBeingAttrs(Net::MessageIn &msg)
Definition: beingrecv.cpp:1760
Viewport * viewport
Definition: viewport.cpp:35
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void processBeingMilleniumShield(Net::MessageIn &msg)
Definition: beingrecv.cpp:1923
void processBeingFakeName(Net::MessageIn &msg)
Definition: beingrecv.cpp:1665
void setLevel(const int n)
Definition: being.h:600
Being * getTarget() const
void setMoveTime()
Definition: being.h:705
void setAttackTime()
Definition: being.h:708
void clearPath()
Definition: being.cpp:553
void setMaxHP(const int hp)
Definition: being.cpp:4343