Mana
Loading...
Searching...
No Matches
beinghandler.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include "actorspritemanager.h"
25#include "being.h"
26#include "client.h"
27#include "effectmanager.h"
28#include "game.h"
29#include "guild.h"
30#include "localplayer.h"
31#include "log.h"
32#include "party.h"
33#include "playerrelations.h"
34
35#include "net/net.h"
36#include "net/tmwa/messagein.h"
37#include "net/tmwa/messageout.h"
39#include "net/tmwa/protocol.h"
40
41#include "resources/emotedb.h"
42#include "resources/hairdb.h"
44
45#include <cmath>
46
47namespace TmwAthena {
48
49// Number of pixels where we decide that the position doesn't need to be reset.
50static const float POS_DEST_DIFF_TOLERANCE = 48.0f;
51
81
82static ActorSprite::Type typeFromJob(short job)
83{
84 if (job <= 25 || (job >= 4001 && job <= 4049))
86 if (job >= 46 && job <= 1000)
87 return ActorSprite::NPC;
88 if (job > 1000 && job <= 2000)
90 if (job == 45)
92
94}
95
96static Being *createBeing(int id, short job)
97{
98 const auto type = typeFromJob(job);
99 if (type == ActorSprite::PORTAL)
100 return nullptr; // Skip portals
101
102 Being *being = actorSpriteManager->createBeing(id, type, job);
103
104 if (type == ActorSprite::PLAYER || type == ActorSprite::NPC)
105 {
106 MessageOut outMsg(CMSG_NAME_REQUEST);
107 outMsg.writeInt32(id);
108 }
109
110 if (type == ActorSprite::NPC)
111 {
113 playerHandler->applyQuestStatusEffects(being);
114 }
115
116 return being;
117}
118
119static void updateBeingType(Being *being, short job)
120{
121 const auto type = typeFromJob(job);
122 const bool typeChanged = being->getType() != type;
123
124 being->setType(type, job);
125
126 if (typeChanged && type == ActorSprite::PLAYER)
127 {
128 MessageOut outMsg(CMSG_NAME_REQUEST);
129 outMsg.writeInt32(being->getId());
130 }
131}
132
133static void handleMoveMessage(Map *map, Being *dstBeing,
134 Uint16 srcX, Uint16 srcY,
135 Uint16 dstX, Uint16 dstY)
136{
137 // Avoid dealing with flawed destination
138 if (map && dstBeing && srcX && srcY && dstX && dstY)
139 {
140 Vector pos = map->getTileCenter(srcX, srcY);
141 Vector dest = map->getTileCenter(dstX, dstY);
142 Vector beingPos = dstBeing->getPosition();
143
144 // Don't set the position as the movement algorithm
145 // can guess it and it would break the animation played,
146 // when we're close enough.
147 if (std::abs(beingPos.x - pos.x) > POS_DEST_DIFF_TOLERANCE
148 || std::abs(beingPos.y - pos.y) > POS_DEST_DIFF_TOLERANCE)
149 dstBeing->setPosition(pos);
150
151 dstBeing->setDestination(dest.x, dest.y);
152 }
153}
154
155static void handlePosMessage(Map *map, Being *dstBeing, Uint16 x, Uint16 y,
156 Uint8 dir = 0)
157{
158 // Avoid dealing with flawed destination
159 if (map && dstBeing && x && y)
160 {
161 Vector pos = map->getTileCenter(x, y);
162 Vector beingPos = dstBeing->getPosition();
163 // Don't set the position as the movement algorithm
164 // can guess it and it would break the animation played,
165 // when we're close enough.
166 if (std::abs(beingPos.x - pos.x) > POS_DEST_DIFF_TOLERANCE
167 || std::abs(beingPos.y - pos.y) > POS_DEST_DIFF_TOLERANCE)
168 dstBeing->setPosition(pos);
169
170 // Set also the destination to the desired position.
171 dstBeing->setDestination(pos.x, pos.y);
172
173 if (dir)
174 dstBeing->setDirection(dir);
175 }
176}
177
178static void applyStatusEffectsByOption1(Being *being,
180 uint16_t option)
181{
182 for (auto &[opt, id] : map)
183 being->setStatusEffect(id, option == opt);
184}
185
186static void applyStatusEffectsByOption(Being *being,
188 uint16_t option)
189{
190 for (auto &[opt, id] : map)
191 {
192 const bool enabled = (option & opt) != 0;
193 being->setStatusEffect(id, enabled);
194 }
195}
196
201static void applyStatusEffects(Being *being,
202 uint16_t opt0,
203 uint16_t opt1,
204 uint16_t opt2,
205 std::optional<uint16_t> opt3 = {})
206{
207 applyStatusEffectsByOption(being, StatusEffectDB::opt0ToIdMap(), opt0);
208 applyStatusEffectsByOption1(being, StatusEffectDB::opt1ToIdMap(), opt1);
209 applyStatusEffectsByOption(being, StatusEffectDB::opt2ToIdMap(), opt2);
210 if (opt3)
211 applyStatusEffectsByOption(being, StatusEffectDB::opt3ToIdMap(), *opt3);
212}
213
215{
217 return;
218
219 int id;
220 short job;
221 SEX sex;
222 float speed;
223 Uint16 headTop, headMid, headBottom;
224 Uint16 shoes, gloves;
225 Uint16 weapon, shield;
226 Uint16 gmstatus;
227 int param1;
228 uint16_t opt0;
229 uint16_t opt1;
230 uint16_t opt2;
231 uint16_t opt3;
232 int type, guild;
233 Uint16 status;
234 Being *srcBeing, *dstBeing;
235 int hairStyle, hairColor, flag;
236
237 // Prepare useful translation variables
238 Map *map = Game::instance()->getCurrentMap();
239
240 switch (msg.getId())
241 {
243 case SMSG_BEING_MOVE:
244 // Information about a being in range
245 id = msg.readInt32();
246 speed = (float)msg.readInt16();
247 opt1 = msg.readInt16();
248 opt2 = msg.readInt16();
249 opt0 = msg.readInt16();
250 job = msg.readInt16(); // class
251
252 dstBeing = actorSpriteManager->findBeing(id);
253
254 if (!dstBeing)
255 {
256 // Being with id >= 110000000 and job 0 are better
257 // known as ghosts, so don't create those.
258 if (job == 0 && id >= 110000000)
259 {
260 break;
261 }
262
263 dstBeing = createBeing(id, job);
264
265 if (!dstBeing)
266 break;
267 }
268
269 if (msg.getId() == SMSG_BEING_VISIBLE)
270 {
271 dstBeing->clearPath();
272 dstBeing->setAction(Being::STAND);
273 }
274
275 // Prevent division by 0 when calculating frame
276 if (speed == 0)
277 speed = 150.0f; // In ticks per tile * 10
278
279 dstBeing->setMoveSpeed(Vector(speed / 10, speed / 10));
280 updateBeingType(dstBeing, job);
281 hairStyle = msg.readInt16();
282 weapon = msg.readInt16();
283 headBottom = msg.readInt16();
284
285 if (msg.getId() == SMSG_BEING_MOVE)
286 {
287 msg.readInt32(); // server tick
288 }
289
290 shield = msg.readInt16();
291 headTop = msg.readInt16();
292 headMid = msg.readInt16();
293 hairColor = msg.readInt16();
294 shoes = msg.readInt16(); // clothes color - "abused" as shoes
295 gloves = msg.readInt16(); // head dir - "abused" as gloves
296 guild = msg.readInt32(); // guild
297 if (guild == 0)
298 {
299 dstBeing->clearGuilds();
300 }
301 else
302 {
303 dstBeing->addGuild(Guild::getGuild(guild));
304 }
305 msg.readInt16(); // guild emblem
306 msg.readInt16(); // manner
307 opt3 = msg.readInt16();
308 msg.readInt8(); // karma
309 sex = static_cast<SEX>(msg.readInt8());
310
311 if (dstBeing->getType() == ActorSprite::PLAYER)
312 {
313 dstBeing->setGender(sexToGender(sex));
314 // Set these after the gender, as the sprites may be gender-specific
315 dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1,
316 hairDB.getHairColor(hairColor));
317 dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
318 dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid);
319 dstBeing->setSprite(SPRITE_HAT, headTop);
320 dstBeing->setSprite(SPRITE_SHOE, shoes);
321 dstBeing->setSprite(SPRITE_GLOVES, gloves);
322 dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true);
323 dstBeing->setSprite(SPRITE_SHIELD, shield);
324 }
325
326 if (msg.getId() == SMSG_BEING_MOVE)
327 {
328 Uint16 srcX, srcY, dstX, dstY;
329 msg.readCoordinatePair(srcX, srcY, dstX, dstY);
330 handleMoveMessage(map, dstBeing, srcX, srcY, dstX, dstY);
331 }
332 else
333 {
334 Uint8 dir;
335 Uint16 x, y;
336 msg.readCoordinates(x, y, dir);
337 handlePosMessage(map, dstBeing, x, y, dir);
338 }
339
340 msg.readInt8(); // unknown
341 msg.readInt8(); // unknown
342 msg.readInt8(); // unknown / sit
343
344 applyStatusEffects(dstBeing, opt0, opt1, opt2, opt3);
345 break;
346
347 case SMSG_BEING_SPAWN:
348 /*
349 * TODO: This packet might need handling in the future.
350 */
351 // Do nothing.
352 break;
353
355 // A being should be removed or has died
356 id = msg.readInt32();
357 dstBeing = actorSpriteManager->findBeing(id);
358 if (!dstBeing)
359 break;
360
361 // If this is player's current target, clear it.
362 if (dstBeing == local_player->getTarget())
364
365 if (msg.readInt8() == 1)
366 dstBeing->setAction(Being::DEAD);
367 else
369
370 break;
371
373 // A being changed mortality status
374 id = msg.readInt32();
375 dstBeing = actorSpriteManager->findBeing(id);
376 if (!dstBeing)
377 break;
378
379 // If this is player's current target, clear it.
380 if (dstBeing == local_player->getTarget())
382
383 if (msg.readInt8() == 1)
384 dstBeing->setAction(Being::STAND);
385
386 break;
387
389 {
390 msg.readInt16(); // Skill Id
391 srcBeing = actorSpriteManager->findBeing(msg.readInt32());
392 dstBeing = actorSpriteManager->findBeing(msg.readInt32());
393 msg.readInt32(); // Server tick
394 int attackSpeed = msg.readInt32(); // src speed
395 msg.readInt32(); // dst speed
396 param1 = msg.readInt32(); // Damage
397 msg.readInt16(); // Skill level
398 msg.readInt16(); // Div
399 msg.readInt8(); // Skill hit/type (?)
400 if (attackSpeed && srcBeing && srcBeing != local_player)
401 srcBeing->setAttackSpeed(attackSpeed);
402 if (dstBeing)
403 dstBeing->takeDamage(srcBeing, param1, Being::HIT); // Perhaps a new skill attack type should be created and used?
404 if (srcBeing)
405 srcBeing->handleAttack(dstBeing, param1);
406 break;
407 }
409 srcBeing = actorSpriteManager->findBeing(msg.readInt32());
410 dstBeing = actorSpriteManager->findBeing(msg.readInt32());
411 msg.readInt32(); // server tick
412 msg.readInt32(); // src speed
413 msg.readInt32(); // dst speed
414 param1 = msg.readInt16();
415 msg.readInt16(); // param 2
416 type = msg.readInt8();
417 msg.readInt16(); // param 3
418
419 switch (type)
420 {
421 case Being::HIT: // Damage
422 case Being::CRITICAL: // Critical Damage
423 case Being::MULTI: // Critical Damage
424 case Being::REFLECT: // Reflected Damage
425 case Being::FLEE: // Lucky Dodge
426 if (dstBeing)
427 dstBeing->takeDamage(srcBeing, param1,
428 static_cast<Being::AttackType>(type));
429 if (srcBeing)
430 srcBeing->handleAttack(dstBeing, param1);
431 break;
432
433 case 0x02: // Sit
434 if (srcBeing)
435 srcBeing->setAction(Being::SIT);
436 break;
437
438 case 0x03: // Stand up
439 if (srcBeing)
440 srcBeing->setAction(Being::STAND);
441 break;
442 }
443 break;
444
446 {
447 id = (Uint32)msg.readInt32();
448 Being* being = actorSpriteManager->findBeing(id);
449 if (!being)
450 break;
451
452 int effectType = msg.readInt32();
453
454 effectManager->trigger(effectType, being);
455 break;
456 }
457
459 if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
460 {
461 break;
462 }
463
465 {
466 const int fx = EmoteDB::get(msg.readInt8() - 1).effectId;
467 effectManager->trigger(fx, dstBeing);
468 }
469
470 break;
471
473 {
474 if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
475 {
476 break;
477 }
478
479 const LOOK type = static_cast<LOOK>(msg.readInt8());
480 const int id = msg.readInt16();
481 const int id2 = msg.readInt16();
482
483 switch (type)
484 {
485 case LOOK::BASE:
486 updateBeingType(dstBeing, id);
487 break;
488 case LOOK::HAIR:
489 {
490 // const int look = id / 256;
491 const int hair = id % 256;
492 dstBeing->setSpriteID(SPRITE_HAIR, hair * -1);
493 break;
494 }
495 case LOOK::WEAPON: // Weapon ID in id, Shield ID in id2
496 dstBeing->setSprite(SPRITE_WEAPON, id, std::string(), true);
497 dstBeing->setSprite(SPRITE_SHIELD, id2);
498 break;
499 case LOOK::HEAD_BOTTOM: // Change lower headgear for eAthena, pants for us
500 dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id);
501 break;
502 case LOOK::HEAD_TOP: // Change upper headgear for eAthena, hat for us
503 dstBeing->setSprite(SPRITE_HAT, id);
504 break;
505 case LOOK::HEAD_MID: // Change middle headgear for eathena, armor for us
506 dstBeing->setSprite(SPRITE_TOPCLOTHES, id);
507 break;
508 case LOOK::HAIR_COLOR:
509 dstBeing->setSpriteColor(SPRITE_HAIR,
510 hairDB.getHairColor(id));
511 break;
513 // ignoring it
514 break;
515 case LOOK::SHIELD:
516 dstBeing->setSprite(SPRITE_SHIELD, id);
517 break;
518 case LOOK::SHOES:
519 dstBeing->setSprite(SPRITE_SHOE, id);
520 break;
521 case LOOK::GLOVES:
522 dstBeing->setSprite(SPRITE_GLOVES, id);
523 break;
524 case LOOK::CAPE:
525 dstBeing->setSprite(SPRITE_CAPE, id);
526 break;
527 case LOOK::MISC1:
528 dstBeing->setSprite(SPRITE_MISC1, id);
529 break;
530 case LOOK::MISC2:
531 dstBeing->setSprite(SPRITE_MISC2, id);
532 break;
533 default:
534 Log::info("SMSG_BEING_CHANGE_LOOKS2: unsupported type: "
535 "%d, id: %d", static_cast<int>(type), id);
536 break;
537 }
538 }
539 break;
540
542 if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
543 {
544 dstBeing->setName(msg.readString(24));
545 }
546 break;
548 if ((dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
549 {
550 dstBeing->setPartyName(msg.readString(24));
551 dstBeing->setGuildName(msg.readString(24));
552 dstBeing->setGuildPos(msg.readString(24));
553 msg.readString(24); // Discard this
554 }
555 break;
557 {
558 if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32())))
559 {
560 break;
561 }
562
563 msg.readInt16(); // unused
564 Uint8 dir = msg.readInt8();
565 if (dir)
566 dstBeing->setDirection(dir);
567 }
568 break;
569
572 case SMSG_PLAYER_MOVE:
573 // An update about a player, potentially including movement.
574 id = msg.readInt32();
575 speed = msg.readInt16();
576 opt1 = msg.readInt16();
577 opt2 = msg.readInt16();
578 opt0 = msg.readInt16();
579 job = msg.readInt16();
580
581 dstBeing = actorSpriteManager->findBeing(id);
582
583 if (!dstBeing)
584 {
585 dstBeing = createBeing(id, job);
586
587 if (!dstBeing)
588 break;
589 }
590
591 if (Party *party = local_player->getParty())
592 if (party->isMember(id))
593 dstBeing->setParty(party);
594
595 // The original speed is ticks per tile * 10
596 if (speed)
597 dstBeing->setMoveSpeed(Vector(speed / 10, speed / 10));
598 else
599 dstBeing->setMoveSpeed(Net::getPlayerHandler()->getDefaultMoveSpeed());
600
601 updateBeingType(dstBeing, job);
602 hairStyle = msg.readInt16();
603 weapon = msg.readInt16();
604 shield = msg.readInt16();
605 headBottom = msg.readInt16();
606
607 if (msg.getId() == SMSG_PLAYER_MOVE)
608 {
609 msg.readInt32(); // server tick
610 }
611
612 headTop = msg.readInt16();
613 headMid = msg.readInt16();
614 hairColor = msg.readInt16();
615 msg.readInt16(); // clothes_color
616 msg.readInt8(); // head_dir
617 msg.readInt8(); // unused2
618 msg.readInt32(); // guild
619 msg.readInt16(); // emblem
620 msg.readInt16(); // manner
621 opt3 = msg.readInt16();
622 msg.readInt8(); // karma
623 dstBeing->setGender(msg.readInt8() == 0 ? Gender::Female
624 : Gender::Male);
625 // Set these after the gender, as the sprites may be gender-specific
626 dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true);
627 dstBeing->setSprite(SPRITE_SHIELD, shield);
628 //dstBeing->setSprite(SPRITE_SHOE, shoes);
629 dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom);
630 dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid);
631 dstBeing->setSprite(SPRITE_HAT, headTop);
632 //dstBeing->setSprite(SPRITE_GLOVES, gloves);
633 //dstBeing->setSprite(SPRITE_CAPE, cape);
634 //dstBeing->setSprite(SPRITE_MISC1, misc1);
635 //dstBeing->setSprite(SPRITE_MISC2, misc2);
636 dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1,
637 hairDB.getHairColor(hairColor));
638
639 if (msg.getId() == SMSG_PLAYER_MOVE)
640 {
641 Uint16 srcX, srcY, dstX, dstY;
642 msg.readCoordinatePair(srcX, srcY, dstX, dstY);
643 handleMoveMessage(map, dstBeing, srcX, srcY, dstX, dstY);
644 }
645 else
646 {
647 Uint8 dir;
648 Uint16 x, y;
649 msg.readCoordinates(x, y, dir);
650 handlePosMessage(map, dstBeing, x, y, dir);
651 }
652
653 gmstatus = msg.readInt16();
654 if (gmstatus & 0x80)
655 dstBeing->setGM(true);
656
657 if (msg.getId() == SMSG_PLAYER_UPDATE_1)
658 {
659 switch (msg.readInt8())
660 {
661 case 1:
662 dstBeing->setAction(Being::DEAD);
663 break;
664
665 case 2:
666 dstBeing->setAction(Being::SIT);
667 break;
668 }
669 }
670 else if (msg.getId() == SMSG_PLAYER_MOVE)
671 {
672 msg.readInt8(); // five
673 }
674
675 msg.readInt8(); // Lv
676 msg.readInt8(); // unused
677
678 applyStatusEffects(dstBeing, opt0, opt1, opt2, opt3);
679 break;
680
681 case SMSG_PLAYER_STOP:
682 /*
683 * Instruction from server to stop walking at x, y.
684 *
685 * Some people like having this enabled. Others absolutely
686 * despise it. So I'm setting to so that it only affects the
687 * local player if the person has set a key "EnableSync" to "1"
688 * in their config.xml file.
689 *
690 * This packet will be honored for all other beings, regardless
691 * of the config setting.
692 */
693
694 id = msg.readInt32();
695 if (mSync || id != local_player->getId())
696 {
697 dstBeing = actorSpriteManager->findBeing(id);
698 if (dstBeing)
699 {
700 Uint16 x = msg.readInt16();
701 Uint16 y = msg.readInt16();
702 handlePosMessage(map, dstBeing, x, y);
703 }
704 }
705 break;
706
708 /*
709 * This is an *advisory* message, telling the client that
710 * it needs to move the character before attacking
711 * a target (out of range, obstruction in line of fire).
712 * We can safely ignore this...
713 */
714 break;
715
717 // Change in players' flags
718 id = msg.readInt32();
719 dstBeing = actorSpriteManager->findBeing(id);
720 if (!dstBeing)
721 break;
722
723 opt1 = msg.readInt16();
724 opt2 = msg.readInt16();
725 opt0 = msg.readInt16();
726 msg.readInt8(); // zero
727
728 applyStatusEffects(dstBeing, opt0, opt1, opt2);
729 break;
730
732 // Status change
733 status = msg.readInt16();
734 id = msg.readInt32();
735 flag = msg.readInt8(); // 0: stop, 1: start
736
737 dstBeing = actorSpriteManager->findBeing(id);
738 if (dstBeing)
739 dstBeing->setStatusEffect(status, flag);
740 break;
741 }
742}
743
744} // namespace TmwAthena
ActorSpriteManager * actorSpriteManager
Definition game.cpp:110
Being * createBeing(int id, ActorSprite::Type type, int subtype)
Create a Being and add it to the list of ActorSprites.
void destroyActor(ActorSprite *actor)
Immediately destroys the given actor.
Being * findBeing(int id) const
Returns a specific Being, by id;.
int getId() const
Definition actorsprite.h:63
const Vector & getPosition() const
Returns the pixel position of this actor.
Definition actor.h:53
Definition being.h:65
void setPosition(const Vector &pos) final
Sets the pixel position of this actor.
Definition being.cpp:187
void setStatusEffect(int id, bool active)
Definition being.cpp:596
Party * getParty() const
Definition being.h:262
AttackType
Definition being.h:91
@ REFLECT
Definition being.h:95
@ HIT
Definition being.h:92
@ FLEE
Definition being.h:96
@ MULTI
Definition being.h:94
@ CRITICAL
Definition being.h:93
void setSprite(unsigned slot, int id, const std::string &color=std::string(), bool isWeapon=false)
Sets visible equipments for this being.
Definition being.cpp:1254
void setDestination(int ex, int ey)
Creates a path for the being from current position to ex and ey.
Definition being.cpp:197
void setGuildName(const std::string &name)
Sets the name of the primary guild the being is in.
Definition being.cpp:482
void setMoveSpeed(const Vector &speed)
Sets the move speed.
Definition being.cpp:173
void setDirection(uint8_t direction)
Sets the current direction.
Definition being.cpp:782
Type getType() const final
Returns the type of the ActorSprite.
Definition being.h:122
void setSpriteColor(unsigned slot, const std::string &color=std::string())
Definition being.cpp:1301
void setName(const std::string &name)
Sets the name for the being.
Definition being.cpp:463
void setAttackSpeed(int speed)
Sets the attack speed.
Definition being.h:325
@ SIT
Definition being.h:77
@ STAND
Definition being.h:74
@ DEAD
Definition being.h:78
void setGM(bool gm)
Triggers whether or not to show the name as a GM name.
Definition being.cpp:1337
void setGuildPos(const std::string &pos)
Definition being.cpp:489
void setPartyName(const std::string &name)
Sets the name of the party the being is in.
Definition being.h:208
virtual void setAction(Action action, int attackId=1)
Sets the current action.
Definition being.cpp:624
void setType(Type type, int subtype)
Can be used to change the type of the being.
Definition being.cpp:93
void setParty(Party *party)
Definition being.cpp:549
void handleAttack(Being *victim, int damage, int attackId=1)
Handles an attack of another being by this being.
Definition being.cpp:421
void setGender(Gender gender)
Sets the gender of this being.
Definition being.cpp:1313
void addGuild(Guild *guild)
Adds a guild to the being.
Definition being.cpp:495
void takeDamage(Being *attacker, int damage, AttackType type, int attackId=1)
Puts a damage bubble above this being.
Definition being.cpp:316
void clearPath()
Removes all path nodes from this being.
Definition being.cpp:254
void setSpriteID(unsigned slot, int id)
Definition being.cpp:1295
void clearGuilds()
Removes all guilds the being is in.
Definition being.cpp:536
bool trigger(int id, Being *being, int rotation=0)
Triggers a effect with the id, at the specified being, and with the given rotation in degree: 0° = Do...
Map * getCurrentMap()
Returns the currently active map.
Definition game.h:70
static Game * instance()
Provides access to the game instance.
Definition game.h:53
static Guild * getGuild(int id)
Definition guild.cpp:183
const std::string & getHairColor(int id) const
Definition hairdb.cpp:79
Being * getTarget() const
Returns the current target of the player.
void stopAttack()
A tile map.
Definition map.h:147
Vector getTileCenter(int x, int y) const
Returns the tile center position in pixel coordinates.
Definition map.cpp:563
const uint16_t * handledMessages
Definition party.h:59
bool hasPermission(Being *being, unsigned int flags)
Tests whether the player in question is being ignored for any of the actions in the specified flags.
static const OptionsMap & opt2ToIdMap()
static const OptionsMap & opt0ToIdMap()
These map flags or indexes to their corresponding status effect ID.
static const OptionsMap & opt3ToIdMap()
std::map< uint16_t, int > OptionsMap
static const OptionsMap & opt1ToIdMap()
void handleMessage(MessageIn &msg) override
BeingHandler(bool enableSync)
Used for parsing an incoming message from eAthena.
Definition messagein.h:35
std::string readString(int length=-1)
Reads a string.
void readCoordinates(uint16_t &x, uint16_t &y, uint8_t &direction)
Reads a special 3 byte block used by eAthena, containing x and y coordinates and direction.
Definition messagein.cpp:81
uint16_t readInt16()
Reads an unsigned 16-bit integer from the message.
Definition messagein.cpp:57
uint8_t readInt8()
Reads an unsigned 8-bit integer from the message.
Definition messagein.cpp:46
void readCoordinatePair(uint16_t &srcX, uint16_t &srcY, uint16_t &dstX, uint16_t &dstY)
Reads a special 5 byte block used by eAthena, containing a source and destination coordinate pair.
uint16_t getId() const
Returns the message ID.
Definition messagein.h:42
uint32_t readInt32()
Reads an unsigned 32-bit integer from the message.
Definition messagein.cpp:69
Vector class.
Definition vector.h:33
float y
Definition vector.h:172
float x
Definition vector.h:171
HairDB hairDB
Hair styles and colors info database.
Definition client.cpp:107
EffectManager * effectManager
Definition game.cpp:114
LocalPlayer * local_player
Net::PlayerHandler * playerHandler
Definition net.cpp:56
const Emote & get(int id)
Definition emotedb.cpp:115
void info(const char *log_text,...) LOG_PRINTF_ATTR
PlayerHandler * getPlayerHandler()
Definition net.cpp:110
Warning: buffers and other variables are shared, so there can be only one connection active at a time...
@ SPRITE_GLOVES
Definition protocol.h:60
@ SPRITE_BOTTOMCLOTHES
Definition protocol.h:53
@ SPRITE_WEAPON
Definition protocol.h:61
@ SPRITE_MISC1
Definition protocol.h:55
@ SPRITE_SHOE
Definition protocol.h:52
@ SPRITE_HAT
Definition protocol.h:58
@ SPRITE_HAIR
Definition protocol.h:57
@ SPRITE_MISC2
Definition protocol.h:56
@ SPRITE_SHIELD
Definition protocol.h:62
@ SPRITE_CAPE
Definition protocol.h:59
@ SPRITE_TOPCLOTHES
Definition protocol.h:54
@ SMSG_PLAYER_STOP
Definition protocol.h:170
@ SMSG_BEING_CHANGE_DIRECTION
Definition protocol.h:186
@ SMSG_PLAYER_MOVE
Definition protocol.h:291
@ SMSG_BEING_MOVE
Definition protocol.h:162
@ SMSG_BEING_ACTION
Definition protocol.h:172
@ SMSG_BEING_RESURRECT
Definition protocol.h:276
@ SMSG_BEING_SELFEFFECT
Definition protocol.h:283
@ SMSG_BEING_NAME_RESPONSE
Definition protocol.h:180
@ SMSG_PLAYER_MOVE_TO_ATTACK
Definition protocol.h:268
@ SMSG_BEING_EMOTION
Definition protocol.h:217
@ SMSG_BEING_CHANGE_LOOKS2
Definition protocol.h:288
@ SMSG_PLAYER_UPDATE_1
Definition protocol.h:289
@ SMSG_SKILL_DAMAGE
Definition protocol.h:292
@ SMSG_BEING_SPAWN
Definition protocol.h:163
@ SMSG_PLAYER_GUILD_PARTY_INFO
Definition protocol.h:279
@ SMSG_PLAYER_UPDATE_2
Definition protocol.h:290
@ SMSG_PLAYER_STATUS_CHANGE
Definition protocol.h:267
@ CMSG_NAME_REQUEST
Definition protocol.h:179
@ SMSG_BEING_STATUS_CHANGE
Definition protocol.h:280
@ SMSG_BEING_REMOVE
Definition protocol.h:167
@ SMSG_BEING_VISIBLE
Definition protocol.h:161
Gender sexToGender(SEX sex)
Definition protocol.h:106
PlayerRelationsManager player_relations
int effectId
Definition emotedb.h:34