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/tmwa/beingrecv.h"
24 
25 #include "actormanager.h"
26 #include "configuration.h"
27 #include "effectmanager.h"
28 #include "guild.h"
29 #include "party.h"
30 
31 #include "being/localplayer.h"
32 
34 
35 #include "input/keyboardconfig.h"
36 
39 
40 #include "net/beinghandler.h"
41 #include "net/serverfeatures.h"
42 
43 #include "net/messagein.h"
44 
45 #include "net/ea/beingrecv.h"
46 
47 #include "net/tmwa/guildmanager.h"
48 #include "net/tmwa/sprite.h"
49 
50 #include "resources/iteminfo.h"
51 
52 #include "resources/db/itemdb.h"
53 
54 #include "utils/timer.h"
55 
56 #include "debug.h"
57 
58 extern Window *deathNotice;
59 
60 namespace TmwAthena
61 {
62 
63 static void setGm(Being *const dstBeing,
64  const uint16_t gmstatus)
65 {
66  if (dstBeing != localPlayer &&
67  gmstatus == 0x80)
68  {
69  dstBeing->setGroupId(paths.getIntValue("gmDefaultLevel"));
70  }
71  else
72  {
73  dstBeing->setGroupId(gmstatus);
74  }
75 }
76 
78 {
79  BLOCK_START("BeingRecv::processBeingChangeLook")
80  if (actorManager == nullptr)
81  {
82  BLOCK_END("BeingRecv::processBeingChangeLook")
83  return;
84  }
85 
86  Being *const dstBeing = actorManager->findBeing(
87  msg.readBeingId("being id"));
88 
89  const uint8_t type = msg.readUInt8("type");
90  const int16_t id = CAST_S16(msg.readUInt8("id"));
91  const int id2 = 1;
92 
93  if ((localPlayer == nullptr) || (dstBeing == nullptr))
94  {
95  BLOCK_END("BeingRecv::processBeingChangeLook")
96  return;
97  }
98  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
99  BLOCK_END("BeingRecv::processBeingChangeLook")
100 }
101 
103 {
104  BLOCK_START("BeingRecv::processBeingChangeLook")
105  if (actorManager == nullptr)
106  {
107  BLOCK_END("BeingRecv::processBeingChangeLook")
108  return;
109  }
110 
111  Being *const dstBeing = actorManager->findBeing(
112  msg.readBeingId("being id"));
113 
114  const uint8_t type = msg.readUInt8("type");
115  int id2 = 0;
116 
117  const int16_t id = msg.readInt16("id1");
118  if (type == 2)
119  {
120  id2 = msg.readInt16("id2");
121  }
122  else
123  {
124  msg.readInt16("id2");
125  id2 = 1;
126  }
127 
128  if ((localPlayer == nullptr) || (dstBeing == nullptr))
129  {
130  BLOCK_END("BeingRecv::processBeingChangeLook")
131  return;
132  }
133  processBeingChangeLookContinue(msg, dstBeing, type, id, id2);
134  BLOCK_END("BeingRecv::processBeingChangeLook")
135 }
136 
138  Being *const dstBeing,
139  const uint8_t type,
140  const int id,
141  const int id2)
142 {
143  if (dstBeing->getType() == ActorType::Player)
144  dstBeing->setOtherTime();
145 
146  switch (type)
147  {
148  case 0: // change race
149  dstBeing->setSubtype(fromInt(id, BeingTypeId),
150  dstBeing->getLook());
151  break;
152  case 1: // eAthena LOOK_HAIR
153  {
154  const uint16_t look = CAST_U16(id / 256);
155  const int hair = id % 256;
156  dstBeing->setHairStyle(SPRITE_HAIR_COLOR, hair * -1);
157  dstBeing->setLook(look);
158  break;
159  }
160  case 2: // Weapon ID in id, Shield ID in id2
161  dstBeing->setSpriteId(SPRITE_BODY,
162  id);
163  dstBeing->setWeaponId(id);
164  dstBeing->setSpriteId(SPRITE_FLOOR,
165  id2);
167  break;
168  case 3: // Change lower headgear for eAthena, pants for us
169  dstBeing->setSpriteId(SPRITE_WEAPON,
170  id);
172  break;
173  case 4: // Change upper headgear for eAthena, hat for us
175  id);
177  break;
178  case 5: // Change middle headgear for eathena, armor for us
180  id);
182  break;
183  case 6: // eAthena LOOK_HAIR_COLOR
185  fromInt(id, ItemColor));
186  break;
187  case 7: // Clothes color
188  // ignoring it
189  break;
190  case 8: // eAthena LOOK_SHIELD
191  dstBeing->setSpriteId(SPRITE_FLOOR,
192  id);
194  break;
195  case 9: // eAthena LOOK_SHOES
196  dstBeing->setSpriteId(SPRITE_HAIR,
197  id);
199  break;
200  case 10: // LOOK_GLOVES
201  dstBeing->setSpriteId(SPRITE_SHOES,
202  id);
204  break;
205  case 11: // LOOK_CAPE
206  dstBeing->setSpriteId(SPRITE_SHIELD,
207  id);
209  break;
210  case 12:
211  dstBeing->setSpriteId(SPRITE_HEAD_TOP,
212  id);
214  break;
215  case 13:
216  dstBeing->setSpriteId(SPRITE_HEAD_MID,
217  id);
219  break;
220  case 14:
221  dstBeing->setSpriteId(SPRITE_ROBE,
222  id);
224  break;
225  case 15:
226  dstBeing->setSpriteId(SPRITE_EVOL2,
227  id);
229  break;
230  case 16:
231  dstBeing->setLook(CAST_U16(id));
232  break;
233  default:
235  break;
236  }
237 }
238 
240 {
241  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
242  if ((actorManager == nullptr) || (localPlayer == nullptr))
243  {
244  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
245  return;
246  }
247 
248  // An update about a player, potentially including movement.
249  const BeingId id = msg.readBeingId("account id");
250  const int16_t speed = msg.readInt16("speed");
251  const uint32_t opt1 = msg.readInt16("opt1");
252  const uint32_t opt2 = msg.readInt16("opt2");
253  const uint32_t option = msg.readInt16("option");
254  const int16_t job = msg.readInt16("job");
255  int disguiseId = 0;
256  if (toInt(id, int) < 110000000 && job >= 1000)
257  disguiseId = job;
258 
259  Being *dstBeing = actorManager->findBeing(id);
260  if (dstBeing == nullptr)
261  {
262  if (actorManager->isBlocked(id) == true)
263  {
264  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
265  return;
266  }
267 
268  dstBeing = Ea::BeingRecv::createBeing(id, job);
269 
270  if (dstBeing == nullptr)
271  {
272  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
273  return;
274  }
275  }
276  else if (disguiseId != 0)
277  {
278  actorManager->undelete(dstBeing);
280  }
281 
282  uint8_t dir = dstBeing->getDirectionDelayed();
283  if (dir != 0u)
284  {
285  if (dir != dstBeing->getDirection())
286  dstBeing->setDirection(dir);
287  }
288 
289  if (Party *const party = localPlayer->getParty())
290  {
291  if (party->isMember(id))
292  dstBeing->setParty(party);
293  }
294 
295  dstBeing->setWalkSpeed(speed);
296 
297  const uint8_t hairStyle = msg.readUInt8("hair style");
298  const uint16_t look = msg.readUInt8("look");
299  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
300  const uint16_t weapon = msg.readInt16("weapon");
301  const uint16_t shield = msg.readInt16("shield");
302  const uint16_t headBottom = msg.readInt16("head bottom");
303 
304  const uint16_t headTop = msg.readInt16("head top");
305  const uint16_t headMid = msg.readInt16("head mid");
306  const ItemColor hairColor = fromInt(
307  msg.readUInt8("hair color"), ItemColor);
308  msg.readUInt8("unused");
309  msg.readInt32("unused");
310 
311  const int guild = msg.readInt32("guild");
312 
313  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
314  {
315  if (guild == 0)
316  dstBeing->clearGuilds();
317  else
318  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
319  }
320 
321  msg.readInt16("emblem");
322  dstBeing->setManner(msg.readInt16("manner"));
323  const uint32_t opt3 = msg.readInt16("opt3");
324  dstBeing->setKarma(msg.readUInt8("karma"));
325  // reserving bit for future usage
326  dstBeing->setGender(Being::intToGender(
327  CAST_U8(msg.readUInt8("gender") & 3)));
328 
329  if (disguiseId == 0)
330  {
331  // Set these after the gender, as the sprites may be gender-specific
332  dstBeing->updateSprite(SPRITE_BODY,
333  weapon,
334  std::string());
335  dstBeing->setWeaponId(weapon);
336  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
337  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
338  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
339  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
340  if (hairStyle == 0)
341  {
343  0,
344  std::string());
345  }
346  else
347  {
349  hairStyle * -1,
350  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
351  }
352  dstBeing->setHairColor(hairColor);
353  }
354  localPlayer->imitateOutfit(dstBeing, -1);
355 
356  uint16_t x, y;
357  msg.readCoordinates(x, y, dir, "position");
358  dstBeing->setTileCoords(x, y);
359  dstBeing->setDirection(dir);
360 
361  localPlayer->imitateDirection(dstBeing, dir);
362 
363  const uint16_t gmstatus = msg.readInt16("gm status");
364 
365  setGm(dstBeing, gmstatus);
366 
367  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
368  const int level = CAST_S32(msg.readUInt8("level"));
369  if (level != 0)
370  dstBeing->setLevel(level);
371 
372  msg.readUInt8("unused");
373 
374  dstBeing->setActionTime(tick_time);
375 
376  dstBeing->setStatusEffectOpitons(option,
377  opt1,
378  opt2,
379  opt3);
380 
381  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
382 }
383 
385 {
386  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
387  if ((actorManager == nullptr) || (localPlayer == nullptr))
388  {
389  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
390  return;
391  }
392 
393  // An update about a player, potentially including movement.
394  const BeingId id = msg.readBeingId("account id");
395  const int16_t speed = msg.readInt16("speed");
396  const uint32_t opt1 = msg.readInt16("opt1");
397  const uint32_t opt2 = msg.readInt16("opt2");
398  const uint32_t option = msg.readInt16("option");
399  const int16_t job = msg.readInt16("job");
400  int disguiseId = 0;
401  if (toInt(id, int) < 110000000 && job >= 1000)
402  disguiseId = job;
403 
404  Being *dstBeing = actorManager->findBeing(id);
405  if (dstBeing == nullptr)
406  {
407  if (actorManager->isBlocked(id) == true)
408  {
409  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
410  return;
411  }
412 
413  dstBeing = Ea::BeingRecv::createBeing(id, job);
414 
415  if (dstBeing == nullptr)
416  {
417  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
418  return;
419  }
420  }
421  else if (disguiseId != 0)
422  {
423  actorManager->undelete(dstBeing);
425  }
426 
427  uint8_t dir = dstBeing->getDirectionDelayed();
428  if (dir != 0u)
429  {
430  if (dir != dstBeing->getDirection())
431  dstBeing->setDirection(dir);
432  }
433 
434  if (Party *const party = localPlayer->getParty())
435  {
436  if (party->isMember(id))
437  dstBeing->setParty(party);
438  }
439 
440  dstBeing->setWalkSpeed(speed);
441 
442  const uint8_t hairStyle = msg.readUInt8("hair style");
443  const uint16_t look = msg.readUInt8("look");
444  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
445  const uint16_t weapon = msg.readInt16("weapon");
446  const uint16_t shield = msg.readInt16("shield");
447  const uint16_t headBottom = msg.readInt16("head bottom");
448  const uint16_t headTop = msg.readInt16("head top");
449  const uint16_t headMid = msg.readInt16("head mid");
450  const ItemColor hairColor = fromInt(
451  msg.readUInt8("hair color"), ItemColor);
452  msg.readUInt8("unused");
453  msg.readInt32("unused");
454 
455  const int guild = msg.readInt32("guild");
456 
457  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
458  {
459  if (guild == 0)
460  dstBeing->clearGuilds();
461  else
462  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
463  }
464 
465  msg.readInt16("emblem");
466  dstBeing->setManner(msg.readInt16("manner"));
467  const uint32_t opt3 = msg.readInt16("opt3");
468  dstBeing->setKarma(msg.readUInt8("karma"));
469  // reserving bit for future usage
470  dstBeing->setGender(Being::intToGender(
471  CAST_U8(msg.readUInt8("gender") & 3)));
472 
473  if (disguiseId == 0)
474  {
475  // Set these after the gender, as the sprites may be gender-specific
476  dstBeing->updateSprite(SPRITE_BODY,
477  weapon,
478  std::string());
479  dstBeing->setWeaponId(weapon);
480  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
481  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
482  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
483  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
484  if (hairStyle == 0)
485  {
487  0,
488  std::string());
489  }
490  else
491  {
493  hairStyle * -1,
494  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
495  }
496  dstBeing->setHairColor(hairColor);
497  }
498  localPlayer->imitateOutfit(dstBeing, -1);
499 
500  uint16_t x, y;
501  msg.readCoordinates(x, y, dir, "position");
502  dstBeing->setTileCoords(x, y);
503  dstBeing->setDirection(dir);
504 
505  localPlayer->imitateDirection(dstBeing, dir);
506 
507  const uint16_t gmstatus = msg.readInt16("gm status");
508 
509  setGm(dstBeing, gmstatus);
510 
511  applyPlayerAction(msg, dstBeing, msg.readUInt8("action type"));
512  const int level = CAST_S32(msg.readUInt8("level"));
513  if (level != 0)
514  dstBeing->setLevel(level);
515 
516  dstBeing->setActionTime(tick_time);
517  dstBeing->setStatusEffectOpitons(option,
518  opt1,
519  opt2,
520  opt3);
521 
522  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
523 }
524 
526 {
527  BLOCK_START("BeingRecv::processPlayerMoveUpdate")
528  if ((actorManager == nullptr) || (localPlayer == nullptr))
529  {
530  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
531  return;
532  }
533 
534  // An update about a player, potentially including movement.
535  const BeingId id = msg.readBeingId("account id");
536  const int16_t speed = msg.readInt16("speed");
537  const uint32_t opt1 = msg.readInt16("opt1");
538  const uint32_t opt2 = msg.readInt16("opt2");
539  const uint32_t option = msg.readInt16("option");
540  const int16_t job = msg.readInt16("job");
541  int disguiseId = 0;
542  if (toInt(id, int) < 110000000 && job >= 1000)
543  disguiseId = job;
544 
545  Being *dstBeing = actorManager->findBeing(id);
546  if (dstBeing == nullptr)
547  {
548  if (actorManager->isBlocked(id) == true)
549  {
550  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
551  return;
552  }
553 
554  dstBeing = Ea::BeingRecv::createBeing(id, job);
555 
556  if (dstBeing == nullptr)
557  {
558  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
559  return;
560  }
561  }
562  else if (disguiseId != 0)
563  {
564  actorManager->undelete(dstBeing);
566  }
567 
568  const uint8_t dir = dstBeing->getDirectionDelayed();
569  if (dir != 0u)
570  {
571  if (dir != dstBeing->getDirection())
572  dstBeing->setDirection(dir);
573  }
574 
575  if (Party *const party = localPlayer->getParty())
576  {
577  if (party->isMember(id))
578  dstBeing->setParty(party);
579  }
580 
581  dstBeing->setWalkSpeed(speed);
582 
583  const uint8_t hairStyle = msg.readUInt8("hair style");
584  const uint16_t look = msg.readUInt8("look");
585  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
586  const uint16_t weapon = msg.readInt16("weapon");
587  const uint16_t shield = msg.readInt16("shield");
588  const uint16_t headBottom = msg.readInt16("head bottom");
589 
590  msg.readInt32("tick");
591 
592  const uint16_t headTop = msg.readInt16("head top");
593  const uint16_t headMid = msg.readInt16("head mid");
594  const ItemColor hairColor = fromInt(
595  msg.readUInt8("hair color"), ItemColor);
596  msg.readUInt8("unused");
597  msg.readInt32("unused");
598 
599  const int guild = msg.readInt32("guild");
600 
601  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
602  {
603  if (guild == 0)
604  dstBeing->clearGuilds();
605  else
606  dstBeing->setGuild(Guild::getGuild(CAST_S16(guild)));
607  }
608 
609  msg.readInt16("emblem");
610  dstBeing->setManner(msg.readInt16("manner"));
611  const uint32_t opt3 = msg.readInt16("opt3");
612  dstBeing->setKarma(msg.readUInt8("karma"));
613  // reserving bit for future usage
614  dstBeing->setGender(Being::intToGender(
615  CAST_U8(msg.readUInt8("gender") & 3)));
616 
617  if (disguiseId == 0)
618  {
619  // Set these after the gender, as the sprites may be gender-specific
620  dstBeing->updateSprite(SPRITE_BODY,
621  weapon,
622  std::string());
623  dstBeing->setWeaponId(weapon);
624  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
625  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
626  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
627  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
628  if (hairStyle == 0)
629  {
631  0,
632  std::string());
633  }
634  else
635  {
637  hairStyle * -1,
638  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
639  }
640  dstBeing->setHairColor(hairColor);
641  }
642  localPlayer->imitateOutfit(dstBeing, -1);
643 
644  uint16_t srcX, srcY, dstX, dstY;
645  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "moving path");
646 
647  localPlayer->followMoveTo(dstBeing, srcX, srcY, dstX, dstY);
648 
649  dstBeing->setTileCoords(srcX, srcY);
650  dstBeing->setDestination(dstX, dstY);
651 
652  // because server don't send direction in move packet,
653  // we fixing it
654 
655  if (srcX != dstX || srcY != dstY)
656  {
657  const int d = dstBeing->calcDirection(dstX, dstY);
658 
659  if ((d != 0) && dstBeing->getDirection() != d)
660  dstBeing->setDirectionDelayed(CAST_U8(d));
661  }
662 
665  if (localPlayer->getDirection() != dstBeing->getDirection())
666  {
667  localPlayer->imitateDirection(dstBeing,
668  dstBeing->getDirection());
669  }
670 
671  const uint16_t gmstatus = msg.readInt16("gm status");
672 
673  setGm(dstBeing, gmstatus);
674 
675  msg.readUInt8("unused");
676 
677  const int level = CAST_S32(msg.readUInt8("level"));
678  if (level != 0)
679  dstBeing->setLevel(level);
680 
681  msg.readUInt8("unused");
682 
683  if (dstBeing->getType() != ActorType::Player)
684  dstBeing->setActionTime(tick_time);
685 
686  dstBeing->setStatusEffectOpitons(option,
687  opt1,
688  opt2,
689  opt3);
690 
691  if (dstBeing->getType() == ActorType::Player)
692  dstBeing->setMoveTime();
693  BLOCK_END("BeingRecv::processPlayerMoveUpdate")
694 }
695 
697 {
698  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
699  if (actorManager == nullptr)
700  {
701  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
702  return;
703  }
704 
705  BeingId spawnId;
706 
707  // Information about a being in range
708  const BeingId id = msg.readBeingId("being id");
709  if (id == Ea::BeingRecv::mSpawnId)
710  spawnId = Ea::BeingRecv::mSpawnId;
711  else
712  spawnId = BeingId_zero;
714  int16_t speed = msg.readInt16("speed");
715  const uint32_t opt1 = msg.readInt16("opt1");
716  const uint32_t opt2 = msg.readInt16("opt2");
717  const uint32_t option = msg.readInt16("option");
718  const int16_t job = msg.readInt16("class");
719  int disguiseId = 0;
720  if (id == localPlayer->getId() && job >= 1000)
721  disguiseId = job;
722 
723  Being *dstBeing = actorManager->findBeing(id);
724 
725  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
726  && !dstBeing->isAlive())
727  {
728  actorManager->destroy(dstBeing);
729  actorManager->erase(dstBeing);
730  dstBeing = nullptr;
731  }
732 
733  if (dstBeing == nullptr)
734  {
735  // Being with id >= 110000000 and job 0 are better
736  // known as ghosts, so don't create those.
737  if (job == 0 && toInt(id, int) >= 110000000)
738  {
739  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
740  return;
741  }
742 
743  if (actorManager->isBlocked(id) == true)
744  {
745  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
746  return;
747  }
748 
749  dstBeing = Ea::BeingRecv::createBeing(id, job);
750 
751  if (dstBeing == nullptr)
752  {
753  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
754  return;
755  }
756  }
757  else
758  {
759  if (dstBeing->getType() == ActorType::Npc)
760  {
761  actorManager->undelete(dstBeing);
763  }
764  }
765 
766  if (dstBeing->getType() == ActorType::Player)
767  dstBeing->setMoveTime();
768 
769  if (spawnId != BeingId_zero)
770  {
771  dstBeing->setAction(BeingAction::SPAWN, 0);
772  }
773  else
774  {
775  dstBeing->clearPath();
776  dstBeing->setActionTime(tick_time);
777  dstBeing->setAction(BeingAction::STAND, 0);
778  }
779 
780  // Prevent division by 0 when calculating frame
781  if (speed == 0)
782  speed = 150;
783 
784  const uint8_t hairStyle = msg.readUInt8("hair style");
785  const uint16_t look = msg.readUInt8("look");
786  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
787  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
788  localPlayer->checkNewName(dstBeing);
789  dstBeing->setWalkSpeed(speed);
790  const uint16_t weapon = msg.readInt16("weapon");
791  const uint16_t headBottom = msg.readInt16("head bottom");
792 
793  const uint16_t shield = msg.readInt16("shield");
794  const uint16_t headTop = msg.readInt16("head top");
795  const uint16_t headMid = msg.readInt16("head mid");
796  const ItemColor hairColor = fromInt(msg.readUInt8("hair color"),
797  ItemColor);
798  msg.readUInt8("unused");
799  const uint16_t shoes = msg.readInt16("shoes / clothes color");
800 
801  uint16_t gloves;
802  if (dstBeing->getType() == ActorType::Monster)
803  {
805  {
806  const int hp = msg.readInt32("hp");
807  const int maxHP = msg.readInt32("max hp");
808  if ((hp != 0) && (maxHP != 0))
809  {
810  dstBeing->setMaxHP(maxHP);
811  const int oldHP = dstBeing->getHP();
812  if ((oldHP == 0) || oldHP > hp)
813  dstBeing->setHP(hp);
814  }
815  }
816  else
817  {
818  msg.readInt32("unused");
819  msg.readInt32("unused");
820  }
821  gloves = 0;
822  }
823  else
824  {
825  gloves = msg.readInt16("gloves / head dir");
826  msg.readInt32("guild");
827  msg.readInt16("guild emblem");
828  }
829 
830  dstBeing->setManner(msg.readInt16("manner"));
831  const uint32_t opt3 = msg.readInt16("opt3");
833  && dstBeing->getType() == ActorType::Monster)
834  {
835  const int attackRange = CAST_S32(
836  msg.readUInt8("attack range (was karma)"));
837  dstBeing->setAttackRange(attackRange);
838  }
839  else
840  {
841  dstBeing->setKarma(msg.readUInt8("karma"));
842  }
843  uint8_t gender = msg.readUInt8("gender");
844 
845  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
846  {
847  // reserving bits for future usage
848  gender &= 3;
849  dstBeing->setGender(Being::intToGender(gender));
850  // Set these after the gender, as the sprites may be gender-specific
851  if (hairStyle == 0)
852  {
853  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
854  }
855  else
856  {
858  hairStyle * -1,
859  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
860  }
861  dstBeing->setHairColor(hairColor);
862  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
863  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
864  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
865  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
866  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
867  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
868  dstBeing->setWeaponId(weapon);
869  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
870  }
871  else if (dstBeing->getType() == ActorType::Npc
873  {
874  setServerGender(dstBeing, gender);
875  }
876 
877  uint8_t dir;
878  uint16_t x, y;
879  msg.readCoordinates(x, y, dir, "position");
880  dstBeing->setTileCoords(x, y);
881 
882  if (job == 45 && (socialWindow != nullptr) && (outfitWindow != nullptr))
883  {
884  const int num = socialWindow->getPortalIndex(x, y);
885  if (num >= 0)
886  {
888  OutfitWindow::keyName(num)));
889  }
890  else
891  {
892  dstBeing->setName("");
893  }
894  }
895 
896  dstBeing->setDirection(dir);
897 
898  msg.readUInt8("unknown");
899  msg.readUInt8("unknown");
900  msg.readUInt8("unknown");
901  msg.readUInt8("unknown");
902  msg.readUInt8("unknown");
903 
904  dstBeing->setStatusEffectOpitons(option,
905  opt1,
906  opt2,
907  opt3);
908  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
909 }
910 
912 {
913  BLOCK_START("BeingRecv::processBeingVisibleOrMove")
914  if (actorManager == nullptr)
915  {
916  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
917  return;
918  }
919 
920  BeingId spawnId;
921 
922  // Information about a being in range
923  const BeingId id = msg.readBeingId("being id");
924  if (id == Ea::BeingRecv::mSpawnId)
925  spawnId = Ea::BeingRecv::mSpawnId;
926  else
927  spawnId = BeingId_zero;
929  int16_t speed = msg.readInt16("speed");
930  const uint32_t opt1 = msg.readInt16("opt1");
931  const uint32_t opt2 = msg.readInt16("opt2");
932  const uint32_t option = msg.readInt16("option");
933  const int16_t job = msg.readInt16("class");
934  int disguiseId = 0;
935  if (id == localPlayer->getId() && job >= 1000)
936  disguiseId = job;
937 
938  Being *dstBeing = actorManager->findBeing(id);
939 
940  if ((dstBeing != nullptr) && dstBeing->getType() == ActorType::Monster
941  && !dstBeing->isAlive())
942  {
943  actorManager->destroy(dstBeing);
944  actorManager->erase(dstBeing);
945  dstBeing = nullptr;
946  }
947 
948  if (dstBeing == nullptr)
949  {
950  // Being with id >= 110000000 and job 0 are better
951  // known as ghosts, so don't create those.
952  if (job == 0 && toInt(id, int) >= 110000000)
953  {
954  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
955  return;
956  }
957 
958  if (actorManager->isBlocked(id) == true)
959  {
960  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
961  return;
962  }
963 
964  dstBeing = Ea::BeingRecv::createBeing(id, job);
965 
966  if (dstBeing == nullptr)
967  {
968  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
969  return;
970  }
971  }
972  else
973  {
974  if (dstBeing->getType() == ActorType::Npc)
975  {
976  actorManager->undelete(dstBeing);
978  }
979  }
980 
981  if (dstBeing->getType() == ActorType::Player)
982  dstBeing->setMoveTime();
983 
984  if (spawnId != BeingId_zero)
985  dstBeing->setAction(BeingAction::SPAWN, 0);
986 
987  // Prevent division by 0 when calculating frame
988  if (speed == 0)
989  speed = 150;
990 
991  const uint8_t hairStyle = msg.readUInt8("hair style");
992  const uint16_t look = msg.readUInt8("look");
993  dstBeing->setSubtype(fromInt(job, BeingTypeId), look);
994  if (dstBeing->getType() == ActorType::Monster && (localPlayer != nullptr))
995  localPlayer->checkNewName(dstBeing);
996  dstBeing->setWalkSpeed(speed);
997  const uint16_t weapon = msg.readInt16("weapon");
998  const uint16_t headBottom = msg.readInt16("head bottom");
999 
1000  msg.readInt32("tick");
1001 
1002  const uint16_t shield = msg.readInt16("shield");
1003  const uint16_t headTop = msg.readInt16("head top");
1004  const uint16_t headMid = msg.readInt16("head mid");
1005  const ItemColor hairColor = fromInt(
1006  msg.readUInt8("hair color"), ItemColor);
1007  msg.readUInt8("unused");
1008  const uint16_t shoes = msg.readInt16("shoes / clothes color");
1009 
1010  uint16_t gloves;
1011  if (dstBeing->getType() == ActorType::Monster)
1012  {
1014  {
1015  const int hp = msg.readInt32("hp");
1016  const int maxHP = msg.readInt32("max hp");
1017  if ((hp != 0) && (maxHP != 0))
1018  {
1019  dstBeing->setMaxHP(maxHP);
1020  const int oldHP = dstBeing->getHP();
1021  if ((oldHP == 0) || oldHP > hp)
1022  dstBeing->setHP(hp);
1023  }
1024  }
1025  else
1026  {
1027  msg.readInt32("unused");
1028  msg.readInt32("unused");
1029  }
1030  gloves = 0;
1031  }
1032  else
1033  {
1034  gloves = msg.readInt16("gloves / head dir");
1035  msg.readInt32("guild");
1036  msg.readInt16("guild emblem");
1037  }
1038 
1039  dstBeing->setManner(msg.readInt16("manner"));
1040  const uint32_t opt3 = msg.readInt16("opt3");
1042  && dstBeing->getType() == ActorType::Monster)
1043  {
1044  const int attackRange = CAST_S32(
1045  msg.readUInt8("attack range (was karma)"));
1046  dstBeing->setAttackRange(attackRange);
1047  }
1048  else
1049  {
1050  dstBeing->setKarma(msg.readUInt8("karma"));
1051  }
1052  uint8_t gender = msg.readUInt8("gender");
1053 
1054  if ((disguiseId == 0) && dstBeing->getType() == ActorType::Player)
1055  {
1056  // reserving bits for future usage
1057  gender &= 3;
1058  dstBeing->setGender(Being::intToGender(gender));
1059  // Set these after the gender, as the sprites may be gender-specific
1060  if (hairStyle == 0)
1061  {
1062  dstBeing->updateSprite(SPRITE_HAIR_COLOR, 0, std::string());
1063  }
1064  else
1065  {
1066  dstBeing->updateSprite(SPRITE_HAIR_COLOR,
1067  hairStyle * -1,
1068  ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
1069  }
1070  dstBeing->setHairColor(hairColor);
1071  dstBeing->updateSprite(SPRITE_WEAPON, headBottom, std::string());
1072  dstBeing->updateSprite(SPRITE_HEAD_BOTTOM, headMid, std::string());
1073  dstBeing->updateSprite(SPRITE_CLOTHES_COLOR, headTop, std::string());
1074  dstBeing->updateSprite(SPRITE_HAIR, shoes, std::string());
1075  dstBeing->updateSprite(SPRITE_SHOES, gloves, std::string());
1076  dstBeing->updateSprite(SPRITE_BODY, weapon, std::string());
1077  dstBeing->setWeaponId(weapon);
1078  dstBeing->updateSprite(SPRITE_FLOOR, shield, std::string());
1079  }
1080  else if (dstBeing->getType() == ActorType::Npc
1082  {
1083  setServerGender(dstBeing, gender);
1084  }
1085 
1086  uint16_t srcX, srcY, dstX, dstY;
1087  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1088  if (disguiseId == 0)
1089  {
1090  dstBeing->setAction(BeingAction::STAND, 0);
1091  dstBeing->setTileCoords(srcX, srcY);
1092  if (serverFeatures->haveMove3())
1093  dstBeing->setCachedDestination(dstX, dstY);
1094  else
1095  dstBeing->setDestination(dstX, dstY);
1096  }
1097 
1098  msg.readUInt8("unknown");
1099  msg.readUInt8("unknown");
1100  msg.readUInt8("unknown");
1101  msg.readUInt8("unknown");
1102  msg.readUInt8("unknown");
1103 
1104  dstBeing->setStatusEffectOpitons(option,
1105  opt1,
1106  opt2,
1107  opt3);
1108  BLOCK_END("BeingRecv::processBeingVisibleOrMove")
1109 }
1110 
1112 {
1113  BLOCK_START("BeingRecv::processBeingSpawn")
1114  // skipping this packet
1115  Ea::BeingRecv::mSpawnId = msg.readBeingId("being id");
1116  msg.readInt16("speed");
1117  msg.readInt16("opt1");
1118  msg.readInt16("opt2");
1119  msg.readInt16("option");
1120  msg.readInt16("disguise");
1121  msg.skip(25, "unused");
1122  BLOCK_END("BeingRecv::processBeingSpawn")
1123 }
1124 
1126 {
1127  msg.readInt32("src id");
1128  msg.readInt32("dst id");
1129  msg.readInt16("dst x");
1130  msg.readInt16("dst y");
1131  msg.readInt16("skill num");
1132  msg.readInt32("skill get p1");
1133  msg.readInt32("cast time");
1134 }
1135 
1137 {
1138  BLOCK_START("BeingRecv::processBeingStatusChange")
1139  if (actorManager == nullptr)
1140  {
1141  BLOCK_END("BeingRecv::processBeingStatusChange")
1142  return;
1143  }
1144 
1145  // Status change
1146  const uint16_t status = msg.readInt16("status");
1147  const BeingId id = msg.readBeingId("being id");
1148  const Enable flag = fromBool(
1149  msg.readUInt8("flag: 0: stop, 1: start"), Enable);
1150 
1151  Being *const dstBeing = actorManager->findBeing(id);
1152  if (dstBeing != nullptr)
1153  {
1154  // dont know on legacy servers is effect really started
1155  // or not. Because this always sending IsStart_true
1156  dstBeing->setStatusEffect(status, flag, IsStart_true);
1157  }
1158  BLOCK_END("BeingRecv::processBeingStatusChange")
1159 }
1160 
1162 {
1163  BLOCK_START("BeingRecv::processBeingMove2")
1164  if (actorManager == nullptr)
1165  {
1166  BLOCK_END("BeingRecv::processBeingMove2")
1167  return;
1168  }
1169 
1170  /*
1171  * A simplified movement packet, used by the
1172  * later versions of eAthena for both mobs and
1173  * players
1174  */
1175  Being *const dstBeing = actorManager->findBeing(
1176  msg.readBeingId("being id"));
1177 
1178  /*
1179  * This packet doesn't have enough info to actually
1180  * create a new being, so if the being isn't found,
1181  * we'll just pretend the packet didn't happen
1182  */
1183 
1184  if (dstBeing == nullptr)
1185  {
1186  BLOCK_END("BeingRecv::processBeingMove2")
1187  return;
1188  }
1189 
1190  uint16_t srcX, srcY, dstX, dstY;
1191  msg.readCoordinatePair(srcX, srcY, dstX, dstY, "move path");
1192  msg.readInt32("tick");
1193 
1194  dstBeing->setAction(BeingAction::STAND, 0);
1195  dstBeing->setTileCoords(srcX, srcY);
1196  dstBeing->setDestination(dstX, dstY);
1197  if (dstBeing->getType() == ActorType::Player)
1198  dstBeing->setMoveTime();
1199  BLOCK_END("BeingRecv::processBeingMove2")
1200 }
1201 
1203 {
1204  BLOCK_START("BeingRecv::processBeingChangeDirection")
1205  if (actorManager == nullptr)
1206  {
1207  BLOCK_END("BeingRecv::processBeingChangeDirection")
1208  return;
1209  }
1210 
1211  Being *const dstBeing = actorManager->findBeing(
1212  msg.readBeingId("being id"));
1213 
1214  if (dstBeing == nullptr)
1215  {
1216  DEBUGLOGSTR("invisible player?");
1217  msg.readInt16("unused");
1218  msg.readUInt8("direction");
1219  BLOCK_END("BeingRecv::processBeingChangeDirection");
1220  return;
1221  }
1222 
1223  msg.readInt16("unused");
1224 
1225  const uint8_t dir = Net::MessageIn::fromServerDirection(
1226  CAST_U8(msg.readUInt8("direction") & 0x0FU));
1227  dstBeing->setDirection(dir);
1228  if (localPlayer != nullptr)
1229  localPlayer->imitateDirection(dstBeing, dir);
1230  BLOCK_END("BeingRecv::processBeingChangeDirection")
1231 }
1232 
1234 {
1235  BLOCK_START("BeingRecv::processPlayerStop")
1236  if (actorManager == nullptr)
1237  {
1238  BLOCK_END("BeingRecv::processPlayerStop")
1239  return;
1240  }
1241 
1242  // Change in players' flags
1243  const BeingId id = msg.readBeingId("account id");
1244  Being *const dstBeing = actorManager->findBeing(id);
1245  if (dstBeing == nullptr)
1246  {
1247  DEBUGLOGSTR("invisible player?");
1248  msg.readInt16("stun mode");
1249  msg.readInt16("status effect");
1250  msg.readInt16("opt?");
1251  msg.readUInt8("Unused?");
1252  return;
1253  }
1254 
1255  const uint32_t opt1 = msg.readInt16("opt1");
1256  const uint32_t opt2 = msg.readInt16("opt2");
1257  const uint32_t option = msg.readInt16("option");
1258  msg.readUInt8("Unused?");
1259 
1260  dstBeing->setStatusEffectOpitons(option,
1261  opt1,
1262  opt2);
1263  BLOCK_END("BeingRecv::processPlayerStop")
1264 }
1265 
1267 {
1268  BLOCK_START("BeingRecv::processBeingResurrect")
1269  if (actorManager == nullptr || localPlayer == nullptr)
1270  {
1271  BLOCK_END("BeingRecv::processBeingResurrect")
1272  return;
1273  }
1274 
1275  // A being changed mortality status
1276 
1277  const BeingId id = msg.readBeingId("being id");
1278  Being *const dstBeing = actorManager->findBeing(id);
1279  if (dstBeing == nullptr)
1280  {
1281  DEBUGLOGSTR("insible player?");
1282  msg.readInt16("flag?");
1283  BLOCK_END("BeingRecv::processBeingResurrect")
1284  return;
1285  }
1286 
1287  // If this is player's current target, clear it.
1288  if (dstBeing == localPlayer->getTarget())
1289  localPlayer->stopAttack(false);
1290  if (dstBeing == localPlayer &&
1291  deathNotice != nullptr)
1292  {
1293  deathNotice->scheduleDelete();
1294  deathNotice = nullptr;
1295  }
1296 
1297  if (msg.readInt16("flag?") == 1)
1298  dstBeing->setAction(BeingAction::STAND, 0);
1299  BLOCK_END("BeingRecv::processBeingResurrect")
1300 }
1301 
1303 {
1304  BLOCK_START("BeingRecv::processPlayerGuilPartyInfo")
1305  if (actorManager == nullptr)
1306  {
1307  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1308  return;
1309  }
1310 
1311  Being *const dstBeing = actorManager->findBeing(
1312  msg.readBeingId("being id"));
1313 
1314  if (dstBeing != nullptr)
1315  {
1316  dstBeing->setPartyName(msg.readString(24, "party name"));
1317  if ((guildManager == nullptr) || !GuildManager::getEnableGuildBot())
1318  {
1319  dstBeing->setGuildName(msg.readString(24, "guild name"));
1320  dstBeing->setGuildPos(msg.readString(24, "guild pos"));
1321  }
1322  else
1323  {
1324  msg.readString(24, "guild name");
1325  msg.readString(24, "guild pos");
1326  }
1327  dstBeing->addToCache();
1328  msg.readString(24, "?");
1329  }
1330  else
1331  {
1332  msg.readString(24, "party name");
1333  msg.readString(24, "guild name");
1334  msg.readString(24, "guild pos");
1335  msg.readString(24, "?");
1336  }
1337  BLOCK_END("BeingRecv::processPlayerGuilPartyInfo")
1338 }
1339 
1341 {
1342  BLOCK_START("BeingRecv::processBeingSelfEffect")
1343  if ((effectManager == nullptr) || (actorManager == nullptr))
1344  {
1345  BLOCK_END("BeingRecv::processBeingSelfEffect")
1346  return;
1347  }
1348 
1349  const BeingId id = msg.readBeingId("being id");
1350  Being *const being = actorManager->findBeing(id);
1351  if (being == nullptr)
1352  {
1353  DEBUGLOGSTR("insible player?");
1354  msg.readInt32("effect type");
1355  BLOCK_END("BeingRecv::processBeingSelfEffect")
1356  return;
1357  }
1358 
1359  const int effectType = msg.readInt32("effect type");
1360 
1362  effectManager->trigger(effectType, being, 0);
1363 
1364  // +++ need dehard code effectType == 3
1365  if (effectType == 3 && being->getType() == ActorType::Player
1366  && (socialWindow != nullptr))
1367  { // reset received damage
1368  socialWindow->resetDamage(being->getName());
1369  }
1370  BLOCK_END("BeingRecv::processBeingSelfEffect")
1371 }
1372 
1374 {
1375  msg.readInt32("skill id");
1376 }
1377 
1379 {
1380  BLOCK_START("BeingRecv::processIpResponse")
1381  if (actorManager == nullptr)
1382  {
1383  BLOCK_END("BeingRecv::processIpResponse")
1384  return;
1385  }
1386 
1387  Being *const dstBeing = actorManager->findBeing(
1388  msg.readBeingId("being id"));
1389  if (dstBeing != nullptr)
1390  {
1391  const std::string ip = ipToString(msg.readInt32("ip address"));
1392  dstBeing->setIp(ip);
1393  }
1394  else
1395  {
1396  msg.readInt32("ip address");
1397  DEBUGLOGSTR("invisible player?");
1398  }
1399 
1400  BLOCK_END("BeingRecv::processIpResponse")
1401 }
1402 
1404 {
1405  BLOCK_START("BeingRecv::processPvpSet")
1406  const BeingId id = msg.readBeingId("being id");
1407  const int rank = msg.readInt32("rank");
1408  int teamId = 0;
1409  teamId = msg.readInt32("team");
1410  if (actorManager != nullptr)
1411  {
1412  Being *const dstBeing = actorManager->findBeing(id);
1413  if (dstBeing != nullptr)
1414  {
1415  dstBeing->setPvpRank(rank);
1416  dstBeing->setTeamId(CAST_U16(teamId));
1417  dstBeing->addToCache();
1418  }
1419  }
1420  BLOCK_END("BeingRecv::processPvpSet")
1421 }
1422 
1424  Being *const being,
1425  const uint8_t type)
1426 {
1427  if (being == nullptr)
1428  return;
1429  switch (type)
1430  {
1431  case 0:
1432  being->setAction(BeingAction::STAND, 0);
1434  break;
1435 
1436  case 1:
1437  if (being->getCurrentAction() != BeingAction::DEAD)
1438  {
1439  being->setAction(BeingAction::DEAD, 0);
1440  being->recalcSpritesOrder();
1441  }
1442  break;
1443 
1444  case 2:
1445  being->setAction(BeingAction::SIT, 0);
1447  break;
1448 
1449  default:
1451  break;
1452  }
1453 }
1454 
1456 {
1457  BLOCK_START("BeingRecv::processSkillDamage")
1458  if (actorManager == nullptr)
1459  {
1460  BLOCK_END("BeingRecv::processSkillDamage")
1461  return;
1462  }
1463 
1464  const int id = msg.readInt16("skill id");
1465  Being *const srcBeing = actorManager->findBeing(
1466  msg.readBeingId("src being id"));
1467  Being *const dstBeing = actorManager->findBeing(
1468  msg.readBeingId("dst being id"));
1469  msg.readInt32("tick");
1470  msg.readInt32("src speed");
1471  msg.readInt32("dst speed");
1472  const int param1 = msg.readInt32("damage");
1473  const int level = msg.readInt16("skill level");
1474  msg.readInt16("div");
1475  msg.readUInt8("skill hit/type?");
1476  if (srcBeing != nullptr)
1477  srcBeing->handleSkill(dstBeing, param1, id, level);
1478  if (dstBeing != nullptr)
1479  dstBeing->takeDamage(srcBeing, param1, AttackType::SKILL, id, level);
1480  BLOCK_END("BeingRecv::processSkillDamage")
1481 }
1482 
1484  const uint8_t gender)
1485 {
1486  if (being == nullptr)
1487  return;
1488  switch (gender)
1489  {
1490  case 2:
1491  being->setGender(Gender::FEMALE);
1492  break;
1493  case 3:
1494  being->setGender(Gender::MALE);
1495  break;
1496  case 4:
1497  being->setGender(Gender::HIDDEN);
1498  break;
1499  default:
1501  break;
1502  }
1503 }
1504 
1505 } // namespace TmwAthena
static bool enabled
unsigned char readUInt8(const char *const str)
Definition: messagein.cpp:103
uint16_t getLook() const
Definition: being.h:921
const ItemInfo & get(const int id)
Definition: itemdb.cpp:792
#define CAST_U8
Definition: cast.h:26
void setAttackRange(const int range)
Definition: being.h:842
Being * createBeing(const BeingId id, const int job)
Definition: beingrecv.cpp:507
BeingId mSpawnId
Definition: beingrecv.cpp:58
Definition: party.h:61
volatile int tick_time
Definition: timer.cpp:52
BeingId readBeingId(const char *const str)
Definition: messagein.cpp:223
void processSkillDamage(Net::MessageIn &msg)
Definition: beingrecv.cpp:1455
void processSkillCastCancel(Net::MessageIn &msg)
Definition: beingrecv.cpp:1373
void setDestination(const int dstX, const int dstY)
Definition: being.cpp:539
OutfitWindow * outfitWindow
void setTileCoords(const int x, const int y)
Definition: being.cpp:5010
#define fromInt(val, name)
Definition: intdefines.h:45
void setGuildName(const std::string &name)
Definition: being.cpp:1195
void processBeingChangeLookContinue(const Net::MessageIn &msg, Being *const dstBeing, const uint8_t type, const int id, const int id2)
Definition: beingrecv.cpp:137
BeingId getId() const
Definition: actorsprite.h:63
void processPlayerGuilPartyInfo(Net::MessageIn &msg)
Definition: beingrecv.cpp:1302
void setOtherTime()
Definition: being.h:717
void destroy(ActorSprite *const actor)
void setCachedDestination(const int dstX, const int dstY)
Definition: being.h:148
void setGuildPos(const std::string &pos)
Definition: being.cpp:1232
Definition: window.h:98
#define BLOCK_START(name)
Definition: perfomance.h:78
uint8_t calcDirection(const int dstX, const int dstY) const
Definition: being.cpp:1766
virtual void setGender(const GenderT gender)
Definition: being.cpp:3581
int BeingId
Definition: beingid.h:29
void processBeingResurrect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1266
virtual bool haveNpcGender() const =0
#define BLOCK_END(name)
Definition: perfomance.h:79
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
int getIntValue(const std::string &key) const
void applyPlayerAction(Net::MessageIn &msg, Being *const being, const uint8_t type)
Definition: beingrecv.cpp:1423
void processBeingChangeLook(Net::MessageIn &msg)
Definition: beingrecv.cpp:77
void setWalkSpeed(const int speed)
Definition: being.h:451
void processPlayerStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1233
uint32_t party
void readCoordinates(uint16_t &x, uint16_t &y, uint8_t &direction, const char *const str)
Definition: messagein.cpp:279
static GenderT intToGender(const uint8_t sex) A_CONST
Definition: being.h:942
void setPartyName(const std::string &name)
Definition: being.cpp:5246
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 processBeingSpawn(Net::MessageIn &msg)
Definition: beingrecv.cpp:1111
void processBeingMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:911
#define toInt(val, name)
Definition: intdefines.h:46
void setDirectionDelayed(const uint8_t direction)
Definition: being.h:501
int16_t readInt16(const char *const str)
Definition: messagein.cpp:130
static std::string getKeyShortString(const std::string &key)
void processBeingStatusChange(Net::MessageIn &msg)
Definition: beingrecv.cpp:1136
#define CAST_U16
Definition: cast.h:28
Net::ServerFeatures * serverFeatures
Definition: net.cpp:97
void setServerGender(Being *const being, const uint8_t gender)
Definition: beingrecv.cpp:1483
#define CAST_S32
Definition: cast.h:29
void setActionTime(const int actionTime)
Definition: being.h:134
void clearGuilds()
Definition: being.cpp:1288
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 setIp(const std::string &ip)
Definition: being.h:745
virtual bool haveServerHp() const =0
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY, const char *const str)
Definition: messagein.cpp:311
#define DEBUGLOGSTR(str)
Definition: logger.h:44
const bool IsStart_true
Definition: isstart.h:29
void undelete(const ActorSprite *const actor)
void setPvpRank(const unsigned int rank)
Definition: being.h:751
void processPvpSet(Net::MessageIn &msg)
Definition: beingrecv.cpp:1403
LocalPlayer * localPlayer
void processPlayerMove(Net::MessageIn &msg)
Definition: beingrecv.cpp:525
void skip(const unsigned int length, const char *const str)
Definition: messagein.cpp:349
GuildManager * guildManager
uint8_t getDirectionDelayed() const
Definition: being.h:504
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
static bool getEnableGuildBot()
Definition: guildmanager.h:55
BeingActionT getCurrentAction() const
Definition: being.h:481
void processPlayerUpdate2(Net::MessageIn &msg)
Definition: beingrecv.cpp:384
Being * findBeing(const BeingId id) const
void processSkillCasting(Net::MessageIn &msg)
Definition: beingrecv.cpp:1125
Net::BeingHandler * beingHandler
Definition: net.cpp:95
void stopAttack(const bool keepAttack)
virtual bool haveMonsterAttackRange() const =0
void processPlayerUpdate1(Net::MessageIn &msg)
Definition: beingrecv.cpp:239
ActorTypeT getType() const
Definition: being.h:115
bool isBlocked(const BeingId id) const
void imitateOutfit(const Being *const player, const int sprite) const
const char * ipToString(const uint32_t address)
Definition: stringutils.cpp:85
void resetDamage(const std::string &name)
bool Enable
Definition: enable.h:29
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
int getHP() const
Definition: being.h:758
void processBeingMove2(Net::MessageIn &msg)
Definition: beingrecv.cpp:1161
void setHairStyle(const unsigned int slot, const int id)
Definition: being.cpp:3372
void processBeingVisible(Net::MessageIn &msg)
Definition: beingrecv.cpp:696
SocialWindow * socialWindow
void setManner(const int manner)
Definition: being.h:1040
const std::string & getName() const
Definition: being.h:231
void imitateDirection(const Being *const being, const unsigned char dir)
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)
Configuration paths
void imitateAction(const Being *const being, const BeingActionT &action)
void processIpResponse(Net::MessageIn &msg)
Definition: beingrecv.cpp:1378
void applyPlayerAction(Net::MessageIn &msg, Being *const being, const uint8_t type)
Definition: beingrecv.cpp:2197
static std::string keyName(const int number)
void updateSprite(const unsigned int slot, const int id, const std::string &color)
Definition: being.cpp:2771
void setSubtype(const BeingTypeId subtype, const uint16_t look)
Definition: being.cpp:370
void setKarma(const int karma)
Definition: being.h:1034
void erase(ActorSprite *const actor)
void setParty(Party *const party)
Definition: being.cpp:1306
void setStatusEffectOpitons(const uint32_t option, const uint32_t opt1, const uint32_t opt2, const uint32_t opt3)
void followMoveTo(const Being *const being, const int x, const int y)
void setName(const std::string &name)
Definition: being.cpp:1135
Window * deathNotice
void recalcSpritesOrder()
Definition: being.cpp:4359
void setTeamId(const uint16_t teamId)
Definition: being.cpp:5187
std::string readString(int length, const char *const dstr)
Definition: messagein.cpp:367
virtual void requestNameById(const BeingId id) const =0
void processBeingSelfEffect(Net::MessageIn &msg)
Definition: beingrecv.cpp:1340
void setLook(const uint16_t look)
Definition: being.cpp:5004
#define CAST_S16
Definition: cast.h:27
const BeingId BeingId_zero
Definition: beingid.h:29
static Guild * getGuild(const int16_t id)
Definition: guild.cpp:356
void setHairColor(const unsigned int slot, const ItemColor color)
Definition: being.cpp:3389
static uint8_t fromServerDirection(const uint8_t serverDir)
Definition: messagein.cpp:249
virtual bool haveMove3() const =0
int32_t readInt32(const char *const str)
Definition: messagein.cpp:174
void processBeingChangeLook2(Net::MessageIn &msg)
Definition: beingrecv.cpp:102
virtual void setGroupId(const int id)
Definition: being.cpp:5587
void setStatusEffect(const int32_t index, const Enable active, const IsStart start)
bool trigger(const int id, Being *const being, const int rotation)
void processBeingChangeDirection(Net::MessageIn &msg)
Definition: beingrecv.cpp:1202
uint32_t guild
int BeingTypeId
Definition: beingtypeid.h:29
Definition: being.h:93
static void setGm(Being *const dstBeing, const uint16_t gmstatus)
Definition: beingrecv.cpp:63
void setWeaponId(const int id)
Definition: being.cpp:3135
EffectManager * effectManager
void setGuild(Guild *const guild)
Definition: being.cpp:1353
ActorManager * actorManager
#define UNIMPLEMENTEDPACKETFIELD(field)
Definition: logger.h:58
void setLevel(const int n)
Definition: being.h:600
Being * getTarget() const
void setMoveTime()
Definition: being.h:705
void clearPath()
Definition: being.cpp:553
void setMaxHP(const int hp)
Definition: being.cpp:4343