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;
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("property"); // can be used to trigger effect
1009  const int castTime = msg.readInt32("cast time");
1010  if (msg.getVersion() >= 20091124)
1011  msg.readInt8("dispossable");
1012 
1014  srcId, dstId,
1015  dstX, dstY,
1016  skillId,
1017  1,
1018  0,
1020  castTime);
1021 }
1022 
1024 {
1025  msg.readInt16("len"); // for now unused
1026  const BeingId srcId = msg.readBeingId("src id");
1027  const BeingId dstId = msg.readBeingId("dst id");
1028  const int dstX = msg.readInt16("dst x");
1029  const int dstY = msg.readInt16("dst y");
1030  const int skillId = msg.readInt16("skill id");
1031  const int skillLevel = msg.readInt16("skill level");
1032  msg.readInt32("property"); // can be used to trigger effect
1033  const int castTime = msg.readInt32("cast time");
1034  const int range = msg.readInt32("skill range");
1035  const SkillType2::SkillType2 inf2 =
1036  static_cast<SkillType2::SkillType2>(msg.readInt32("inf2"));
1037 
1039  srcId, dstId,
1040  dstX, dstY,
1041  skillId,
1042  skillLevel,
1043  range,
1044  inf2,
1045  castTime);
1046 }
1047 
1049  const BeingId srcId,
1050  const BeingId dstId,
1051  const int dstX,
1052  const int dstY,
1053  const int skillId,
1054  const int skillLevel,
1055  const int range,
1056  const SkillType2::SkillType2 inf2,
1057  const int castTime)
1058 {
1059  if (effectManager == nullptr ||
1060  actorManager == nullptr)
1061  return;
1062 
1063  if (srcId == BeingId_zero)
1064  {
1066  return;
1067  }
1068  Being *const srcBeing = actorManager->findBeing(srcId);
1069  if (dstId != BeingId_zero)
1070  { // being to being
1071  Being *const dstBeing = actorManager->findBeing(dstId);
1072  if (srcBeing != nullptr)
1073  {
1074  srcBeing->handleSkillCasting(dstBeing, skillId, skillLevel);
1075  if (dstBeing != nullptr)
1076  {
1077  srcBeing->addCast(dstBeing->getTileX(),
1078  dstBeing->getTileY(),
1079  skillId,
1080  skillLevel,
1081  range,
1082  castTime / MILLISECONDS_IN_A_TICK);
1083  }
1084  }
1085  }
1086  else if (dstX != 0 || dstY != 0)
1087  { // being to position
1088  if (srcBeing != nullptr)
1089  srcBeing->setAction(BeingAction::CAST, skillId);
1091  skillLevel,
1092  dstX, dstY,
1093  castTime);
1094  if (srcBeing != nullptr)
1095  {
1096  srcBeing->addCast(dstX, dstY,
1097  skillId,
1098  skillLevel,
1099  range,
1100  castTime / MILLISECONDS_IN_A_TICK);
1101  }
1102  }
1103  if ((localPlayer != nullptr) &&
1104  srcBeing == localPlayer &&
1105  (inf2 & SkillType2::FreeCastAny) == 0)
1106  {
1108  }
1109 }
1110 
1112 {
1113  BLOCK_START("BeingRecv::processBeingStatusChange")
1114  if (actorManager == nullptr)
1115  {
1116  BLOCK_END("BeingRecv::processBeingStatusChange")
1117  return;
1118  }
1119 
1120  // Status change
1121  const uint16_t status = msg.readInt16("status");
1122  const BeingId id = msg.readBeingId("being id");
1123  const Enable flag = fromBool(
1124  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1125  if (msg.getVersion() >= 20120618)
1126  msg.readInt32("total");
1127  if (msg.getVersion() >= 20090121)
1128  {
1129  msg.readInt32("left");
1130  msg.readInt32("val1");
1131  msg.readInt32("val2");
1132  msg.readInt32("val3");
1133  }
1134 
1135  const IsStart start = msg.getVersion() == 20090121 ?
1137 
1138  Being *const dstBeing = actorManager->findBeing(id);
1139  if (dstBeing != nullptr)
1140  dstBeing->setStatusEffect(status, flag, start);
1141  BLOCK_END("BeingRecv::processBeingStatusChange")
1142 }
1143 
1145 {
1146  BLOCK_START("BeingRecv::processBeingMove2")
1147  if (actorManager == nullptr)
1148  {
1149  BLOCK_END("BeingRecv::processBeingMove2")
1150  return;
1151  }
1152 
1153  /*
1154  * A simplified movement packet, used by the
1155  * later versions of eAthena for both mobs and
1156  * players
1157  */
1158  Being *const dstBeing = actorManager->findBeing(
1159  msg.readBeingId("being id"));
1160 
1161  uint16_t srcX;
1162  uint16_t srcY;
1163  uint16_t dstX;
1164  uint16_t dstY;
1165  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1166  msg.readUInt8("(sx<<4) | (sy&0x0f)");
1167  msg.readInt32("tick");
1168 
1169  /*
1170  * This packet doesn't have enough info to actually
1171  * create a new being, so if the being isn't found,
1172  * we'll just pretend the packet didn't happen
1173  */
1174 
1175  if (dstBeing == nullptr)
1176  {
1177  BLOCK_END("BeingRecv::processBeingMove2")
1178  return;
1179  }
1180 
1181  dstBeing->setTileCoords(srcX, srcY);
1182  if (localPlayer != nullptr)
1183  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
1184  if (serverFeatures->haveMove3())
1185  dstBeing->setCachedDestination(dstX, dstY);
1186  else
1187  dstBeing->setDestination(dstX, dstY);
1188  if (dstBeing->getType() == ActorType::Player)
1189  dstBeing->setMoveTime();
1190  BLOCK_END("BeingRecv::processBeingMove2")
1191 }
1192 
1194 {
1195  BLOCK_START("BeingRecv::processBeingAction2")
1196  if (actorManager == nullptr)
1197  {
1198  BLOCK_END("BeingRecv::processBeingAction2")
1199  return;
1200  }
1201 
1202  Being *const srcBeing = actorManager->findBeing(
1203  msg.readBeingId("src being id"));
1204  Being *const dstBeing = actorManager->findBeing(
1205  msg.readBeingId("dst being id"));
1206 
1207  msg.readInt32("tick");
1208  const int srcSpeed = msg.readInt32("src speed");
1209  msg.readInt32("dst speed");
1210  int param1;
1211  if (msg.getVersion() >= 20071113)
1212  param1 = msg.readInt32("damage");
1213  else
1214  param1 = msg.readInt16("damage");
1215  if (msg.getVersion() >= 20131223)
1216  msg.readUInt8("is sp damaged");
1217  msg.readInt16("count");
1218  const AttackTypeT type = static_cast<AttackTypeT>(
1219  msg.readUInt8("action"));
1220  if (msg.getVersion() >= 20071113)
1221  msg.readInt32("left damage");
1222  else
1223  msg.readInt16("left damage");
1224 
1225  switch (type)
1226  {
1227  case AttackType::HIT: // Damage
1228  case AttackType::CRITICAL: // Critical Damage
1229  case AttackType::MULTI: // Critical Damage
1231  case AttackType::REFLECT: // Reflected Damage
1232  case AttackType::FLEE: // Lucky Dodge
1233  case AttackType::SPLASH:
1234  case AttackType::SKILL:
1235  case AttackType::REPEATE:
1236  if (srcBeing != nullptr)
1237  {
1238  if (srcSpeed != 0 && srcBeing->getType() == ActorType::Player)
1239  srcBeing->setAttackDelay(srcSpeed);
1240  // attackid=1, type
1241  srcBeing->handleAttack(dstBeing, param1, 1);
1242  if (srcBeing->getType() == ActorType::Player)
1243  srcBeing->setAttackTime();
1244  }
1245  if (dstBeing != nullptr)
1246  {
1247  // level not present, using 1
1248  dstBeing->takeDamage(srcBeing, param1,
1249  static_cast<AttackTypeT>(type), 1, 1);
1250  }
1251  break;
1252 
1253  case AttackType::PICKUP:
1254  break;
1255 
1257  break;
1258 
1259  case AttackType::SIT:
1260  if (srcBeing != nullptr)
1261  {
1262  srcBeing->setAction(BeingAction::SIT, 0);
1263  if (srcBeing->getType() == ActorType::Player)
1264  {
1265  srcBeing->setMoveTime();
1266  if (localPlayer != nullptr)
1268  }
1269  }
1270  break;
1271 
1272  case AttackType::STAND:
1273  if (srcBeing != nullptr)
1274  {
1275  srcBeing->setAction(BeingAction::STAND, 0);
1276  if (srcBeing->getType() == ActorType::Player)
1277  {
1278  srcBeing->setMoveTime();
1279  if (localPlayer != nullptr)
1280  {
1281  localPlayer->imitateAction(srcBeing,
1283  }
1284  }
1285  }
1286  break;
1287  default:
1288  case AttackType::MISS:
1289  case AttackType::SKILLMISS:
1291  break;
1292  }
1293  BLOCK_END("BeingRecv::processBeingAction2")
1294 }
1295 
1297 {
1298  if (actorManager == nullptr)
1299  return;
1300  Being *const dstBeing = actorManager->findBeing(
1301  msg.readBeingId("being id"));
1302  int hp;
1303  int maxHP;
1304  if (msg.getVersion() >= 20100126)
1305  {
1306  hp = msg.readInt32("hp");
1307  maxHP = msg.readInt32("max hp");
1308  }
1309  else
1310  {
1311  hp = msg.readInt16("hp");
1312  maxHP = msg.readInt16("max hp");
1313  }
1314  if (dstBeing != nullptr)
1315  {
1316  dstBeing->setHP(hp);
1317  dstBeing->setMaxHP(maxHP);
1318  }
1319 }
1320 
1322 {
1323  if (actorManager == nullptr)
1324  return;
1325  Being *const dstBeing = actorManager->findBeing(
1326  msg.readBeingId("monster id"));
1327  const int hp = msg.readInt32("hp");
1328  const int maxHP = msg.readInt32("max hp");
1329  if (dstBeing != nullptr)
1330  {
1331  dstBeing->setHP(hp);
1332  dstBeing->setMaxHP(maxHP);
1333  }
1334 }
1335 
1337 {
1338  const int id = msg.readInt16("skill id");
1339  msg.readInt16("inf");
1340  msg.readInt16("unused");
1341  const int level = msg.readInt16("skill level");
1342  msg.readInt16("sp");
1343  msg.readInt16("range");
1344  msg.readString(24, "skill name");
1345  msg.readInt8("unused");
1346 
1347  if (localPlayer != nullptr)
1348  {
1349  localPlayer->handleSkill(localPlayer, 0, id, level);
1351  }
1352 }
1353 
1355 {
1357  // +++ here need window with rank tables.
1358  msg.readInt16("rank type");
1359  for (int f = 0; f < 10; f ++)
1360  msg.readString(24, "name");
1361  for (int f = 0; f < 10; f ++)
1362  msg.readInt32("points");
1363  msg.readInt32("my points");
1364 }
1365 
1367 {
1369  // +++ here need window with rank tables.
1370  for (int f = 0; f < 10; f ++)
1371  msg.readString(24, "name");
1372  for (int f = 0; f < 10; f ++)
1373  msg.readInt32("points");
1374 }
1375 
1377 {
1379  // +++ here need window with rank tables.
1380  for (int f = 0; f < 10; f ++)
1381  msg.readString(24, "name");
1382  for (int f = 0; f < 10; f ++)
1383  msg.readInt32("points");
1384 }
1385 
1387 {
1389  // +++ here need window with rank tables.
1390  for (int f = 0; f < 10; f ++)
1391  msg.readString(24, "name");
1392  for (int f = 0; f < 10; f ++)
1393  msg.readInt32("points");
1394 }
1395 
1397 {
1399  // +++ here need window with rank tables.
1400  for (int f = 0; f < 10; f ++)
1401  msg.readString(24, "name");
1402  for (int f = 0; f < 10; f ++)
1403  msg.readInt32("points");
1404 }
1405 
1407 {
1408  BLOCK_START("BeingRecv::processBeingChangeDirection")
1409  if (actorManager == nullptr)
1410  {
1411  BLOCK_END("BeingRecv::processBeingChangeDirection")
1412  return;
1413  }
1414 
1415  Being *const dstBeing = actorManager->findBeing(
1416  msg.readBeingId("being id"));
1417 
1418  msg.readInt16("head direction");
1419 
1420  const uint8_t dir = Net::MessageIn::fromServerDirection(
1421  CAST_U8(msg.readUInt8("player direction") & 0x0FU));
1422 
1423  if (dstBeing == nullptr)
1424  {
1425  BLOCK_END("BeingRecv::processBeingChangeDirection")
1426  return;
1427  }
1428 
1429  dstBeing->setDirection(dir);
1430  if (localPlayer != nullptr)
1431  localPlayer->imitateDirection(dstBeing, dir);
1432  BLOCK_END("BeingRecv::processBeingChangeDirection")
1433 }
1434 
1436 {
1437  if ((effectManager == nullptr) || (actorManager == nullptr))
1438  return;
1439 
1440  const BeingId id = msg.readBeingId("being id");
1441  Being *const being = actorManager->findBeing(id);
1442  if (being == nullptr)
1443  {
1444  msg.readInt32("effect type");
1445  return;
1446  }
1447 
1448  const int effectType = msg.readInt32("effect type");
1449 
1451  effectManager->trigger(effectType, being, 0);
1452 
1453  // +++ need dehard code effectType == 3
1454  if (effectType == 3 && being->getType() == ActorType::Player
1455  && (socialWindow != nullptr))
1456  { // reset received damage
1457  socialWindow->resetDamage(being->getName());
1458  }
1459 }
1460 
1462 {
1464  msg.readBeingId("being id");
1465  msg.readInt32("effect type");
1466 }
1467 
1469 {
1470  // +++ add new type of permanent effects?
1471  const int cnt = (msg.readInt16("len") - 9) / 2;
1472  if (cnt > 0)
1473  {
1475  }
1476  msg.readBeingId("being id");
1477  msg.readUInt8("enable");
1478  for (int f = 0; f < cnt; f ++)
1479  msg.readInt16("hat effect");
1480 }
1481 
1483 {
1485  // +++ need somhow show this effects.
1486  // type is not same with self/misc effect.
1487  msg.readBeingId("account id");
1488  msg.readInt32("effect type");
1489  msg.readInt32("num"); // effect variable
1490 }
1491 
1493 {
1495  // +++ need play this effect.
1496  msg.readString(24, "sound effect name");
1497  msg.readUInt8("type");
1498  msg.readInt32("unused");
1499  msg.readInt32("source being id");
1500 }
1501 
1503 {
1505  msg.readInt16("skill id");
1506  msg.readInt32("src id");
1507  msg.readInt16("val");
1508  msg.readInt16("x");
1509  msg.readInt16("y");
1510  msg.readInt32("tick");
1511 }
1512 
1514 {
1515  if (msg.getVersion() >= 20110718)
1516  msg.readInt16("len");
1517  const BeingId id = msg.readBeingId("skill unit id");
1518  const BeingId creatorId = msg.readBeingId("creator accound id");
1519  const int x = msg.readInt16("x");
1520  const int y = msg.readInt16("y");
1521  int job = 0;
1522  if (msg.getVersion() >= 20121212)
1523  job = msg.readInt32("job");
1524  if (msg.getVersion() >= 20110718)
1525  msg.readUInt8("radius");
1526  msg.readUInt8("visible");
1527  int level = 0;
1528  if (msg.getVersion() >= 20130731)
1529  level = msg.readUInt8("level");
1530  Being *const dstBeing = createBeing2(msg,
1531  id,
1532  job,
1534  if (dstBeing == nullptr)
1535  return;
1536  dstBeing->setAction(BeingAction::STAND, 0);
1537  dstBeing->setTileCoords(x, y);
1538  dstBeing->setLevel(level);
1539  dstBeing->setCreatorId(creatorId);
1540 }
1541 
1543 {
1544  BLOCK_START("BeingRecv::processPlayerStop")
1545  if (actorManager == nullptr)
1546  {
1547  BLOCK_END("BeingRecv::processPlayerStop")
1548  return;
1549  }
1550 
1551  // Change in players' flags
1552  const BeingId id = msg.readBeingId("account id");
1553  Being *const dstBeing = actorManager->findBeing(id);
1554  if (dstBeing == nullptr)
1555  {
1556  msg.readInt16("opt1");
1557  msg.readInt16("opt2");
1558  if (msg.getVersion() >= 7)
1559  msg.readInt32("option");
1560  else
1561  msg.readInt16("option");
1562  msg.readUInt8("karma");
1563  return;
1564  }
1565 
1566  const uint32_t opt1 = msg.readInt16("opt1");
1567  const uint32_t opt2 = msg.readInt16("opt2");
1568  uint32_t option;
1569  if (msg.getVersion() >= 7)
1570  option = msg.readInt32("option");
1571  else
1572  option = msg.readInt16("option");
1573  dstBeing->setKarma(msg.readUInt8("karma"));
1574 
1575  dstBeing->setStatusEffectOpitons(option,
1576  opt1,
1577  opt2);
1578  BLOCK_END("BeingRecv::processPlayerStop")
1579 }
1580 
1582 {
1583  if (actorManager == nullptr)
1584  return;
1585 
1586  // look like this function unused on server
1587 
1588  const BeingId id = msg.readBeingId("account id");
1589  Being *const dstBeing = actorManager->findBeing(id);
1590  if (dstBeing == nullptr)
1591  return;
1592 
1593  const uint32_t option = msg.readInt32("option");
1594  dstBeing->setLevel(msg.readInt32("level"));
1595  msg.readInt32("showEFST");
1596  dstBeing->setStatusEffectOpiton0(option);
1597 }
1598 
1600 {
1601  BLOCK_START("BeingRecv::processBeingResurrect")
1602  if (actorManager == nullptr ||
1603  localPlayer == nullptr)
1604  {
1605  BLOCK_END("BeingRecv::processBeingResurrect")
1606  return;
1607  }
1608 
1609  // A being changed mortality status
1610 
1611  const BeingId id = msg.readBeingId("being id");
1612  msg.readInt16("unused");
1613  Being *const dstBeing = actorManager->findBeing(id);
1614  if (dstBeing == nullptr)
1615  {
1616  DEBUGLOGSTR("insible player?");
1617  BLOCK_END("BeingRecv::processBeingResurrect")
1618  return;
1619  }
1620 
1621  // If this is player's current target, clear it.
1622  if (dstBeing == localPlayer->getTarget())
1623  localPlayer->stopAttack(false);
1624  if (dstBeing == localPlayer &&
1625  deathNotice != nullptr)
1626  {
1627  deathNotice->scheduleDelete();
1628  deathNotice = nullptr;
1629  }
1630 
1631  dstBeing->setAction(BeingAction::STAND, 0);
1632  BLOCK_END("BeingRecv::processBeingResurrect")
1633 }
1634 
1636 {
1637  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo")
1638  if (actorManager == nullptr)
1639  {
1640  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1641  return;
1642  }
1643 
1644  const BeingId beingId = msg.readBeingId("being id");
1645  const std::string name = msg.readString(24, "char name");
1646  actorManager->updateNameId(name, beingId);
1647  Being *const dstBeing = actorManager->findBeing(beingId);
1648  if (dstBeing != nullptr)
1649  {
1650  if (beingId == localPlayer->getId())
1651  {
1653  }
1654  dstBeing->setName(name);
1655  dstBeing->setPartyName(msg.readString(24, "party name"));
1656  dstBeing->setGuildName(msg.readString(24, "guild name"));
1657  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1658  dstBeing->addToCache();
1659  }
1660  else
1661  {
1662  msg.readString(24, "party name");
1663  msg.readString(24, "guild name");
1664  msg.readString(24, "guild pos");
1665  }
1666  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1667 }
1668 
1670 {
1671  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo2")
1672  if (actorManager == nullptr)
1673  {
1674  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo2")
1675  return;
1676  }
1677 
1678  const BeingId beingId = msg.readBeingId("being id");
1679  const std::string name = msg.readString(24, "char name");
1680  actorManager->updateNameId(name, beingId);
1681  Being *const dstBeing = actorManager->findBeing(beingId);
1682  if (dstBeing != nullptr)
1683  {
1684  if (beingId == localPlayer->getId())
1685  {
1687  }
1688  dstBeing->setName(name);
1689  dstBeing->setPartyName(msg.readString(24, "party name"));
1690  dstBeing->setGuildName(msg.readString(24, "guild name"));
1691  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1692  dstBeing->addToCache();
1693  }
1694  else
1695  {
1696  msg.readString(24, "party name");
1697  msg.readString(24, "guild name");
1698  msg.readString(24, "guild pos");
1699  }
1700  // +++ need use it for show player title
1701  msg.readInt32("title");
1702  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo2")
1703 }
1704 
1706 {
1707  const BeingId id = msg.readBeingId("skill unit id");
1708  if (actorManager == nullptr)
1709  return;
1710  Being *const dstBeing = actorManager->findBeing(id);
1711  if (dstBeing == nullptr)
1712  return;
1713  actorManager->destroy(dstBeing);
1714 }
1715 
1717 {
1718  uint16_t x;
1719  uint16_t y;
1720  uint8_t dir;
1721  if (msg.getVersion() < 20071106)
1722  {
1723  msg.readBeingId("npc id");
1724  msg.skip(8, "unused");
1725  msg.readInt16("class?"); // 111
1726  msg.skip(30, "unused");
1727  msg.readCoordinates(x, y, dir, "position");
1728  msg.readUInt8("sx");
1729  msg.readUInt8("sy");
1730  msg.skip(3, "unused");
1731  return;
1732  }
1733  const BeingTypeT type = static_cast<BeingTypeT>(
1734  msg.readUInt8("object type"));
1735  const BeingId id = msg.readBeingId("npc id");
1736  msg.skip(8, "unused");
1737  const uint16_t job = msg.readInt16("class?"); // 111
1738  msg.skip(30, "unused");
1739  msg.readCoordinates(x, y, dir, "position");
1740  msg.readUInt8("sx");
1741  msg.readUInt8("sy");
1742  msg.skip(3, "unused");
1743 
1744  Being *const dstBeing = createBeing2(msg, id, job, type);
1745  if (dstBeing == nullptr)
1746  return;
1747  dstBeing->setSubtype(fromInt(job, BeingTypeId), 0);
1748  dstBeing->setTileCoords(x, y);
1749  dstBeing->setDirection(dir);
1750 }
1751 
1753 {
1754  const BeingId id = msg.readBeingId("account id");
1755  const int type = msg.readInt16("type");
1756  const int value = msg.readInt32("value");
1757 
1758  if (actorManager == nullptr)
1759  return;
1760  Being *const dstBeing = actorManager->findBeing(id);
1761  if (dstBeing == nullptr)
1762  return;
1763 
1764  if (type != Sp::MANNER)
1765  {
1767  return;
1768  }
1769  dstBeing->setManner(value);
1770 }
1771 
1773 {
1774  BLOCK_START("BeingRecv::processBeingSelfEffect")
1775  if ((effectManager == nullptr) || (actorManager == nullptr))
1776  {
1777  BLOCK_END("BeingRecv::processBeingSelfEffect")
1778  return;
1779  }
1780 
1781  const BeingId id = msg.readBeingId("being id");
1782  Being *const being = actorManager->findBeing(id);
1783  if (being == nullptr)
1784  {
1785  DEBUGLOGSTR("insible player?");
1786  msg.readInt32("effect type");
1787  BLOCK_END("BeingRecv::processBeingSelfEffect")
1788  return;
1789  }
1790 
1791  const int effectType = msg.readInt32("effect type");
1793  effectManager->trigger(effectType, being, 0);
1794 
1795  BLOCK_END("BeingRecv::processBeingSelfEffect")
1796 }
1797 
1799 {
1800  if (actorManager == nullptr)
1801  return;
1802  const int len = msg.readInt16("len");
1803  if (len < 12)
1804  return;
1805  Being *const dstBeing = actorManager->findBeing(
1806  msg.readBeingId("monster id"));
1807  const int attackRange = msg.readInt32("range");
1808  if (dstBeing != nullptr)
1809  dstBeing->setAttackRange(attackRange);
1810 }
1811 
1813 {
1814  if (actorManager == nullptr)
1815  return;
1816  const int len = msg.readInt16("len");
1817  if (len < 14)
1818  return;
1819 
1820  Being *const dstBeing = actorManager->findBeing(
1821  msg.readBeingId("player id"));
1822  const int groupId = msg.readInt32("group id");
1823  uint16_t mount = 0;
1824  mount = msg.readInt16("mount");
1825  int language = -1;
1826  if (len > 14)
1827  language = msg.readInt16("language");
1828  int clanId = 0;
1829  if (len > 16)
1830  clanId = msg.readInt32("clan id");
1831  if (dstBeing != nullptr)
1832  {
1833  if (dstBeing != localPlayer)
1834  {
1835  dstBeing->setGroupId(groupId);
1836  }
1837  dstBeing->setHorse(mount);
1838  dstBeing->setLanguageId(language);
1839  if (clanId != 0)
1840  {
1841  const ClanInfo *const info = ClanDb::get(clanId);
1842  if (info == nullptr)
1843  dstBeing->setClanName(std::string());
1844  else
1845  dstBeing->setClanName(info->name);
1846  }
1847  else
1848  {
1849  dstBeing->setClanName(std::string());
1850  }
1851  if (dstBeing == localPlayer)
1853  }
1854 }
1855 
1857 {
1859 
1860  msg.readInt16("class");
1861  msg.readInt16("level");
1862  msg.readInt16("size");
1863  msg.readInt32("hp");
1864  msg.readInt16("def");
1865  msg.readInt16("race");
1866  msg.readInt16("mdef");
1867  msg.readInt16("ele");
1868 }
1869 
1871 {
1873 
1874  msg.readBeingId("being id");
1875  msg.readUInt8("type");
1876  msg.readInt32("class");
1877 }
1878 
1880 {
1881  if (actorManager == nullptr)
1882  return;
1883  Being *const dstBeing = actorManager->findBeing(
1884  msg.readBeingId("being id"));
1885  const int balls = msg.readInt16("spirits amount");
1886  if (dstBeing != nullptr)
1887  dstBeing->setSpiritBalls(balls);
1888 }
1889 
1891 {
1893 
1894  msg.readInt32("src being id");
1895  msg.readInt32("dst being id");
1896  msg.readInt32("flag");
1897 }
1898 
1900 {
1902 
1903  msg.readBeingId("being id");
1904  msg.readInt32("wait");
1905 }
1906 
1908 {
1910 
1911  msg.readBeingId("being id");
1912 }
1913 
1915 {
1916  if (actorManager == nullptr)
1917  return;
1918  Being *const dstBeing = actorManager->findBeing(
1919  msg.readBeingId("being id"));
1920  const int x = msg.readInt16("x");
1921  const int y = msg.readInt16("y");
1922  if (dstBeing == nullptr)
1923  return;
1924  if (localPlayer == dstBeing)
1925  {
1926  localPlayer->stopAttack(false);
1928  if (viewport != nullptr)
1930  }
1931 
1932  dstBeing->setAction(BeingAction::STAND, 0);
1933  dstBeing->setTileCoords(x, y);
1934 }
1935 
1937 {
1939 
1940  msg.readString(24, "map name");
1941  msg.readInt32("monster id");
1942  msg.readUInt8("start");
1943  msg.readUInt8("result");
1944 }
1945 
1947 {
1949 
1950  msg.readUInt8("which");
1951 }
1952 
1954 {
1956 
1957  msg.readUInt8("info type");
1958  msg.readInt32("x");
1959  msg.readInt32("y");
1960  msg.readInt16("min hours");
1961  msg.readInt16("min minutes");
1962  msg.readInt16("max hours");
1963  msg.readInt16("max minutes");
1964  msg.readString(24, "monster name"); // really can be used 51 byte?
1965 }
1966 
1968 {
1970 
1971  msg.readBeingId("account id");
1972  msg.readInt16("font");
1973 }
1974 
1976 {
1978 
1979  msg.readBeingId("account id");
1980  msg.readInt16("shields");
1981  msg.readInt16("unused");
1982 }
1983 
1985 {
1987 
1988  msg.readBeingId("account id");
1989  msg.readInt16("charm type");
1990  msg.readInt16("charm count");
1991 }
1992 
1994 {
1996 
1997  const int count = (msg.readInt16("len") - 45) / (21 + itemIdLen * 5);
1998  msg.readString(24, "name");
1999  msg.readInt16("job");
2000  msg.readInt16("head");
2001  msg.readInt16("accessory");
2002  msg.readInt16("accessory2");
2003  msg.readInt16("accessory3");
2004  if (msg.getVersion() >= 20101124)
2005  msg.readInt16("robe");
2006  msg.readInt16("hair color");
2007  msg.readInt16("body color");
2008  msg.readUInt8("gender");
2009  for (int f = 0; f < count; f ++)
2010  {
2011  msg.readInt16("index");
2012  msg.readItemId("item id");
2013  msg.readUInt8("item type");
2014  msg.readInt32("location");
2015  msg.readInt32("wear state");
2016  msg.readInt8("refine");
2017  for (int d = 0; d < maxCards; d ++)
2018  msg.readItemId("card");
2019  msg.readInt32("hire expire date (?)");
2020  msg.readInt16("equip type");
2021  msg.readInt16("item sprite number");
2022  msg.readUInt8("flags");
2023  }
2024 }
2025 
2027 {
2029 
2030  const int count = (msg.readInt16("len") - 47) / (21 + itemIdLen * 5);
2031  msg.readString(24, "name");
2032  msg.readInt16("job");
2033  msg.readInt16("head");
2034  msg.readInt16("accessory");
2035  msg.readInt16("accessory2");
2036  msg.readInt16("accessory3");
2037  msg.readInt16("robe");
2038  msg.readInt16("hair color");
2039  msg.readInt16("body color");
2040  msg.readInt16("body2");
2041  msg.readUInt8("gender");
2042  for (int f = 0; f < count; f ++)
2043  {
2044  msg.readInt16("index");
2045  msg.readItemId("item id");
2046  msg.readUInt8("item type");
2047  msg.readInt32("location");
2048  msg.readInt32("wear state");
2049  msg.readInt8("refine");
2050  for (int d = 0; d < maxCards; d ++)
2051  msg.readItemId("card");
2052  msg.readInt32("hire expire date (?)");
2053  msg.readInt16("equip type");
2054  msg.readInt16("item sprite number");
2055  msg.readUInt8("flags");
2056  }
2057 }
2058 
2060 {
2061  BLOCK_START("BeingRecv::processPvpSet")
2062  const BeingId id = msg.readBeingId("being id");
2063  const int rank = msg.readInt32("rank");
2064  msg.readInt32("num");
2065  if (actorManager != nullptr)
2066  {
2067  Being *const dstBeing = actorManager->findBeing(id);
2068  if (dstBeing != nullptr)
2069  dstBeing->setPvpRank(rank);
2070  }
2071  BLOCK_END("BeingRecv::processPvpSet")
2072 }
2073 
2075 {
2076  BLOCK_START("BeingRecv::processNameResponse2")
2077  if ((actorManager == nullptr) || (localPlayer == nullptr))
2078  {
2079  BLOCK_END("BeingRecv::processNameResponse2")
2080  return;
2081  }
2082 
2083  const int len = msg.readInt16("len");
2084  const BeingId beingId = msg.readBeingId("account id");
2085  const std::string str = msg.readString(len - 8, "name");
2086  actorManager->updateNameId(str, beingId);
2087  Being *const dstBeing = actorManager->findBeing(beingId);
2088  if (dstBeing != nullptr)
2089  {
2090  if (beingId == localPlayer->getId())
2091  {
2093  }
2094  else
2095  {
2096  dstBeing->setName(str);
2097  dstBeing->updateGuild();
2098  dstBeing->addToCache();
2099 
2100  if (dstBeing->getType() == ActorType::Player)
2101  dstBeing->updateColors();
2102 
2103  if (localPlayer != nullptr)
2104  {
2105  const Party *const party = localPlayer->getParty();
2106  if (party != nullptr && party->isMember(dstBeing->getId()))
2107  {
2108  PartyMember *const member = party->getMember(
2109  dstBeing->getId());
2110 
2111  if (member != nullptr)
2112  member->setName(dstBeing->getName());
2113  }
2114  localPlayer->checkNewName(dstBeing);
2115  }
2116  }
2117  }
2118  BLOCK_END("BeingRecv::processNameResponse2")
2119 }
2120 
2122  const BeingId id,
2123  const int32_t job,
2124  const BeingTypeT beingType)
2125 {
2126  if (actorManager == nullptr)
2127  return nullptr;
2128 
2130  switch (beingType)
2131  {
2132  case BeingType::PC:
2133  type = ActorType::Player;
2134  break;
2135  case BeingType::NPC:
2136  case BeingType::NPC_EVENT:
2137  type = ActorType::Npc;
2138  break;
2139  case BeingType::MONSTER:
2140  type = ActorType::Monster;
2141  break;
2142  case BeingType::MERSOL:
2143  type = ActorType::Mercenary;
2144  break;
2145  case BeingType::PET:
2146  type = ActorType::Pet;
2147  break;
2148  case BeingType::HOMUN:
2149  type = ActorType::Homunculus;
2150  break;
2151  case BeingType::SKILL:
2152  type = ActorType::SkillUnit;
2153  break;
2154  case BeingType::ELEMENTAL:
2155  type = ActorType::Elemental;
2156  break;
2157  case BeingType::ITEM:
2158  logger->log("not supported object type: %d, job: %d",
2159  CAST_S32(beingType), CAST_S32(job));
2160  break;
2161  case BeingType::CHAT:
2162  default:
2163  UNIMPLEMENTEDPACKETFIELD(CAST_S32(beingType));
2164  type = ActorType::Monster;
2165  logger->log("not supported object type: %d, job: %d",
2166  CAST_S32(beingType), CAST_S32(job));
2167  break;
2168  }
2169  if (job == 45 && beingType == BeingType::NPC_EVENT)
2170  type = ActorType::Portal;
2171 
2172  Being *const being = actorManager->createBeing(
2173  id, type, fromInt(job, BeingTypeId));
2174  if (beingType == BeingType::MERSOL)
2175  {
2176  const MercenaryInfo *const info = PlayerInfo::getMercenary();
2177  if ((info != nullptr) && info->id == id)
2179  }
2180  else if (beingType == BeingType::PET)
2181  {
2182  if (PlayerInfo::getPetBeingId() == id)
2183  PlayerInfo::setPetBeing(being);
2184  }
2185  return being;
2186 }
2187 
2189 {
2190  msg.readInt32("id?");
2191 }
2192 
2194 {
2195  if ((packets_re == true && msg.getVersion() >= 20180221) ||
2196  (packets_main == true && msg.getVersion() >= 20180307) ||
2197  (packets_zero == true && msg.getVersion() >= 20180328))
2198  {
2199  const int flag = msg.readInt16("flag");
2200  // name request errors
2201  if (flag != 3)
2202  return;
2203  }
2204  const int id = msg.readInt32("char id");
2205  if (actorManager == nullptr)
2206  {
2207  msg.readString(24, "name");
2208  return;
2209  }
2210  actorManager->addChar(id, msg.readString(24, "name"));
2211 }
2212 
2214 {
2215  const BeingId id = msg.readBeingId("graffiti id");
2216  const BeingId creatorId = msg.readBeingId("creator id");
2217  const int x = msg.readInt16("x");
2218  const int y = msg.readInt16("y");
2219  const int job = msg.readUInt8("job");
2220  msg.readUInt8("visible");
2221  msg.readUInt8("is content");
2222  const std::string text = msg.readString(80, "text");
2223 
2224  Being *const dstBeing = createBeing2(msg, id, job, BeingType::SKILL);
2225  if (dstBeing == nullptr)
2226  return;
2227 
2228  dstBeing->setAction(BeingAction::STAND, 0);
2229  dstBeing->setTileCoords(x, y);
2230  dstBeing->setShowName(true);
2231  dstBeing->setName(text);
2232  dstBeing->setCreatorId(creatorId);
2233 }
2234 
2236 {
2237  BLOCK_START("BeingRecv::processSkillDamage")
2238  if (actorManager == nullptr)
2239  {
2240  BLOCK_END("BeingRecv::processSkillDamage")
2241  return;
2242  }
2243 
2244  const int id = msg.readInt16("skill id");
2245  Being *const srcBeing = actorManager->findBeing(
2246  msg.readBeingId("src being id"));
2247  Being *const dstBeing = actorManager->findBeing(
2248  msg.readBeingId("dst being id"));
2249  msg.readInt32("tick");
2250  msg.readInt32("src speed");
2251  msg.readInt32("dst speed");
2252  int param1;
2253  if (msg.getVersion() >= 3)
2254  param1 = msg.readInt32("damage");
2255  else
2256  param1 = msg.readInt16("damage");
2257  const int level = msg.readInt16("skill level");
2258  msg.readInt16("div");
2259  msg.readUInt8("skill hit/type?");
2260  if (srcBeing != nullptr)
2261  srcBeing->handleSkill(dstBeing, param1, id, level);
2262  if (dstBeing != nullptr)
2263  dstBeing->takeDamage(srcBeing, param1, AttackType::SKILL, id, level);
2264  BLOCK_END("BeingRecv::processSkillDamage")
2265 }
2266 
2268 {
2270  // 0 position
2271  // 1 no position
2272  // 3 monster
2273  msg.readUInt8("navigate type");
2274  msg.readUInt8("transportation flag");
2275  msg.readUInt8("hide window");
2276  msg.readString(16, "map name");
2277  msg.readInt16("x");
2278  msg.readInt16("y");
2279  msg.readInt16("mob id");
2280 }
2281 
2283  Being *const being,
2284  const uint8_t type)
2285 {
2286  if (being == nullptr)
2287  return;
2288  switch (type)
2289  {
2290  case 0:
2291  being->setAction(BeingAction::STAND, 0);
2293  break;
2294 
2295  case 1:
2296  if (being->getCurrentAction() != BeingAction::DEAD)
2297  {
2298  being->setAction(BeingAction::DEAD, 0);
2299  being->recalcSpritesOrder();
2300  }
2301  break;
2302 
2303  case 2:
2304  being->setAction(BeingAction::SIT, 0);
2306  break;
2307 
2308  default:
2310  break;
2311  }
2312 }
2313 
2314 } // namespace EAthena
void processBeingFont(Net::MessageIn &msg)
Definition: beingrecv.cpp:1967
#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:1193
#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:1914
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:557
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:1502
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:1482
#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:1468
void processNavigateTo(Net::MessageIn &msg)
Definition: beingrecv.cpp:2267
BeingId getId() const
Definition: actorsprite.h:63
void setOtherTime()
Definition: being.h:717
void processBeingHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1296
void destroy(ActorSprite *const actor)
void processBossMapInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1953
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:1396
void processBeingChangeLookCards(Net::MessageIn &msg)
Definition: beingrecv.cpp:217
void processClassChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1870
void processPlayerGuilPartyInfo2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1669
void processGraffiti(Net::MessageIn &msg)
Definition: beingrecv.cpp:2213
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:1993
void processGladiatorFeelRequest(Net::MessageIn &msg)
Definition: beingrecv.cpp:1946
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: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:1798
void processComboDelay(Net::MessageIn &msg)
Definition: beingrecv.cpp:1899
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:2193
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:2074
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:546
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:1542
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:98
void returnCamera()
Definition: viewport.cpp:1110
void processAlchemistRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1376
void processBeingSoundEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1492
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:1599
void setStatusEffectOpiton0(const uint32_t option)
void processMonsterHp(Net::MessageIn &msg)
Definition: beingrecv.cpp:1321
void processSkillDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:2235
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:1386
bool info(InputEvent &event)
Definition: commands.cpp:56
void processMonsterInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1856
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:1435
LocalPlayer * localPlayer
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:349
void processBeingRemoveSpecialEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1461
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:1581
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:1907
void processSkillAutoCast(Net::MessageIn &msg)
Definition: beingrecv.cpp:1336
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:1705
void imitateDirection(const Being *const being, const unsigned char dir)
Definition: map.h:71
void processBladeStop(Net::MessageIn &msg)
Definition: beingrecv.cpp:1890
void processBeingSelfEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1772
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:1023
void processSkillEntry(Net::MessageIn &msg)
Definition: beingrecv.cpp:1513
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:2282
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:2059
void processBeingChangeDirection(Net::MessageIn &msg)
Definition: beingrecv.cpp:1406
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:1879
Window * deathNotice
Definition: sp.h:34
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1635
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1144
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:1048
static Game * instance()
Definition: game.h:81
void recalcSpritesOrder()
Definition: being.cpp:4359
void setMercenaryBeing(Being *const being)
Definition: playerinfo.cpp:523
void processRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1354
#define restrict
Definition: localconsts.h:164
std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:367
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1111
#define UNIMPLEMENTEDPACKET
Definition: logger.h:55
BeingId getPetBeingId()
Definition: playerinfo.cpp:578
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:665
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:2121
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
void processBlacksmithRanksList(Net::MessageIn &msg)
Definition: beingrecv.cpp:1366
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:1001
void processSkillCancel(Net::MessageIn &msg)
Definition: beingrecv.cpp:2188
int itemIdLen
Definition: client.cpp:129
virtual void setGroupId(const int id)
Definition: being.cpp:5587
void processBeingStatUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:1752
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:1984
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:1936
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:1812
Viewport * viewport
Definition: viewport.cpp:35
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void processBeingMilleniumShield(Net::MessageIn &msg)
Definition: beingrecv.cpp:1975
void processBeingFakeName(Net::MessageIn &msg)
Definition: beingrecv.cpp:1716
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:2026