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