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