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