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