ManaPlus
beingrecv.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  *
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;
550  uint16_t y;
551  msg.readCoordinates(x, y, dir, "position");
552  msg.readInt8("xs");
553  msg.readInt8("ys");
554  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
555  dstBeing->setTileCoords(x, y);
556 
557  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
558  {
559  const int num = socialWindow->getPortalIndex(x, y);
560  if (num >= 0)
561  {
563  OutfitWindow::keyName(num)));
564  }
565  else
566  {
567  dstBeing->setName("");
568  }
569  }
570 
571  dstBeing->setDirection(dir);
572 
573  const int level = CAST_S32(msg.readInt16("level"));
574  if (level != 0)
575  dstBeing->setLevel(level);
576  if (msg.getVersion() >= 20080102)
577  msg.readInt16("font");
578 
579  if (msg.getVersion() >= 20120221)
580  {
581  const int maxHP = msg.readInt32("max hp");
582  const int hp = msg.readInt32("hp");
583  dstBeing->setMaxHP(maxHP);
584  dstBeing->setHP(hp);
585  msg.readInt8("is boss");
586  }
587 
588  if (msg.getVersion() >= 20150513)
589  {
590  msg.readInt16("body2");
591  }
592  if (msg.getVersion() >= 20131223)
593  {
594  msg.readString(24, "name");
595  }
596 
597  dstBeing->setStatusEffectOpitons(option,
598  opt1,
599  opt2,
600  opt3);
601 }
602 
604 {
605  if (actorManager == nullptr)
606  return;
607 
608  if (msg.getVersion() >= 20091103)
609  msg.readInt16("len");
610  BeingTypeT type;
611  if (msg.getVersion() >= 20071106)
612  {
613  type = static_cast<BeingTypeT>(
614  msg.readUInt8("object type"));
615  }
616  else
617  {
618  // need detect type based on id
619  type = BeingType::MONSTER;
620  }
621 
622  // Information about a being in range
623  const BeingId id = msg.readBeingId("being id");
624  if (msg.getVersion() >= 20131223)
625  msg.readBeingId("char id");
626  BeingId spawnId;
627  if (id == Ea::BeingRecv::mSpawnId)
628  spawnId = Ea::BeingRecv::mSpawnId;
629  else
630  spawnId = BeingId_zero;
632  int16_t speed = msg.readInt16("speed");
633  const uint32_t opt1 = msg.readInt16("opt1");
634  // probably wrong effect usage
635  const uint32_t opt2 = msg.readInt16("opt2");
636  uint32_t option;
637  if (msg.getVersion() >= 7)
638  option = msg.readInt32("option");
639  else
640  option = msg.readInt16("option");
641  const int16_t job = msg.readInt16("class");
642 
643  Being *dstBeing = actorManager->findBeing(id);
644 
645  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
646  && !dstBeing->isAlive())
647  {
648  actorManager->destroy(dstBeing);
649  actorManager->erase(dstBeing);
650  dstBeing = nullptr;
651  }
652 
653  if (dstBeing == nullptr)
654  {
655  if (actorManager->isBlocked(id) == true)
656  return;
657 
658  dstBeing = createBeing2(msg, id, job, type);
659  if (dstBeing == nullptr)
660  return;
661  }
662  else
663  {
664  // undeleting marked for deletion being
665  if (dstBeing->getType() == ActorType::Npc)
666  actorManager->undelete(dstBeing);
667  }
668 
669  if (dstBeing->getType() == ActorType::Player)
670  dstBeing->setMoveTime();
671 
672  if (spawnId != BeingId_zero)
673  dstBeing->setAction(BeingAction::SPAWN, 0);
674 
675  // Prevent division by 0 when calculating frame
676  if (speed == 0)
677  speed = 150;
678 
679  dstBeing->setWalkSpeed(speed);
680  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
681  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
682  localPlayer->checkNewName(dstBeing);
683 
684  const int hairStyle = msg.readInt16("hair style");
685  uint32_t weapon;
686  if (msg.getVersion() >= 7)
687  {
688  weapon = msg.readItemId("weapon");
689  msg.readItemId("shield");
690  }
691  else
692  {
693  weapon = CAST_U32(msg.readInt16("weapon"));
694  }
695  const uint16_t headBottom = msg.readInt16("head bottom");
696  msg.readInt32("tick");
697  if (msg.getVersion() < 7)
698  msg.readInt16("shield");
699  const uint16_t headTop = msg.readInt16("head top");
700  const uint16_t headMid = msg.readInt16("head mid");
701  const ItemColor hairColor = fromInt(
702  msg.readInt16("hair color"), ItemColor);
703  const uint16_t shoes = msg.readInt16("shoes or clothes color?");
704 
705  const uint16_t gloves = msg.readInt16("head dir / gloves");
706  // may be use robe as gloves?
707  if (msg.getVersion() >= 20101124)
708  msg.readInt16("robe");
709  msg.readInt32("guild id");
710  msg.readInt16("guild emblem");
711  dstBeing->setManner(msg.readInt16("manner"));
712  uint32_t opt3;
713  if (msg.getVersion() >= 7)
714  opt3 = msg.readInt32("opt3");
715  else
716  opt3 = msg.readInt16("opt3");
717  dstBeing->setKarma(msg.readUInt8("karma"));
718  const uint8_t gender = CAST_U8(msg.readUInt8("gender") & 3);
719 
720  setBasicFields(dstBeing,
721  gender,
722  hairStyle,
723  hairColor,
724  weapon,
725  headBottom,
726  headMid,
727  headTop,
728  shoes,
729  gloves,
731 
732  uint16_t srcX;
733  uint16_t srcY;
734  uint16_t dstX;
735  uint16_t dstY;
736  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
737  msg.readUInt8("(sx<<4) | (sy&0x0f)");
738  msg.readInt8("xs");
739  msg.readInt8("ys");
740  dstBeing->setAction(BeingAction::STAND, 0);
741  dstBeing->setTileCoords(srcX, srcY);
742  if (localPlayer != nullptr)
743  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
744  if (serverFeatures->haveMove3())
745  dstBeing->setCachedDestination(dstX, dstY);
746  else
747  dstBeing->setDestination(dstX, dstY);
748 
749  // because server don't send direction in move packet, we fixing it
750 
751  uint8_t d = 0;
752  if (localPlayer != nullptr &&
753  srcX == dstX &&
754  srcY == dstY)
755  { // if player did one step from invisible area to visible,
756  // move path is broken
757  int x2 = localPlayer->getTileX();
758  int y2 = localPlayer->getTileY();
759  if (abs(x2 - srcX) > abs(y2 - srcY))
760  y2 = srcY;
761  else
762  x2 = srcX;
763  d = dstBeing->calcDirection(x2, y2);
764  }
765  else
766  {
767  d = dstBeing->calcDirection(dstX, dstY);
768  }
769  if ((d != 0U) && dstBeing->getDirection() != d)
770  dstBeing->setDirection(d);
771 
772  const int level = CAST_S32(msg.readInt16("level"));
773  if (level != 0)
774  dstBeing->setLevel(level);
775  if (msg.getVersion() >= 20080102)
776  msg.readInt16("font");
777  if (msg.getVersion() >= 20120221)
778  {
779  const int maxHP = msg.readInt32("max hp");
780  const int hp = msg.readInt32("hp");
781  dstBeing->setMaxHP(maxHP);
782  dstBeing->setHP(hp);
783  msg.readInt8("is boss");
784  }
785  if (msg.getVersion() >= 20150513)
786  {
787  msg.readInt16("body2");
788  }
789  if (msg.getVersion() >= 20131223)
790  {
791  msg.readString(24, "name");
792  }
793 
794  dstBeing->setStatusEffectOpitons(option,
795  opt1,
796  opt2,
797  opt3);
798 }
799 
801 {
802  if (actorManager == nullptr)
803  return;
804 
805  // need get type from id
807  if (msg.getVersion() >= 20091103)
808  {
809  msg.readInt16("len");
810  type = static_cast<BeingTypeT>(
811  msg.readUInt8("object type"));
812  }
813 
814  // Information about a being in range
815  const BeingId id = msg.readBeingId("being id");
816  if (msg.getVersion() >= 20131223)
817  {
818  msg.readBeingId("char id");
819  }
821  const BeingId spawnId = id;
822  int16_t speed = msg.readInt16("speed");
823  const uint32_t opt1 = msg.readInt16("opt1");
824  // probably wrong effect usage
825  const uint32_t opt2 = msg.readInt16("opt2");
826  uint32_t option;
827  if (msg.getVersion() >= 20080102)
828  option = msg.readInt32("option");
829  else
830  option = msg.readInt16("option");
831  const int16_t job = msg.readInt16("class");
832 
833  Being *dstBeing = actorManager->findBeing(id);
834 
835  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
836  && !dstBeing->isAlive())
837  {
838  actorManager->destroy(dstBeing);
839  actorManager->erase(dstBeing);
840  dstBeing = nullptr;
841  }
842 
843  if (dstBeing == nullptr)
844  {
845  if (actorManager->isBlocked(id) == true)
846  return;
847 
848  dstBeing = createBeing2(msg, id, job, type);
849  if (dstBeing == nullptr)
850  return;
851  }
852  else
853  {
854  // undeleting marked for deletion being
855  if (dstBeing->getType() == ActorType::Npc)
856  actorManager->undelete(dstBeing);
857  }
858 
859  if (dstBeing->getType() == ActorType::Player)
860  dstBeing->setMoveTime();
861 
862  if (spawnId != BeingId_zero)
863  dstBeing->setAction(BeingAction::SPAWN, 0);
864 
865  // Prevent division by 0 when calculating frame
866  if (speed == 0)
867  speed = 150;
868 
869  dstBeing->setWalkSpeed(speed);
870  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
871  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
872  localPlayer->checkNewName(dstBeing);
873 
874  const int hairStyle = msg.readInt16("hair style");
875  uint32_t weapon;
876  if (msg.getVersion() >= 7)
877  {
878  weapon = msg.readItemId("weapon");
879  msg.readItemId("shield");
880  }
881  else
882  {
883  weapon = CAST_U32(msg.readInt16("weapon"));
884  }
885  const uint16_t headBottom = msg.readInt16("head bottom");
886  if (msg.getVersion() < 7)
887  msg.readInt16("shield");
888  const uint16_t headTop = msg.readInt16("head top");
889  const uint16_t headMid = msg.readInt16("head mid");
890  const ItemColor hairColor = fromInt(
891  msg.readInt16("hair color"), ItemColor);
892  const uint16_t shoes = msg.readInt16("shoes or clothes color?");
893  const uint16_t gloves = msg.readInt16("head dir / gloves");
894  // may be use robe as gloves?
895  if (msg.getVersion() >= 20101124)
896  msg.readInt16("robe");
897  msg.readInt32("guild id");
898  msg.readInt16("guild emblem");
899  dstBeing->setManner(msg.readInt16("manner"));
900  uint32_t opt3;
901  if (msg.getVersion() >= 7)
902  opt3 = msg.readInt32("opt3");
903  else
904  opt3 = msg.readInt16("opt3");
905 
906  dstBeing->setKarma(msg.readUInt8("karma"));
907  const uint8_t gender = CAST_U8(msg.readUInt8("gender") & 3);
908 
909  setBasicFields(dstBeing,
910  gender,
911  hairStyle,
912  hairColor,
913  weapon,
914  headBottom,
915  headMid,
916  headTop,
917  shoes,
918  gloves,
919  true);
920 
921  uint8_t dir;
922  uint16_t x;
923  uint16_t y;
924  msg.readCoordinates(x, y, dir, "position");
925  msg.readInt8("xs");
926  msg.readInt8("ys");
927  dstBeing->setTileCoords(x, y);
928 
929  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
930  {
931  const int num = socialWindow->getPortalIndex(x, y);
932  if (num >= 0)
933  {
935  OutfitWindow::keyName(num)));
936  }
937  else
938  {
939  dstBeing->setName("");
940  }
941  }
942 
943  dstBeing->setDirection(dir);
944 
945  const int level = CAST_S32(msg.readInt16("level"));
946  if (level != 0)
947  dstBeing->setLevel(level);
948  if (msg.getVersion() >= 20080102)
949  msg.readInt16("font");
950  if (msg.getVersion() >= 20120221)
951  {
952  const int maxHP = msg.readInt32("max hp");
953  const int hp = msg.readInt32("hp");
954  dstBeing->setMaxHP(maxHP);
955  dstBeing->setHP(hp);
956  msg.readInt8("is boss");
957  }
958  if (msg.getVersion() >= 20150513)
959  {
960  msg.readInt16("body2");
961  }
962  if (msg.getVersion() >= 20131223)
963  {
964  msg.readString(24, "name");
965  }
966 
967  dstBeing->setStatusEffectOpitons(option,
968  opt1,
969  opt2,
970  opt3);
971 }
972 
974 {
975  const int16_t type = msg.readInt16("type");
976  const int flags = msg.readInt32("flags");
977  if (type == 0x28)
978  {
979  // +++ need get other flags from here
980  MapTypeProperty2 props;
981  props.data = CAST_U32(flags);
982  const Game *const game = Game::instance();
983  if (game == nullptr)
984  return;
985  Map *const map = game->getCurrentMap();
986  if (map == nullptr)
987  return;
988  map->setPvpMode(props.bits.party | (props.bits.guild * 2));
989  }
990 }
991 
993 {
994  const int16_t type = msg.readInt16("type");
995  if (type == 19)
997  else
999 }
1000 
1002 {
1003  const BeingId srcId = msg.readBeingId("src id");
1004  const BeingId dstId = msg.readBeingId("dst id");
1005  const int dstX = msg.readInt16("dst x");
1006  const int dstY = msg.readInt16("dst y");
1007  const int skillId = msg.readInt16("skill id");
1008  msg.readInt32("element"); // +++ use different effects
1009  const int castTime = msg.readInt32("cast time");
1010 
1012  srcId, dstId,
1013  dstX, dstY,
1014  skillId,
1015  1,
1016  0,
1018  castTime);
1019 }
1020 
1022 {
1023  const BeingId srcId = msg.readBeingId("src id");
1024  const BeingId dstId = msg.readBeingId("dst id");
1025  const int dstX = msg.readInt16("dst x");
1026  const int dstY = msg.readInt16("dst y");
1027  const int skillId = msg.readInt16("skill id");
1028  msg.readInt32("element"); // +++ use different effects
1029  const int castTime = msg.readInt32("cast time");
1030  msg.readInt8("dispossable");
1031 
1033  srcId, dstId,
1034  dstX, dstY,
1035  skillId,
1036  1,
1037  0,
1039  castTime);
1040 }
1041 
1043 {
1044  const BeingId srcId = msg.readBeingId("src id");
1045  const BeingId dstId = msg.readBeingId("dst id");
1046  const int dstX = msg.readInt16("dst x");
1047  const int dstY = msg.readInt16("dst y");
1048  const int skillId = msg.readInt16("skill id");
1049  msg.readInt32("element"); // +++ use different effects
1050  const int castTime = msg.readInt32("cast time");
1051  msg.readInt8("dispossable");
1052  msg.readInt32("unknown");
1053 
1055  srcId, dstId,
1056  dstX, dstY,
1057  skillId,
1058  1,
1059  0,
1061  castTime);
1062 }
1063 
1065 {
1066  msg.readInt16("len"); // for now unused
1067  const BeingId srcId = msg.readBeingId("src id");
1068  const BeingId dstId = msg.readBeingId("dst id");
1069  const int dstX = msg.readInt16("dst x");
1070  const int dstY = msg.readInt16("dst y");
1071  const int skillId = msg.readInt16("skill id");
1072  const int skillLevel = msg.readInt16("skill level");
1073  msg.readInt32("element"); // +++ use different effects
1074  const int castTime = msg.readInt32("cast time");
1075  const int range = msg.readInt32("skill range");
1076  const SkillType2::SkillType2 inf2 =
1077  static_cast<SkillType2::SkillType2>(msg.readInt32("inf2"));
1078  // +++ add new unknown field
1079 
1081  srcId, dstId,
1082  dstX, dstY,
1083  skillId,
1084  skillLevel,
1085  range,
1086  inf2,
1087  castTime);
1088 }
1089 
1091  const BeingId srcId,
1092  const BeingId dstId,
1093  const int dstX,
1094  const int dstY,
1095  const int skillId,
1096  const int skillLevel,
1097  const int range,
1098  const SkillType2::SkillType2 inf2,
1099  const int castTime)
1100 {
1101  if (effectManager == nullptr ||
1102  actorManager == nullptr)
1103  return;
1104 
1105  if (srcId == BeingId_zero)
1106  {
1108  return;
1109  }
1110  Being *const srcBeing = actorManager->findBeing(srcId);
1111  if (dstId != BeingId_zero)
1112  { // being to being
1113  Being *const dstBeing = actorManager->findBeing(dstId);
1114  if (srcBeing != nullptr)
1115  {
1116  srcBeing->handleSkillCasting(dstBeing, skillId, skillLevel);
1117  if (dstBeing != nullptr)
1118  {
1119  srcBeing->addCast(dstBeing->getTileX(),
1120  dstBeing->getTileY(),
1121  skillId,
1122  skillLevel,
1123  range,
1124  castTime / MILLISECONDS_IN_A_TICK);
1125  }
1126  }
1127  }
1128  else if (dstX != 0 || dstY != 0)
1129  { // being to position
1130  if (srcBeing != nullptr)
1131  srcBeing->setAction(BeingAction::CAST, skillId);
1133  skillLevel,
1134  dstX, dstY,
1135  castTime);
1136  if (srcBeing != nullptr)
1137  {
1138  srcBeing->addCast(dstX, dstY,
1139  skillId,
1140  skillLevel,
1141  range,
1142  castTime / MILLISECONDS_IN_A_TICK);
1143  }
1144  }
1145  if ((localPlayer != nullptr) &&
1146  srcBeing == localPlayer &&
1147  (inf2 & SkillType2::FreeCastAny) == 0)
1148  {
1150  }
1151 }
1152 
1154 {
1155  BLOCK_START("BeingRecv::processBeingStatusChange")
1156  if (actorManager == nullptr)
1157  {
1158  BLOCK_END("BeingRecv::processBeingStatusChange")
1159  return;
1160  }
1161 
1162  // Status change
1163  const uint16_t status = msg.readInt16("status");
1164  const BeingId id = msg.readBeingId("being id");
1165  const Enable flag = fromBool(
1166  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1167  if (msg.getVersion() >= 20120618)
1168  msg.readInt32("total");
1169  if (msg.getVersion() >= 20090121)
1170  {
1171  msg.readInt32("left");
1172  msg.readInt32("val1");
1173  msg.readInt32("val2");
1174  msg.readInt32("val3");
1175  }
1176 
1177  const IsStart start = msg.getVersion() == 20090121 ?
1179 
1180  Being *const dstBeing = actorManager->findBeing(id);
1181  if (dstBeing != nullptr)
1182  dstBeing->setStatusEffect(status, flag, start);
1183  BLOCK_END("BeingRecv::processBeingStatusChange")
1184 }
1185 
1187 {
1188  BLOCK_START("BeingRecv::processBeingMove2")
1189  if (actorManager == nullptr)
1190  {
1191  BLOCK_END("BeingRecv::processBeingMove2")
1192  return;
1193  }
1194 
1195  /*
1196  * A simplified movement packet, used by the
1197  * later versions of eAthena for both mobs and
1198  * players
1199  */
1200  Being *const dstBeing = actorManager->findBeing(
1201  msg.readBeingId("being id"));
1202 
1203  uint16_t srcX;
1204  uint16_t srcY;
1205  uint16_t dstX;
1206  uint16_t dstY;
1207  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1208  msg.readUInt8("(sx<<4) | (sy&0x0f)");
1209  msg.readInt32("tick");
1210 
1211  /*
1212  * This packet doesn't have enough info to actually
1213  * create a new being, so if the being isn't found,
1214  * we'll just pretend the packet didn't happen
1215  */
1216 
1217  if (dstBeing == nullptr)
1218  {
1219  BLOCK_END("BeingRecv::processBeingMove2")
1220  return;
1221  }
1222 
1223  dstBeing->setTileCoords(srcX, srcY);
1224  if (localPlayer != nullptr)
1225  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
1226  if (serverFeatures->haveMove3())
1227  dstBeing->setCachedDestination(dstX, dstY);
1228  else
1229  dstBeing->setDestination(dstX, dstY);
1230  if (dstBeing->getType() == ActorType::Player)
1231  dstBeing->setMoveTime();
1232  BLOCK_END("BeingRecv::processBeingMove2")
1233 }
1234 
1236 {
1237  BLOCK_START("BeingRecv::processBeingAction2")
1238  if (actorManager == nullptr)
1239  {
1240  BLOCK_END("BeingRecv::processBeingAction2")
1241  return;
1242  }
1243 
1244  Being *const srcBeing = actorManager->findBeing(
1245  msg.readBeingId("src being id"));
1246  Being *const dstBeing = actorManager->findBeing(
1247  msg.readBeingId("dst being id"));
1248 
1249  msg.readInt32("tick");
1250  const int srcSpeed = msg.readInt32("src speed");
1251  msg.readInt32("dst speed");
1252  int param1;
1253  if (msg.getVersion() >= 20071113)
1254  param1 = msg.readInt32("damage");
1255  else
1256  param1 = msg.readInt16("damage");
1257  if (msg.getVersion() >= 20131223)
1258  msg.readUInt8("is sp damaged");
1259  msg.readInt16("count");
1260  const AttackTypeT type = static_cast<AttackTypeT>(
1261  msg.readUInt8("action"));
1262  if (msg.getVersion() >= 20071113)
1263  msg.readInt32("left damage");
1264  else
1265  msg.readInt16("left damage");
1266 
1267  switch (type)
1268  {
1269  case AttackType::HIT: // Damage
1270  case AttackType::CRITICAL: // Critical Damage
1271  case AttackType::MULTI: // Critical Damage
1273  case AttackType::REFLECT: // Reflected Damage
1274  case AttackType::FLEE: // Lucky Dodge
1275  case AttackType::SPLASH:
1276  case AttackType::SKILL:
1277  case AttackType::REPEATE:
1278  if (srcBeing != nullptr)
1279  {
1280  if (srcSpeed != 0 && srcBeing->getType() == ActorType::Player)
1281  srcBeing->setAttackDelay(srcSpeed);
1282  // attackid=1, type
1283  srcBeing->handleAttack(dstBeing, param1, 1);
1284  if (srcBeing->getType() == ActorType::Player)
1285  srcBeing->setAttackTime();
1286  }
1287  if (dstBeing != nullptr)
1288  {
1289  // level not present, using 1
1290  dstBeing->takeDamage(srcBeing, param1,
1291  static_cast<AttackTypeT>(type), 1, 1);
1292  }
1293  break;
1294 
1295  case AttackType::PICKUP:
1296  break;
1297 
1299  break;
1300 
1301  case AttackType::SIT:
1302  if (srcBeing != nullptr)
1303  {
1304  srcBeing->setAction(BeingAction::SIT, 0);
1305  if (srcBeing->getType() == ActorType::Player)
1306  {
1307  srcBeing->setMoveTime();
1308  if (localPlayer != nullptr)
1310  }
1311  }
1312  break;
1313 
1314  case AttackType::STAND:
1315  if (srcBeing != nullptr)
1316  {
1317  srcBeing->setAction(BeingAction::STAND, 0);
1318  if (srcBeing->getType() == ActorType::Player)
1319  {
1320  srcBeing->setMoveTime();
1321  if (localPlayer != nullptr)
1322  {
1323  localPlayer->imitateAction(srcBeing,
1325  }
1326  }
1327  }
1328  break;
1329  default:
1330  case AttackType::MISS:
1331  case AttackType::SKILLMISS:
1333  break;
1334  }
1335  BLOCK_END("BeingRecv::processBeingAction2")
1336 }
1337 
1339 {
1340  if (actorManager == nullptr)
1341  return;
1342  Being *const dstBeing = actorManager->findBeing(
1343  msg.readBeingId("being id"));
1344  int hp;
1345  int maxHP;
1346  if (msg.getVersion() >= 20100126)
1347  {
1348  hp = msg.readInt32("hp");
1349  maxHP = msg.readInt32("max hp");
1350  }
1351  else
1352  {
1353  hp = msg.readInt16("hp");
1354  maxHP = msg.readInt16("max hp");
1355  }
1356  if (dstBeing != nullptr)
1357  {
1358  dstBeing->setHP(hp);
1359  dstBeing->setMaxHP(maxHP);
1360  }
1361 }
1362 
1364 {
1365  if (actorManager == nullptr)
1366  return;
1367  Being *const dstBeing = actorManager->findBeing(
1368  msg.readBeingId("monster id"));
1369  const int hp = msg.readInt32("hp");
1370  const int maxHP = msg.readInt32("max hp");
1371  if (dstBeing != nullptr)
1372  {
1373  dstBeing->setHP(hp);
1374  dstBeing->setMaxHP(maxHP);
1375  }
1376 }
1377 
1379 {
1380  const int id = msg.readInt16("skill id");
1381  msg.readInt16("inf");
1382  msg.readInt16("unused");
1383  const int level = msg.readInt16("skill level");
1384  msg.readInt16("sp");
1385  msg.readInt16("range");
1386  msg.readString(24, "skill name");
1387  msg.readInt8("unused");
1388 
1389  if (localPlayer != nullptr)
1390  {
1391  localPlayer->handleSkill(localPlayer, 0, id, level);
1393  }
1394 }
1395 
1397 {
1399  // +++ here need window with rank tables.
1400  msg.readInt16("rank type");
1401  for (int f = 0; f < 10; f ++)
1402  msg.readString(24, "name");
1403  for (int f = 0; f < 10; f ++)
1404  msg.readInt32("points");
1405  msg.readInt32("my points");
1406 }
1407 
1409 {
1411  // +++ here need window with rank tables.
1412  for (int f = 0; f < 10; f ++)
1413  msg.readString(24, "name");
1414  for (int f = 0; f < 10; f ++)
1415  msg.readInt32("points");
1416 }
1417 
1419 {
1421  // +++ here need window with rank tables.
1422  for (int f = 0; f < 10; f ++)
1423  msg.readString(24, "name");
1424  for (int f = 0; f < 10; f ++)
1425  msg.readInt32("points");
1426 }
1427 
1429 {
1431  // +++ here need window with rank tables.
1432  for (int f = 0; f < 10; f ++)
1433  msg.readString(24, "name");
1434  for (int f = 0; f < 10; f ++)
1435  msg.readInt32("points");
1436 }
1437 
1439 {
1441  // +++ here need window with rank tables.
1442  for (int f = 0; f < 10; f ++)
1443  msg.readString(24, "name");
1444  for (int f = 0; f < 10; f ++)
1445  msg.readInt32("points");
1446 }
1447 
1449 {
1450  BLOCK_START("BeingRecv::processBeingChangeDirection")
1451  if (actorManager == nullptr)
1452  {
1453  BLOCK_END("BeingRecv::processBeingChangeDirection")
1454  return;
1455  }
1456 
1457  Being *const dstBeing = actorManager->findBeing(
1458  msg.readBeingId("being id"));
1459 
1460  msg.readInt16("head direction");
1461 
1462  const uint8_t dir = Net::MessageIn::fromServerDirection(
1463  CAST_U8(msg.readUInt8("player direction") & 0x0FU));
1464 
1465  if (dstBeing == nullptr)
1466  {
1467  BLOCK_END("BeingRecv::processBeingChangeDirection")
1468  return;
1469  }
1470 
1471  dstBeing->setDirection(dir);
1472  if (localPlayer != nullptr)
1473  localPlayer->imitateDirection(dstBeing, dir);
1474  BLOCK_END("BeingRecv::processBeingChangeDirection")
1475 }
1476 
1478 {
1479  if ((effectManager == nullptr) || (actorManager == nullptr))
1480  return;
1481 
1482  const BeingId id = msg.readBeingId("being id");
1483  Being *const being = actorManager->findBeing(id);
1484  if (being == nullptr)
1485  {
1486  msg.readInt32("effect type");
1487  return;
1488  }
1489 
1490  const int effectType = msg.readInt32("effect type");
1491 
1493  effectManager->trigger(effectType, being, 0);
1494 
1495  // +++ need dehard code effectType == 3
1496  if (effectType == 3 && being->getType() == ActorType::Player
1497  && (socialWindow != nullptr))
1498  { // reset received damage
1499  socialWindow->resetDamage(being->getName());
1500  }
1501 }
1502 
1504 {
1506  msg.readBeingId("being id");
1507  msg.readInt32("effect type");
1508 }
1509 
1511 {
1512  // +++ add new type of permanent effects?
1513  const int cnt = (msg.readInt16("len") - 9) / 2;
1514  if (cnt > 0)
1515  {
1517  }
1518  msg.readBeingId("being id");
1519  msg.readUInt8("enable");
1520  for (int f = 0; f < cnt; f ++)
1521  msg.readInt16("hat effect");
1522 }
1523 
1525 {
1527  // +++ need somhow show this effects.
1528  // type is not same with self/misc effect.
1529  msg.readBeingId("account id");
1530  msg.readInt32("effect type");
1531  msg.readInt32("num"); // effect variable
1532 }
1533 
1535 {
1537  // +++ need play this effect.
1538  msg.readString(24, "sound effect name");
1539  msg.readUInt8("type");
1540  msg.readInt32("unused");
1541  msg.readInt32("source being id");
1542 }
1543 
1545 {
1547  msg.readInt16("skill id");
1548  msg.readInt32("src id");
1549  msg.readInt16("val");
1550  msg.readInt16("x");
1551  msg.readInt16("y");
1552  msg.readInt32("tick");
1553 }
1554 
1556 {
1557  if (msg.getVersion() >= 20110718)
1558  msg.readInt16("len");
1559  const BeingId id = msg.readBeingId("skill unit id");
1560  const BeingId creatorId = msg.readBeingId("creator accound id");
1561  const int x = msg.readInt16("x");
1562  const int y = msg.readInt16("y");
1563  int job = 0;
1564  if (msg.getVersion() >= 20121212)
1565  job = msg.readInt32("job");
1566  if (msg.getVersion() >= 20110718)
1567  msg.readUInt8("radius");
1568  msg.readUInt8("visible");
1569  int level = 0;
1570  if (msg.getVersion() >= 20130731)
1571  level = msg.readUInt8("level");
1572  Being *const dstBeing = createBeing2(msg,
1573  id,
1574  job,
1576  if (dstBeing == nullptr)
1577  return;
1578  dstBeing->setAction(BeingAction::STAND, 0);
1579  dstBeing->setTileCoords(x, y);
1580  dstBeing->setLevel(level);
1581  dstBeing->setCreatorId(creatorId);
1582 }
1583 
1585 {
1586  BLOCK_START("BeingRecv::processPlayerStop")
1587  if (actorManager == nullptr)
1588  {
1589  BLOCK_END("BeingRecv::processPlayerStop")
1590  return;
1591  }
1592 
1593  // Change in players' flags
1594  const BeingId id = msg.readBeingId("account id");
1595  Being *const dstBeing = actorManager->findBeing(id);
1596  if (dstBeing == nullptr)
1597  {
1598  msg.readInt16("opt1");
1599  msg.readInt16("opt2");
1600  if (msg.getVersion() >= 7)
1601  msg.readInt32("option");
1602  else
1603  msg.readInt16("option");
1604  msg.readUInt8("karma");
1605  return;
1606  }
1607 
1608  const uint32_t opt1 = msg.readInt16("opt1");
1609  const uint32_t opt2 = msg.readInt16("opt2");
1610  uint32_t option;
1611  if (msg.getVersion() >= 7)
1612  option = msg.readInt32("option");
1613  else
1614  option = msg.readInt16("option");
1615  dstBeing->setKarma(msg.readUInt8("karma"));
1616 
1617  dstBeing->setStatusEffectOpitons(option,
1618  opt1,
1619  opt2);
1620  BLOCK_END("BeingRecv::processPlayerStop")
1621 }
1622 
1624 {
1625  if (actorManager == nullptr)
1626  return;
1627 
1628  // look like this function unused on server
1629 
1630  const BeingId id = msg.readBeingId("account id");
1631  Being *const dstBeing = actorManager->findBeing(id);
1632  if (dstBeing == nullptr)
1633  return;
1634 
1635  const uint32_t option = msg.readInt32("option");
1636  dstBeing->setLevel(msg.readInt32("level"));
1637  msg.readInt32("showEFST");
1638  dstBeing->setStatusEffectOpiton0(option);
1639 }
1640 
1642 {
1643  BLOCK_START("BeingRecv::processBeingResurrect")
1644  if (actorManager == nullptr ||
1645  localPlayer == nullptr)
1646  {
1647  BLOCK_END("BeingRecv::processBeingResurrect")
1648  return;
1649  }
1650 
1651  // A being changed mortality status
1652 
1653  const BeingId id = msg.readBeingId("being id");
1654  msg.readInt16("unused");
1655  Being *const dstBeing = actorManager->findBeing(id);
1656  if (dstBeing == nullptr)
1657  {
1658  DEBUGLOGSTR("insible player?");
1659  BLOCK_END("BeingRecv::processBeingResurrect")
1660  return;
1661  }
1662 
1663  // If this is player's current target, clear it.
1664  if (dstBeing == localPlayer->getTarget())
1665  localPlayer->stopAttack(false);
1666  if (dstBeing == localPlayer &&
1667  deathNotice != nullptr)
1668  {
1669  deathNotice->scheduleDelete();
1670  deathNotice = nullptr;
1671  }
1672 
1673  dstBeing->setAction(BeingAction::STAND, 0);
1674  BLOCK_END("BeingRecv::processBeingResurrect")
1675 }
1676 
1678 {
1679  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo")
1680  if (actorManager == nullptr)
1681  {
1682  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1683  return;
1684  }
1685 
1686  const BeingId beingId = msg.readBeingId("being id");
1687  const std::string name = msg.readString(24, "char name");
1688  actorManager->updateNameId(name, beingId);
1689  Being *const dstBeing = actorManager->findBeing(beingId);
1690  if (dstBeing != nullptr)
1691  {
1692  if (beingId == localPlayer->getId())
1693  {
1695  }
1696  dstBeing->setName(name);
1697  dstBeing->setPartyName(msg.readString(24, "party name"));
1698  dstBeing->setGuildName(msg.readString(24, "guild name"));
1699  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1700  dstBeing->addToCache();
1701  }
1702  else
1703  {
1704  msg.readString(24, "party name");
1705  msg.readString(24, "guild name");
1706  msg.readString(24, "guild pos");
1707  }
1708  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1709 }
1710 
1712 {
1713  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo2")
1714  if (actorManager == nullptr)
1715  {
1716  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo2")
1717  return;
1718  }
1719 
1720  const BeingId beingId = msg.readBeingId("being id");
1721  const std::string name = msg.readString(24, "char name");
1722  actorManager->updateNameId(name, beingId);
1723  Being *const dstBeing = actorManager->findBeing(beingId);
1724  if (dstBeing != nullptr)
1725  {
1726  if (beingId == localPlayer->getId())
1727  {
1729  }
1730  dstBeing->setName(name);
1731  dstBeing->setPartyName(msg.readString(24, "party name"));
1732  dstBeing->setGuildName(msg.readString(24, "guild name"));
1733  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1734  dstBeing->addToCache();
1735  }
1736  else
1737  {
1738  msg.readString(24, "party name");
1739  msg.readString(24, "guild name");
1740  msg.readString(24, "guild pos");
1741  }
1742  // +++ need use it for show player title
1743  msg.readInt32("title");
1744  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo2")
1745 }
1746 
1748 {
1749  const BeingId id = msg.readBeingId("skill unit id");
1750  if (actorManager == nullptr)
1751  return;
1752  Being *const dstBeing = actorManager->findBeing(id);
1753  if (dstBeing == nullptr)
1754  return;
1755  actorManager->destroy(dstBeing);
1756 }
1757 
1759 {
1760  uint16_t x;
1761  uint16_t y;
1762  uint8_t dir;
1763  if (msg.getVersion() < 20071106)
1764  {
1765  msg.readBeingId("npc id");
1766  msg.skip(8, "unused");
1767  msg.readInt16("class?"); // 111
1768  msg.skip(30, "unused");
1769  msg.readCoordinates(x, y, dir, "position");
1770  msg.readUInt8("sx");
1771  msg.readUInt8("sy");
1772  msg.skip(3, "unused");
1773  return;
1774  }
1775  const BeingTypeT type = static_cast<BeingTypeT>(
1776  msg.readUInt8("object type"));
1777  const BeingId id = msg.readBeingId("npc id");
1778  msg.skip(8, "unused");
1779  const uint16_t job = msg.readInt16("class?"); // 111
1780  msg.skip(30, "unused");
1781  msg.readCoordinates(x, y, dir, "position");
1782  msg.readUInt8("sx");
1783  msg.readUInt8("sy");
1784  msg.skip(3, "unused");
1785 
1786  Being *const dstBeing = createBeing2(msg, id, job, type);
1787  if (dstBeing == nullptr)
1788  return;
1789  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
1790  dstBeing->setTileCoords(x, y);
1791  dstBeing->setDirection(dir);
1792 }
1793 
1795 {
1796  const BeingId id = msg.readBeingId("account id");
1797  const int type = msg.readInt16("type");
1798  const int value = msg.readInt32("value");
1799 
1800  if (actorManager == nullptr)
1801  return;
1802  Being *const dstBeing = actorManager->findBeing(id);
1803  if (dstBeing == nullptr)
1804  return;
1805 
1806  if (type != Sp::MANNER)
1807  {
1809  return;
1810  }
1811  dstBeing->setManner(value);
1812 }
1813 
1815 {
1816  BLOCK_START("BeingRecv::processBeingSelfEffect")
1817  if ((effectManager == nullptr) || (actorManager == nullptr))
1818  {
1819  BLOCK_END("BeingRecv::processBeingSelfEffect")
1820  return;
1821  }
1822 
1823  const BeingId id = msg.readBeingId("being id");
1824  Being *const being = actorManager->findBeing(id);
1825  if (being == nullptr)
1826  {
1827  DEBUGLOGSTR("insible player?");
1828  msg.readInt32("effect type");
1829  BLOCK_END("BeingRecv::processBeingSelfEffect")
1830  return;
1831  }
1832 
1833  const int effectType = msg.readInt32("effect type");
1835  effectManager->trigger(effectType, being, 0);
1836 
1837  BLOCK_END("BeingRecv::processBeingSelfEffect")
1838 }
1839 
1841 {
1842  if (actorManager == nullptr)
1843  return;
1844  const int len = msg.readInt16("len");
1845  if (len < 12)
1846  return;
1847  Being *const dstBeing = actorManager->findBeing(
1848  msg.readBeingId("monster id"));
1849  const int attackRange = msg.readInt32("range");
1850  if (dstBeing != nullptr)
1851  dstBeing->setAttackRange(attackRange);
1852 }
1853 
1855 {
1856  if (actorManager == nullptr)
1857  return;
1858  const int len = msg.readInt16("len");
1859  if (len < 14)
1860  return;
1861 
1862  Being *const dstBeing = actorManager->findBeing(
1863  msg.readBeingId("player id"));
1864  const int groupId = msg.readInt32("group id");
1865  uint16_t mount = 0;
1866  mount = msg.readInt16("mount");
1867  int language = -1;
1868  if (len > 14)
1869  language = msg.readInt16("language");
1870  int clanId = 0;
1871  if (len > 16)
1872  clanId = msg.readInt32("clan id");
1873  if (dstBeing != nullptr)
1874  {
1875  if (dstBeing != localPlayer)
1876  {
1877  dstBeing->setGroupId(groupId);
1878  }
1879  dstBeing->setHorse(mount);
1880  dstBeing->setLanguageId(language);
1881  if (clanId != 0)
1882  {
1883  const ClanInfo *const info = ClanDb::get(clanId);
1884  if (info == nullptr)
1885  dstBeing->setClanName(std::string());
1886  else
1887  dstBeing->setClanName(info->name);
1888  }
1889  else
1890  {
1891  dstBeing->setClanName(std::string());
1892  }
1893  if (dstBeing == localPlayer)
1895  }
1896 }
1897 
1899 {
1901 
1902  msg.readInt16("class");
1903  msg.readInt16("level");
1904  msg.readInt16("size");
1905  msg.readInt32("hp");
1906  msg.readInt16("def");
1907  msg.readInt16("race");
1908  msg.readInt16("mdef");
1909  msg.readInt16("ele");
1910 }
1911 
1913 {
1915 
1916  msg.readBeingId("being id");
1917  msg.readUInt8("type");
1918  msg.readInt32("class");
1919 }
1920 
1922 {
1923  if (actorManager == nullptr)
1924  return;
1925  Being *const dstBeing = actorManager->findBeing(
1926  msg.readBeingId("being id"));
1927  const int balls = msg.readInt16("spirits amount");
1928  if (dstBeing != nullptr)
1929  dstBeing->setSpiritBalls(balls);
1930 }
1931 
1933 {
1935 
1936  msg.readInt32("src being id");
1937  msg.readInt32("dst being id");
1938  msg.readInt32("flag");
1939 }
1940 
1942 {
1944 
1945  msg.readBeingId("being id");
1946  msg.readInt32("wait");
1947 }
1948 
1950 {
1952 
1953  msg.readBeingId("being id");
1954 }
1955 
1957 {
1958  if (actorManager == nullptr)
1959  return;
1960  Being *const dstBeing = actorManager->findBeing(
1961  msg.readBeingId("being id"));
1962  const int x = msg.readInt16("x");
1963  const int y = msg.readInt16("y");
1964  if (dstBeing == nullptr)
1965  return;
1966  if (localPlayer == dstBeing)
1967  {
1968  localPlayer->stopAttack(false);
1970  if (viewport != nullptr)
1972  }
1973 
1974  dstBeing->setAction(BeingAction::STAND, 0);
1975  dstBeing->setTileCoords(x, y);
1976 }
1977 
1979 {
1981 
1982  msg.readString(24, "map name");
1983  msg.readInt32("monster id");
1984  msg.readUInt8("start");
1985  msg.readUInt8("result");
1986 }
1987 
1989 {
1991 
1992  msg.readUInt8("which");
1993 }
1994 
1996 {
1998 
1999  msg.readUInt8("info type");
2000  msg.readInt32("x");
2001  msg.readInt32("y");
2002  msg.readInt16("min hours");
2003  msg.readInt16("min minutes");
2004  msg.readInt16("max hours");
2005  msg.readInt16("max minutes");
2006  msg.readString(24, "monster name"); // really can be used 51 byte?
2007 }
2008 
2010 {
2012 
2013  msg.readBeingId("account id");
2014  msg.readInt16("font");
2015 }
2016 
2018 {
2020 
2021  msg.readBeingId("account id");
2022  msg.readInt16("shields");
2023  msg.readInt16("unused");
2024 }
2025 
2027 {
2029 
2030  msg.readBeingId("account id");
2031  msg.readInt16("charm type");
2032  msg.readInt16("charm count");
2033 }
2034 
2036 {
2038 
2039  const int count = (msg.readInt16("len") - 45) / (21 + itemIdLen * 5);
2040  msg.readString(24, "name");
2041  msg.readInt16("job");
2042  msg.readInt16("head");
2043  msg.readInt16("accessory");
2044  msg.readInt16("accessory2");
2045  msg.readInt16("accessory3");
2046  if (msg.getVersion() >= 20101124)
2047  msg.readInt16("robe");
2048  msg.readInt16("hair color");
2049  msg.readInt16("body color");
2050  msg.readUInt8("gender");
2051  for (int f = 0; f < count; f ++)
2052  {
2053  msg.readInt16("index");
2054  msg.readItemId("item id");
2055  msg.readUInt8("item type");
2056  msg.readInt32("location");
2057  msg.readInt32("wear state");
2058  msg.readInt8("refine");
2059  for (int d = 0; d < maxCards; d ++)
2060  msg.readItemId("card");
2061  msg.readInt32("hire expire date (?)");
2062  msg.readInt16("equip type");
2063  msg.readInt16("item sprite number");
2064  msg.readUInt8("flags");
2065  }
2066 }
2067 
2069 {
2071 
2072  const int count = (msg.readInt16("len") - 47) / (21 + itemIdLen * 5);
2073  msg.readString(24, "name");
2074  msg.readInt16("job");
2075  msg.readInt16("head");
2076  msg.readInt16("accessory");
2077  msg.readInt16("accessory2");
2078  msg.readInt16("accessory3");
2079  msg.readInt16("robe");
2080  msg.readInt16("hair color");
2081  msg.readInt16("body color");
2082  msg.readInt16("body2");
2083  msg.readUInt8("gender");
2084  for (int f = 0; f < count; f ++)
2085  {
2086  msg.readInt16("index");
2087  msg.readItemId("item id");
2088  msg.readUInt8("item type");
2089  msg.readInt32("location");
2090  msg.readInt32("wear state");
2091  msg.readInt8("refine");
2092  for (int d = 0; d < maxCards; d ++)
2093  msg.readItemId("card");
2094  msg.readInt32("hire expire date (?)");
2095  msg.readInt16("equip type");
2096  msg.readInt16("item sprite number");
2097  msg.readUInt8("flags");
2098  }
2099 }
2100 
2102 {
2103  BLOCK_START("BeingRecv::processPvpSet")
2104  const BeingId id = msg.readBeingId("being id");
2105  const int rank = msg.readInt32("rank");
2106  msg.readInt32("num");
2107  if (actorManager != nullptr)
2108  {
2109  Being *const dstBeing = actorManager->findBeing(id);
2110  if (dstBeing != nullptr)
2111  dstBeing->setPvpRank(rank);
2112  }
2113  BLOCK_END("BeingRecv::processPvpSet")
2114 }
2115 
2117 {
2118  BLOCK_START("BeingRecv::processNameResponse2")
2119  if ((actorManager == nullptr) || (localPlayer == nullptr))
2120  {
2121  BLOCK_END("BeingRecv::processNameResponse2")
2122  return;
2123  }
2124 
2125  const int len = msg.readInt16("len");
2126  const BeingId beingId = msg.readBeingId("account id");
2127  const std::string str = msg.readString(len - 8, "name");
2128  actorManager->updateNameId(str, beingId);
2129  Being *const dstBeing = actorManager->findBeing(beingId);
2130  if (dstBeing != nullptr)
2131  {
2132  if (beingId == localPlayer->getId())
2133  {
2135  }
2136  else
2137  {
2138  dstBeing->setName(str);
2139  dstBeing->updateGuild();
2140  dstBeing->addToCache();
2141 
2142  if (dstBeing->getType() == ActorType::Player)
2143  dstBeing->updateColors();
2144 
2145  if (localPlayer != nullptr)
2146  {
2147  const Party *const party = localPlayer->getParty();
2148  if (party != nullptr && party->isMember(dstBeing->getId()))
2149  {
2150  PartyMember *const member = party->getMember(
2151  dstBeing->getId());
2152 
2153  if (member != nullptr)
2154  member->setName(dstBeing->getName());
2155  }
2156  localPlayer->checkNewName(dstBeing);
2157  }
2158  }
2159  }
2160  BLOCK_END("BeingRecv::processNameResponse2")
2161 }
2162 
2164  const BeingId id,
2165  const int32_t job,
2166  const BeingTypeT beingType)
2167 {
2168  if (actorManager == nullptr)
2169  return nullptr;
2170 
2172  switch (beingType)
2173  {
2174  case BeingType::PC:
2175  type = ActorType::Player;
2176  break;
2177  case BeingType::NPC:
2178  case BeingType::NPC_EVENT:
2179  type = ActorType::Npc;
2180  break;
2181  case BeingType::MONSTER:
2182  type = ActorType::Monster;
2183  break;
2184  case BeingType::MERSOL:
2185  type = ActorType::Mercenary;
2186  break;
2187  case BeingType::PET:
2188  type = ActorType::Pet;
2189  break;
2190  case BeingType::HOMUN:
2191  type = ActorType::Homunculus;
2192  break;
2193  case BeingType::SKILL:
2194  type = ActorType::SkillUnit;
2195  break;
2196  case BeingType::ELEMENTAL:
2197  type = ActorType::Elemental;
2198  break;
2199  case BeingType::ITEM:
2200  logger->log("not supported object type: %d, job: %d",
2201  CAST_S32(beingType), CAST_S32(job));
2202  break;
2203  case BeingType::CHAT:
2204  default:
2205  UNIMPLEMENTEDPACKETFIELD(CAST_S32(beingType));
2206  type = ActorType::Monster;
2207  logger->log("not supported object type: %d, job: %d",
2208  CAST_S32(beingType), CAST_S32(job));
2209  break;
2210  }
2211  if (job == 45 && beingType == BeingType::NPC_EVENT)
2212  type = ActorType::Portal;
2213 
2214  Being *const being = actorManager->createBeing(
2215  id, type, fromInt(job, BeingTypeId));
2216  if (beingType == BeingType::MERSOL)
2217  {
2218  const MercenaryInfo *const info = PlayerInfo::getMercenary();
2219  if ((info != nullptr) && info->id == id)
2221  }
2222  else if (beingType == BeingType::PET)
2223  {
2224  if (PlayerInfo::getPetBeingId() == id)
2225  PlayerInfo::setPetBeing(being);
2226  }
2227  return being;
2228 }
2229 
2231 {
2232  msg.readInt32("id?");
2233 }
2234 
2236 {
2237  if ((packets_re == true && msg.getVersion() >= 20180221) ||
2238  (packets_main == true && msg.getVersion() >= 20180307) ||
2239  (packets_zero == true && msg.getVersion() >= 20180328))
2240  {
2241  const int flag = msg.readInt16("flag");
2242  // name request errors
2243  if (flag != 3)
2244  return;
2245  }
2246  const int id = msg.readInt32("char id");
2247  if (actorManager == nullptr)
2248  {
2249  msg.readString(24, "name");
2250  return;
2251  }
2252  actorManager->addChar(id, msg.readString(24, "name"));
2253 }
2254 
2256 {
2257  const BeingId id = msg.readBeingId("graffiti id");
2258  const BeingId creatorId = msg.readBeingId("creator id");
2259  const int x = msg.readInt16("x");
2260  const int y = msg.readInt16("y");
2261  const int job = msg.readUInt8("job");
2262  msg.readUInt8("visible");
2263  msg.readUInt8("is content");
2264  const std::string text = msg.readString(80, "text");
2265 
2266  Being *const dstBeing = createBeing2(msg, id, job, BeingType::SKILL);
2267  if (dstBeing == nullptr)
2268  return;
2269 
2270  dstBeing->setAction(BeingAction::STAND, 0);
2271  dstBeing->setTileCoords(x, y);
2272  dstBeing->setShowName(true);
2273  dstBeing->setName(text);
2274  dstBeing->setCreatorId(creatorId);
2275 }
2276 
2278 {
2279  BLOCK_START("BeingRecv::processSkillDamage")
2280  if (actorManager == nullptr)
2281  {
2282  BLOCK_END("BeingRecv::processSkillDamage")
2283  return;
2284  }
2285 
2286  const int id = msg.readInt16("skill id");
2287  Being *const srcBeing = actorManager->findBeing(
2288  msg.readBeingId("src being id"));
2289  Being *const dstBeing = actorManager->findBeing(
2290  msg.readBeingId("dst being id"));
2291  msg.readInt32("tick");
2292  msg.readInt32("src speed");
2293  msg.readInt32("dst speed");
2294  int param1;
2295  if (msg.getVersion() >= 3)
2296  param1 = msg.readInt32("damage");
2297  else
2298  param1 = msg.readInt16("damage");
2299  const int level = msg.readInt16("skill level");
2300  msg.readInt16("div");
2301  msg.readUInt8("skill hit/type?");
2302  if (srcBeing != nullptr)
2303  srcBeing->handleSkill(dstBeing, param1, id, level);
2304  if (dstBeing != nullptr)
2305  dstBeing->takeDamage(srcBeing, param1, AttackType::SKILL, id, level);
2306  BLOCK_END("BeingRecv::processSkillDamage")
2307 }
2308 
2310 {
2312  // 0 position
2313  // 1 no position
2314  // 3 monster
2315  msg.readUInt8("navigate type");
2316  msg.readUInt8("transportation flag");
2317  msg.readUInt8("hide window");
2318  msg.readString(16, "map name");
2319  msg.readInt16("x");
2320  msg.readInt16("y");
2321  msg.readInt16("mob id");
2322 }
2323 
2325  Being *const being,
2326  const uint8_t type)
2327 {
2328  if (being == nullptr)
2329  return;
2330  switch (type)
2331  {
2332  case 0:
2333  being->setAction(BeingAction::STAND, 0);
2335  break;
2336 
2337  case 1:
2338  if (being->getCurrentAction() != BeingAction::DEAD)
2339  {
2340  being->setAction(BeingAction::DEAD, 0);
2341  being->recalcSpritesOrder();
2342  }
2343  break;
2344 
2345  case 2:
2346  being->setAction(BeingAction::SIT, 0);
2348  break;
2349 
2350  default:
2352  break;
2353  }
2354 }
2355 
2356 } // namespace EAthena
void processBeingFont(Net::MessageIn &msg)
Definition: beingrecv.cpp:2009
#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:1235
#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:1956
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 processSkillCastingEvol(Net::MessageIn &msg)
Definition: beingrecv.cpp:1064
void setPetBeing(Being *const being)
Definition: playerinfo.cpp:559
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:1544
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:1524
#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:1510
void processNavigateTo(Net::MessageIn &msg)
Definition: beingrecv.cpp:2309
BeingId getId() const
Definition: actorsprite.h:63
void setOtherTime()
Definition: being.h:717
void processBeingHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1338
void destroy(ActorSprite *const actor)
void processBossMapInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1995
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:1438
void processBeingChangeLookCards(Net::MessageIn &msg)
Definition: beingrecv.cpp:217
void processClassChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1912
void processPlayerGuilPartyInfo2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1711
void processGraffiti(Net::MessageIn &msg)
Definition: beingrecv.cpp:2255
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:603
void processBeingViewEquipment(Net::MessageIn &msg)
Definition: beingrecv.cpp:2035
void processGladiatorFeelRequest(Net::MessageIn &msg)
Definition: beingrecv.cpp:1988
void notify(const unsigned int message)
#define A_NONNULL(...)
Definition: localconsts.h:167
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:295
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:1840
void processComboDelay(Net::MessageIn &msg)
Definition: beingrecv.cpp:1941
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:2235
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:2116
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:548
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:1584
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:99
void returnCamera()
Definition: viewport.cpp:1110
void processAlchemistRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1418
void processBeingSoundEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1534
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:1641
void setStatusEffectOpiton0(const uint32_t option)
void processMonsterHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1363
void processSkillDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:2277
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:1428
bool info(InputEvent &event)
Definition: commands.cpp:56
void processMonsterInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1898
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:327
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:135
void processBeingSpecialEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1477
LocalPlayer * localPlayer
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:365
void processBeingRemoveSpecialEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1503
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:1623
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:1949
void processSkillAutoCast(Net::MessageIn &msg)
Definition: beingrecv.cpp:1378
void processBeingSpawn(Net::MessageIn &msg)
Definition: beingrecv.cpp:800
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:1747
void imitateDirection(const Being *const being, const unsigned char dir)
Definition: map.h:71
void processBladeStop(Net::MessageIn &msg)
Definition: beingrecv.cpp:1932
void processBeingSelfEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1814
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:830
void checkNewName(Being *const being)
void processSkillCasting2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1021
void processSkillCasting3(Net::MessageIn &msg)
Definition: beingrecv.cpp:1042
void processSkillEntry(Net::MessageIn &msg)
Definition: beingrecv.cpp:1555
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:2324
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:973
void followMoveTo(const Being *const being, const int x, const int y)
void processPvpSet(Net::MessageIn &msg)
Definition: beingrecv.cpp:2101
void processBeingChangeDirection(Net::MessageIn &msg)
Definition: beingrecv.cpp:1448
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:1921
Window * deathNotice
Definition: sp.h:34
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1677
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1186
void processMapType(Net::MessageIn &msg)
Definition: beingrecv.cpp:992
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:1090
static Game * instance()
Definition: game.h:81
void recalcSpritesOrder()
Definition: being.cpp:4359
void setMercenaryBeing(Being *const being)
Definition: playerinfo.cpp:525
void processRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1396
#define restrict
Definition: localconsts.h:164
std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:383
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1153
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
BeingId getPetBeingId()
Definition: playerinfo.cpp:580
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:265
void log(const char *const log_text,...)
Definition: logger.cpp:264
virtual bool haveMove3() const =0
void setServerLanguage(const int lang)
Definition: playerinfo.cpp:667
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:2163
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
void processBlacksmithRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1408
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:1001
void processSkillCancel(Net::MessageIn &msg)
Definition: beingrecv.cpp:2230
int itemIdLen
Definition: client.cpp:129
virtual void setGroupId(const int id)
Definition: being.cpp:5587
void processBeingStatUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:1794
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:2026
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:1978
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:1854
Viewport * viewport
Definition: viewport.cpp:35
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void processBeingMilleniumShield(Net::MessageIn &msg)
Definition: beingrecv.cpp:2017
void processBeingFakeName(Net::MessageIn &msg)
Definition: beingrecv.cpp:1758
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
void processBeingViewEquipment2(Net::MessageIn &msg)
Definition: beingrecv.cpp:2068