Mana
Loading...
Searching...
No Matches
being.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
22#include "being.h"
23
24#include "actorspritemanager.h"
25#include "client.h"
26#include "configuration.h"
27#include "effectmanager.h"
28#include "event.h"
29#include "game.h"
30#include "guild.h"
31#include "localplayer.h"
32#include "log.h"
33#include "map.h"
34#include "particle.h"
35#include "party.h"
36#include "playerrelations.h"
37#include "sound.h"
38#include "sprite.h"
39#include "statuseffect.h"
40#include "text.h"
41
42#include "gui/gui.h"
43#include "gui/socialwindow.h"
44#include "gui/speechbubble.h"
45
46#include "net/charhandler.h"
47#include "net/gamehandler.h"
48#include "net/net.h"
49#include "net/playerhandler.h"
50#include "net/npchandler.h"
51
52#include "resources/beinginfo.h"
53#include "resources/itemdb.h"
54#include "resources/iteminfo.h"
55#include "resources/monsterdb.h"
56#include "resources/npcdb.h"
58#include "resources/theme.h"
60
61#include "utils/stringutils.h"
62
63#include <cmath>
64
65Being::Being(int id, Type type, int subtype, Map *map)
66 : ActorSprite(id)
67 , mInfo(BeingInfo::Unknown)
68{
69 setMap(map);
70 setType(type, subtype);
71
73 mSpeechBubble->addDeathListener(this);
74
76
79}
80
82{
83 delete mSpeechBubble;
84 delete mDispName;
85 delete mText;
86}
87
93void Being::setType(Type type, int subtype)
94{
95 if (mType == type && mSubType == subtype)
96 return;
97
98 mType = type;
99 mSubType = subtype;
100
101 for (auto &spriteState : mSpriteStates)
102 {
103 spriteState.visibleId = 0;
104 spriteState.particles.clear();
105 }
106
107 switch (getType())
108 {
109 case MONSTER:
113 break;
114 case NPC:
117 mShowName = true;
118 break;
119 case PLAYER: {
120 mSprites.clear();
121 mChildParticleEffects.clear();
122
123 int id = -100 - subtype;
124
125 // Prevent showing errors when sprite doesn't exist
126 if (!itemDb->exists(id))
127 id = -100;
128
129 setSprite(Net::getCharHandler()->baseSprite(), id);
133 break;
134 }
135 case FLOOR_ITEM:
136 case PORTAL:
137 case UNKNOWN:
138 break;
139 }
140
142
143 updateName();
145 updateColors();
146}
147
149{
150 return mInfo->targetSelection;
151}
152
157
159{
160 return mInfo->hoverCursor;
161}
162
163unsigned char Being::getWalkMask() const
164{
165 return mInfo->walkMask;
166}
167
169{
170 return mInfo->blockType;
171}
172
173void Being::setMoveSpeed(const Vector &speed)
174{
175 mMoveSpeed = speed;
176 // If we already can, recalculate the system speed right away.
177 if (mMap)
180}
181
183{
184 return getPixelY() - std::min(getHeight(), 64) - 6;
185}
186
188{
190
192
193 if (mText)
195}
196
197void Being::setDestination(int dstX, int dstY)
198{
199 // We can't calculate anything without a map anyway.
200 if (!mMap)
201 return;
202
203 // Don't handle flawed destinations from server...
204 if (dstX <= 0 || dstY <= 0)
205 return;
206
207 // If the destination is unwalkable, don't bother trying to get there
208 const int tileWidth = mMap->getTileWidth();
209 const int tileHeight = mMap->getTileHeight();
210 if (!mMap->getWalk(dstX / tileWidth, dstY / tileHeight))
211 return;
212
213 Position dest(0, 0);
214 Path thisPath;
215 if (Net::getPlayerHandler()->usePixelPrecision())
216 {
218 dstX, dstY);
219 thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y,
220 dest.x, dest.y,
222 }
223 else
224 {
225 // We center the destination.
226 dest.x = (dstX / tileWidth) * tileWidth + tileWidth / 2;
227 dest.y = (dstY / tileHeight) * tileHeight + tileHeight / 2;
228 // and find a tile centered pixel path
229 thisPath = mMap->findTilePath((int) mPos.x, (int) mPos.y,
230 dest.x, dest.y, getWalkMask());
231 }
232
233 if (thisPath.empty())
234 {
235 // If there is no path but the destination is on the same walkable tile,
236 // we accept it.
237 if ((int)mPos.x / tileWidth == dest.x / tileWidth
238 && (int)mPos.y / tileHeight == dest.y / tileHeight)
239 {
240 mDest.x = dest.x;
241 mDest.y = dest.y;
242 }
243 setPath(Path());
244 return;
245 }
246
247 // The destination is valid, so we set it.
248 mDest.x = dest.x;
249 mDest.y = dest.y;
250
251 setPath(thisPath);
252}
253
255{
256 mPath.clear();
257}
258
259void Being::setPath(const Path &path)
260{
261 mPath = path;
262}
263
264void Being::setSpeech(const std::string &text, int time)
265{
266 mSpeech = text;
268 trim(mSpeech);
269
270 // Check for links
271 std::string::size_type start = mSpeech.find('[');
272 std::string::size_type end = mSpeech.find(']', start);
273
274 while (start != std::string::npos && end != std::string::npos)
275 {
276 // Catch multiple embeds and ignore them so it doesn't crash the client.
277 while ((mSpeech.find('[', start + 1) != std::string::npos) &&
278 (mSpeech.find('[', start + 1) < end))
279 {
280 start = mSpeech.find('[', start + 1);
281 }
282
283 std::string::size_type position = mSpeech.find('|');
284 if (mSpeech[start + 1] == '@' && mSpeech[start + 2] == '@')
285 {
286 mSpeech.erase(end, 1);
287 mSpeech.erase(start, (position - start) + 1);
288 }
289 position = mSpeech.find('@');
290
291 while (position != std::string::npos)
292 {
293 mSpeech.erase(position, 2);
294 position = mSpeech.find('@');
295 }
296
297 start = mSpeech.find('[', start + 1);
298 end = mSpeech.find(']', start);
299 }
300
301 if (!mSpeech.empty())
302 mSpeechTimer.set(std::min(time, SPEECH_MAX_TIME));
303
304 const int speech = config.speech;
305 if (speech == TEXT_OVERHEAD)
306 {
307 delete mText;
308 mText = new Text(mSpeech,
310 gcn::Graphics::CENTER,
312 true);
313 }
314}
315
316void Being::takeDamage(Being *attacker, int amount,
317 AttackType type, int attackId)
318{
319 gcn::Font *font;
320 std::string damage = amount ? toString(amount)
321 : (type == FLEE ? "dodge" : "miss");
322 const gcn::Color *color;
323
324 font = gui->getInfoParticleFont();
325
326 // Selecting the right color
327 if (type == CRITICAL || type == FLEE)
328 {
329 if (attacker == local_player)
330 {
331 color = &userPalette->getColor(
333 }
334 else
335 {
337 }
338 }
339 else if (!amount)
340 {
341 if (attacker == local_player)
342 {
343 // This is intended to be the wrong direction to visually
344 // differentiate between hits and misses
346 }
347 else
348 {
350 }
351 }
352 else if (getType() == MONSTER)
353 {
354 if (attacker == local_player)
355 {
356 color = &userPalette->getColor(
358 }
359 else
360 {
361 color = &userPalette->getColor(
363 }
364 }
365 else
366 {
368 }
369
370 // Show damage number
373 color, font, true);
374
375 if (amount > 0)
376 {
377 auto &hurtSfx = mInfo->getSound(SoundEvent::Hurt);
378 if (attacker)
379 sound.playSfx(hurtSfx, attacker->getPixelX(), attacker->getPixelY());
380 else
381 sound.playSfx(hurtSfx);
382
383 if (getType() == MONSTER)
384 {
385 mDamageTaken += amount;
386 updateName();
387 }
388
389 // Init the particle effect path based on current weapon or default.
390 int hitEffectId = 0;
391 const ItemInfo *attackerWeapon = attacker ?
392 attacker->getEquippedWeapon() : nullptr;
393
394 if (attackerWeapon && attacker->getType() == PLAYER)
395 {
396 if (type != CRITICAL)
397 hitEffectId = attackerWeapon->hitEffectId;
398 else
399 hitEffectId = attackerWeapon->criticalHitEffectId;
400 }
401 else if (attacker && attacker->getType() == MONSTER)
402 {
403 const Attack &attack = attacker->getInfo().getAttack(attackId);
404
405 if (type != CRITICAL)
406 hitEffectId = attack.hitEffectId;
407 else
408 hitEffectId = attack.criticalHitEffectId;
409 }
410 else
411 {
412 if (type != CRITICAL)
413 hitEffectId = paths.getIntValue("hitEffectId");
414 else
415 hitEffectId = paths.getIntValue("criticalHitEffectId");
416 }
417 effectManager->trigger(hitEffectId, this);
418 }
419}
420
421void Being::handleAttack(Being *victim, int damage, int attackId)
422{
423 // Monsters, NPCs and remote players handle the first attack (id="1")
424 // per default.
425 // TODO: Fix this for Manaserv by sending the attack id.
426 // TODO: Add attack type handling, see Attack struct and AttackType
427 // and make use of it by grouping attacks per attack type and add random
428 // attack use on tA, based on normal and critical attack types.
429 if (this != local_player)
430 setAction(Being::ATTACK, attackId);
431
432 if (victim)
433 {
434 lookAt(victim->getPosition());
435
436 if (getType() == PLAYER && mEquippedWeapon)
438 else
440 }
441
442 if (getType() == PLAYER)
443 {
444 auto itemInfo = mEquippedWeapon;
445
446 // Fall back to racesprite item
447 if (!itemInfo)
448 itemInfo = &itemDb->get(-100 - mSubType);
449
450 const auto event = damage > 0 ? EquipmentSoundEvent::Hit
452 const auto &soundFile = itemInfo->getSound(event);
453 sound.playSfx(soundFile, getPixelX(), getPixelY());
454 }
455 else
456 {
457 const auto event = damage > 0 ? SoundEvent::Hit : SoundEvent::Miss;
458 const auto &soundFile = mInfo->getSound(event);
459 sound.playSfx(soundFile, getPixelX(), getPixelY());
460 }
461}
462
463void Being::setName(const std::string &name)
464{
465 if (getType() == NPC)
466 mName = name.substr(0, name.find('#', 0));
467 else
468 mName = name;
469
470 updateName();
471}
472
473void Being::setShowName(bool doShowName)
474{
475 if (mShowName == doShowName)
476 return;
477
478 mShowName = doShowName;
479 updateName();
480}
481
482void Being::setGuildName(const std::string &name)
483{
484 Log::info("Got guild name \"%s\" for being %s(%i)", name.c_str(),
485 mName.c_str(), mId);
486}
487
488
489void Being::setGuildPos(const std::string &pos)
490{
491 Log::info("Got guild position \"%s\" for being %s(%i)", pos.c_str(),
492 mName.c_str(), mId);
493}
494
496{
497 mGuilds[guild->getId()] = guild;
498 guild->addMember(mId, mName);
499
500 if (this == local_player && socialWindow)
501 socialWindow->addTab(guild);
502}
503
505{
506 const auto it = mGuilds.find(id);
507 assert(it != mGuilds.end());
508
509 auto [_, guild] = *it;
510
511 if (this == local_player && socialWindow)
512 socialWindow->removeTab(guild);
513
514 guild->removeMember(mId);
515 mGuilds.erase(it);
516}
517
518Guild *Being::getGuild(const std::string &guildName) const
519{
520 for (auto &[_, guild] : mGuilds)
521 if (guild->getName() == guildName)
522 return guild;
523
524 return nullptr;
525}
526
527Guild *Being::getGuild(int id) const
528{
529 auto itr = mGuilds.find(id);
530 if (itr != mGuilds.end())
531 return itr->second;
532
533 return nullptr;
534}
535
537{
538 for (auto &[_, guild] : mGuilds)
539 {
540 if (this == local_player && socialWindow)
541 socialWindow->removeTab(guild);
542
543 guild->removeMember(mId);
544 }
545
546 mGuilds.clear();
547}
548
550{
551 if (party == mParty)
552 return;
553
554 Party *old = mParty;
555 mParty = party;
556
557 if (old)
558 {
559 old->removeMember(mId);
560 }
561
562 updateColors();
563
564 if (this == local_player && socialWindow)
565 {
566 if (old)
568
569 if (party)
570 socialWindow->addTab(party);
571 }
572}
573
574void Being::fireMissile(Being *victim, const std::string &particle)
575{
576 if (!victim || particle.empty())
577 return;
578
579 Particle *missile = particleEngine->addEffect(particle,
580 getPixelX(), getPixelY());
581
582 if (missile)
583 {
585 target->moveBy(Vector(0.0f, 0.0f,
586 Game::instance()->getCurrentTileWidth()));
587 target->setLifetime(1000);
588 victim->controlParticle(target);
589
590 missile->setDestination(target, 7, 0);
591 missile->setDieDistance(8);
592 missile->setLifetime(900);
593 }
594}
595
596void Being::setStatusEffect(int id, bool active)
597{
598 const auto it = mStatusEffects.find(id);
599 const bool wasActive = it != mStatusEffects.end();
600
601 if (active != wasActive)
602 {
603 if (active)
604 mStatusEffects.insert(id);
605 else
606 mStatusEffects.erase(it);
607
608 updateStatusEffect(id, active);
609 }
610}
611
612void Being::updateStatusEffect(int id, bool newStatus)
613{
614 auto effect = StatusEffectDB::getStatusEffect(id);
615 if (!effect)
616 return;
617
618 if (Particle *particle = effect->getParticle(newStatus))
620 else
621 mStatusParticleEffects.erase(id);
622}
623
624void Being::setAction(Action action, int attackId)
625{
626 std::string currentAction = SpriteAction::INVALID;
627
628 switch (action)
629 {
630 case MOVE:
631 currentAction = SpriteAction::MOVE;
632 // Note: When adding a run action,
633 // Differentiate walk and run with action name,
634 // while using only the ACTION_MOVE.
635 break;
636 case SIT:
637 currentAction = SpriteAction::SIT;
638 break;
639 case ATTACK:
640 if (mEquippedWeapon)
641 {
642 currentAction = mEquippedWeapon->attackAction;
643 mSprites.reset();
644 }
645 else
646 {
647 currentAction = mInfo->getAttack(attackId).action;
648 mSprites.reset();
649
650 // Attack particle effect
652 {
653 int effectId = mInfo->getAttack(attackId).effectId;
654 int rotation = 0;
655 switch (mSpriteDirection)
656 {
657 case DIRECTION_DOWN: rotation = 0; break;
658 case DIRECTION_LEFT: rotation = 90; break;
659 case DIRECTION_UP: rotation = 180; break;
660 case DIRECTION_RIGHT: rotation = 270; break;
661 default: break;
662 }
663 effectManager->trigger(effectId, this, rotation);
664 }
665 }
666
667 break;
668 case HURT:
669 //currentAction = SpriteAction::HURT;// Buggy: makes the player stop
670 // attacking and unable to attack
671 // again until he moves.
672 // TODO: fix this!
673 break;
674 case DEAD:
675 currentAction = SpriteAction::DEAD;
677 getPixelX(), getPixelY());
678 break;
679 case STAND:
680 currentAction = SpriteAction::STAND;
681 break;
682 }
683
684 if (currentAction != SpriteAction::INVALID)
685 {
686 mSprites.play(currentAction);
687 mAction = action;
688 }
689
690 if (currentAction != SpriteAction::MOVE)
692}
693
694void Being::setAction(const std::string &action)
695{
696 // Actions are triggered by strings from abilities when using manaserv,
697 // it's not necessarily an attack, but it seems the most appropriate value.
698 mAction = ATTACK;
699 mSprites.play(action);
700}
701
702void Being::lookAt(const Vector &destPos)
703{
704 // We first handle simple cases
705
706 // If the two positions are the same,
707 // don't update the direction since it's only a matter of keeping
708 // the previous one.
709 if (mPos.x == destPos.x && mPos.y == destPos.y)
710 return;
711
712 if (mPos.x == destPos.x)
713 {
714 if (mPos.y > destPos.y)
716 else
718 return;
719 }
720
721 if (mPos.y == destPos.y)
722 {
723 if (mPos.x > destPos.x)
725 else
727 return;
728 }
729
730 // Now let's handle diagonal cases
731 // First, find the lower angle:
732 if (mPos.x < destPos.x)
733 {
734 // Up-right direction
735 if (mPos.y > destPos.y)
736 {
737 // Compute tan of the angle
738 if ((mPos.y - destPos.y) / (destPos.x - mPos.x) < 1)
739 // The angle is less than 45°, we look to the right
741 else
743 return;
744 }
745 else // Down-right
746 {
747 // Compute tan of the angle
748 if ((destPos.y - mPos.y) / (destPos.x - mPos.x) < 1)
749 // The angle is less than 45°, we look to the right
751 else
753 return;
754 }
755 }
756 else
757 {
758 // Up-left direction
759 if (mPos.y > destPos.y)
760 {
761 // Compute tan of the angle
762 if ((mPos.y - destPos.y) / (mPos.x - destPos.x) < 1)
763 // The angle is less than 45°, we look to the left
765 else
767 return;
768 }
769 else // Down-left
770 {
771 // Compute tan of the angle
772 if ((destPos.y - mPos.y) / (mPos.x - destPos.x) < 1)
773 // The angle is less than 45°, we look to the left
775 else
777 return;
778 }
779 }
780}
781
783{
784 if (!direction || mDirection == direction)
785 return;
786
787 mDirection = direction;
788
790 if (mDirection & UP)
791 dir = DIRECTION_UP;
792 else if (mDirection & DOWN)
793 dir = DIRECTION_DOWN;
794 else if (mDirection & RIGHT)
795 dir = DIRECTION_RIGHT;
796 else
797 dir = DIRECTION_LEFT;
798 mSpriteDirection = dir;
799
802}
803
805{
806 // FIXME: Get this from XML file once a better pathfinding algorithm is up.
807 return 16;
808}
809
811{
812 // Remove text and speechbubbles if speech boxes aren't being used
813 if (mText && mSpeechTimer.passed())
814 {
815 delete mText;
816 mText = nullptr;
817 }
818
820 {
822
824
825 // Restart status/particle effects, if needed
826 for (int id : mStatusEffects)
827 {
829 if (effect && effect->persistentParticleEffect)
830 updateStatusEffect(id, true);
831 }
832 }
833
835 {
837
838 // Update particle effects
839 const float py = mPos.y + paths.getIntValue("spriteOffsetY");
840
841 for (auto &spriteState : mSpriteStates)
842 for (auto &particle : spriteState.particles)
843 particle->moveTo(mPos.x, py);
844
845 for (auto &[_, p] : mStatusParticleEffects)
846 p->moveTo(mPos.x, py);
847 }
848
850
851 // Remove it after 1.5 secs if the dead animation isn't long enough,
852 // or simply play it until it's finished.
853 if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && getType() != PLAYER)
854 if (mActionTimer.elapsed() > std::max(mSprites.getMaxDuration(), 1500))
856}
857
859{
860 float dt = Time::deltaTime();
861
862 while (dt > 0.f)
863 {
864 const Vector dest = mPath.empty() ? mDest
865 : Vector(mPath.front().x,
866 mPath.front().y);
867
868 // Avoid going to flawed destinations
869 // We make the being stop move in that case.
870 if (dest.x <= 0 || dest.y <= 0)
871 {
872 mDest = mPos;
873 mPath.clear();
874 break;
875 }
876
877 // The Vector representing the difference between current position
878 // and the next destination path node.
879 const Vector dir = dest - mPos;
880
881 // When we've not reached our destination, move to it.
882 if (!dir.isNull())
883 {
884 const float distanceToDest = dir.length();
885
886 // The deplacement of a point along a vector is calculated
887 // using the Unit Vector (â) multiplied by the point speed.
888 // â = a / ||a|| (||a|| is the a length.)
889 // Then, diff = (dir/||dir||) * speed.
890 const Vector normalizedDir = dir.normalized();
891 Vector diff(normalizedDir.x * mSpeedPixelsPerSecond.x * dt,
892 normalizedDir.y * mSpeedPixelsPerSecond.y * dt);
893 const float distanceToMove = diff.length();
894
895 // Test if we don't miss the destination by a move too far:
896 if (distanceToMove > distanceToDest)
897 {
898 setPosition(dest);
899
900 // Also, if the destination is reached, try to get the next
901 // path point, if existing.
902 if (!mPath.empty())
903 {
904 mPath.pop_front();
905
906 if (mPath.empty())
907 pathFinished();
908 }
909
910 // Set dt to the time left after performing this move.
911 dt -= dt * (distanceToDest / distanceToMove);
912 }
913 else
914 {
915 // Otherwise, go to it using the nominal speed.
916 setPosition(mPos + diff);
917 // And set the remaining time to 0.
918 dt = 0.f;
919 }
920
921 if (mAction != MOVE)
923
924 // The player direction is handled for keyboard
925 // by LocalPlayer::startWalking(), we shouldn't get
926 // in the way here for other cases.
927 // Hence, we set the direction in Being::logic() only when:
928 // 1. It is not the local_player
929 // 2. When it is the local_player but only by mouse
930 // (because in that case, the path can have more than one tile.)
932 {
933 int direction = 0;
934 const float dx = std::abs(dir.x);
935 const float dy = std::abs(dir.y);
936
937 if (dx > dy)
938 direction |= (dir.x > 0) ? RIGHT : LEFT;
939 else
940 direction |= (dir.y > 0) ? DOWN : UP;
941
942 setDirection(direction);
943 }
944 }
945 else if (!mPath.empty())
946 {
947 // If the current path node has been reached,
948 // remove it and go to the next one.
949 mPath.pop_front();
950
951 if (mPath.empty())
952 pathFinished();
953 }
954 else
955 {
956 if (mAction == MOVE)
958 break;
959 }
960 }
961}
962
963void Being::drawSpeech(int offsetX, int offsetY)
964{
965 const int px = getPixelX() - offsetX;
966 const int speech = config.speech;
967
968 // Draw speech above this being
969 if (mSpeechTimer.passed())
970 {
971 if (mSpeechBubble->isVisible())
972 mSpeechBubble->setVisible(false);
973 }
974 else if (speech == NAME_IN_BUBBLE || speech == NO_NAME_IN_BUBBLE)
975 {
976 const bool showName = (speech == NAME_IN_BUBBLE);
977
978 delete mText;
979 mText = nullptr;
980
981 mSpeechBubble->setCaption(showName ? mName : std::string(), mNameColor);
982
983 mSpeechBubble->setText(mSpeech, showName);
984 mSpeechBubble->setPosition(px - (mSpeechBubble->getWidth() / 2),
986 - mSpeechBubble->getHeight() - offsetY);
987 mSpeechBubble->setVisible(true);
988 }
989 else if (speech == TEXT_OVERHEAD)
990 {
991 mSpeechBubble->setVisible(false);
992
993 if (!mText)
994 {
995 mText = new Text(mSpeech,
997 gcn::Graphics::CENTER,
999 true);
1000 }
1001 }
1002 else if (speech == NO_SPEECH)
1003 {
1004 mSpeechBubble->setVisible(false);
1005
1006 delete mText;
1007 mText = nullptr;
1008 }
1009}
1010
1012{
1013 if (!mDispName)
1014 return;
1015
1016 // Monster names show above the sprite instead of below it
1017 if (getType() == MONSTER)
1019 else
1021}
1022
1023void Being::flashName(int time)
1024{
1025 if (mDispName)
1026 mDispName->flash(time);
1027}
1028
1030{
1031 delete mDispName;
1032 mDispName = nullptr;
1033
1034 if (!mShowName)
1035 return;
1036
1037 std::string mDisplayName(mName);
1038
1039 if (getType() == PLAYER)
1040 {
1041 if (config.showGender)
1042 {
1043 if (getGender() == Gender::Female)
1044 mDisplayName += " \u2640";
1045 else if (getGender() == Gender::Male)
1046 mDisplayName += " \u2642";
1047 }
1048
1049 // Display the IP when under tmw-Athena (GM only).
1051 && local_player->getShowIp() && getIp())
1052 {
1053 mDisplayName += strprintf(" %s", ipToString(getIp()));
1054 }
1055 }
1056
1057 if (getType() == MONSTER)
1058 {
1060 {
1061 mDisplayName += ", " + toString(getDamageTaken());
1062 }
1063 }
1064
1065 gcn::Font *font = nullptr;
1066 if (local_player && local_player->getTarget() == this
1067 && getType() != MONSTER)
1068 {
1069 font = boldFont;
1070 }
1071
1072 mDispName = new FlashText(mDisplayName, getPixelX(), getPixelY(),
1073 gcn::Graphics::CENTER, mNameColor, font);
1074
1076}
1077
1078void Being::addSpriteParticles(SpriteState &spriteState, const SpriteDisplay &display)
1079{
1080 if (!particleEngine) // happens in CharSelectDialog, for example
1081 return;
1082 if (!spriteState.particles.empty())
1083 return;
1084
1085 for (const auto &particle : display.particles)
1086 {
1087 Particle *p = particleEngine->addEffect(particle, 0, 0, 0);
1088 spriteState.particles.emplace_back(p);
1089 }
1090}
1091
1093{
1094 if (mType != PLAYER)
1095 return;
1096
1097 for (auto &spriteState : mSpriteStates)
1098 {
1099 if (spriteState.id)
1100 {
1101 auto &itemInfo = itemDb->get(spriteState.id);
1102 addSpriteParticles(spriteState, itemInfo.display);
1103 }
1104 }
1105}
1106
1108{
1109 switch (getType()) {
1111 return;
1113 if (this == local_player)
1114 {
1116 }
1117 else if (mIsGM)
1118 {
1120 }
1121 else if (mParty && mParty == local_player->getParty())
1122 {
1124 }
1125 else
1126 {
1128 }
1129 break;
1130 case ActorSprite::NPC:
1132 break;
1135 break;
1138 return;
1139 }
1140
1141 if (mDispName)
1143}
1144
1150{
1151 if (mType != PLAYER)
1152 return;
1153
1154 // hack for allow different logic in dead player
1155 const int direction = mAction == DEAD ? DIRECTION_DEAD : mSpriteDirection;
1156
1157 // Get the current item IDs
1158 std::vector<int> itemIDs(mSpriteStates.size());
1159 for (size_t i = 0; i < mSpriteStates.size(); i++)
1160 itemIDs[i] = mSpriteStates[i].id;
1161
1162 // Apply the replacements
1163 for (auto &spriteState : mSpriteStates)
1164 {
1165 if (!spriteState.id)
1166 continue;
1167
1168 auto &itemInfo = itemDb->get(spriteState.id);
1169 for (const auto &replacement : itemInfo.replacements)
1170 {
1171 if (replacement.direction != DIRECTION_ALL && replacement.direction != direction)
1172 continue;
1173
1174 if (replacement.sprite == SPRITE_ALL)
1175 {
1176 if (replacement.items.empty())
1177 {
1178 itemIDs.assign(itemIDs.size(), 0);
1179 }
1180 else
1181 {
1182 for (int &id : itemIDs)
1183 {
1184 for (auto &item : replacement.items)
1185 if (!item.from || id == item.from)
1186 id = item.to;
1187 }
1188 }
1189 }
1190 else if (replacement.sprite < itemIDs.size())
1191 {
1192 int &id = itemIDs[replacement.sprite];
1193
1194 if (replacement.items.empty())
1195 {
1196 id = 0;
1197 }
1198 else
1199 {
1200 for (auto &item : replacement.items)
1201 if (!item.from || id == item.from)
1202 id = item.to;
1203 }
1204 }
1205 }
1206 }
1207
1208 // Set the new sprites
1209 bool newSpriteSet = false;
1210
1212
1213 for (size_t i = 0; i < mSpriteStates.size(); i++)
1214 {
1215 auto &spriteState = mSpriteStates[i];
1216 if (spriteState.visibleId == itemIDs[i])
1217 continue;
1218
1219 spriteState.visibleId = itemIDs[i];
1220
1221 if (spriteState.visibleId == 0)
1222 {
1223 mSprites.set(i, nullptr);
1224 }
1225 else
1226 {
1227 newSpriteSet = true;
1228
1229 auto &itemInfo = itemDb->get(spriteState.visibleId);
1230 std::string filename = itemInfo.getSprite(mGender, mSubType);
1231 Sprite *equipmentSprite = nullptr;
1232
1233 if (!filename.empty())
1234 {
1235 if (!spriteState.color.empty())
1236 filename += "|" + spriteState.color;
1237
1238 equipmentSprite = Sprite::load(
1239 paths.getStringValue("sprites") + filename);
1240
1241 if (equipmentSprite)
1242 equipmentSprite->setDirection(getSpriteDirection());
1243 }
1244
1245 mSprites.set(i, equipmentSprite);
1246 }
1247 }
1248
1249 // Make sure any new sprites are set to the correct action
1250 if (newSpriteSet)
1252}
1253
1254void Being::setSprite(unsigned slot, int id, const std::string &color,
1255 bool isWeapon)
1256{
1257 if (slot >= mSpriteStates.size())
1258 mSpriteStates.resize(slot + 1);
1259
1260 auto &spriteState = mSpriteStates[slot];
1261
1262 // Clear current particles when the ID changes
1263 if (spriteState.id != id)
1264 spriteState.particles.clear();
1265
1266 // Clear the current sprite when the color changes
1267 if (spriteState.color != color && spriteState.visibleId)
1268 {
1269 spriteState.visibleId = 0;
1270 mSprites.set(slot, nullptr);
1271 }
1272
1273 spriteState.id = id;
1274 spriteState.color = color;
1275
1276 if (id == 0) // id = 0 means unequip
1277 {
1278 if (isWeapon)
1279 mEquippedWeapon = nullptr;
1280 }
1281 else
1282 {
1283 auto &itemInfo = itemDb->get(id);
1284
1285 if (mType == PLAYER)
1286 addSpriteParticles(spriteState, itemInfo.display);
1287
1288 if (isWeapon)
1289 mEquippedWeapon = &itemInfo;
1290 }
1291
1293}
1294
1295void Being::setSpriteID(unsigned slot, int id)
1296{
1297 assert(slot < mSpriteStates.size());
1298 setSprite(slot, id, mSpriteStates[slot].color);
1299}
1300
1301void Being::setSpriteColor(unsigned slot, const std::string &color)
1302{
1303 assert(slot < mSpriteStates.size());
1304 setSprite(slot, mSpriteStates[slot].id, color);
1305}
1306
1308{
1309 // For now, just draw actors with only one layer when obscured
1310 return mSprites.getNumberOfLayers() == 1;
1311}
1312
1314{
1315 if (gender != mGender)
1316 {
1317 mGender = gender;
1318
1319 // Reset all sprites to force reload with the correct gender
1320 for (size_t i = 0; i < mSpriteStates.size(); i++)
1321 {
1322 auto &spriteState = mSpriteStates[i];
1323 if (spriteState.visibleId)
1324 {
1325 mSprites.set(i, nullptr);
1326 spriteState.visibleId = 0;
1327 }
1328 }
1329
1331
1332 if (config.showGender)
1333 updateName();
1334 }
1335}
1336
1337void Being::setGM(bool gm)
1338{
1339 mIsGM = gm;
1340
1341 updateColors();
1342}
1343
1344void Being::setIp(int ip)
1345{
1346 if (mIp == ip)
1347 return;
1348
1349 mIp = ip;
1350
1352 updateName();
1353}
1354
1356{
1357 return mType == NPC;
1358}
1359
1361{
1363}
1364
1365void Being::event(Event::Channel channel, const Event &event)
1366{
1367 if (channel == Event::ChatChannel &&
1368 (event.getType() == Event::Being
1369 || event.getType() == Event::Player) &&
1370 event.getInt("permissions") & PlayerPermissions::SPEECH_FLOAT)
1371 {
1372 try
1373 {
1374 if (mId == event.getInt("beingId"))
1375 {
1376 setSpeech(event.getString("text"));
1377 }
1378 }
1379 catch (BadEvent badEvent)
1380 {}
1381 }
1382 else if (channel == Event::ConfigChannel &&
1383 event.getType() == Event::ConfigOptionChanged)
1384 {
1385 if (getType() == PLAYER && event.hasValue(&Config::visibleNames))
1386 {
1388 }
1389 }
1390}
1391
1392void Being::death(const gcn::Event &event)
1393{
1394 if (event.getSource() == mSpeechBubble)
1395 mSpeechBubble = nullptr;
1396}
1397
1399{
1400 for (auto &spriteState : mSpriteStates)
1401 spriteState.particles.clear();
1402
1403 mStatusParticleEffects.clear();
1404
1406
1408
1409 // Recalculate pixel/tick speed
1410 if (map && !mMoveSpeed.isNull())
1411 {
1414 }
1415}
ActorSpriteManager * actorSpriteManager
Definition game.cpp:110
Gender
Definition being.h:58
#define SPEECH_MAX_TIME
Definition being.h:45
An action consists of several animations, one for each direction.
Definition action.h:32
void scheduleDelete(ActorSprite *actor)
Destroys the given ActorSprite at the end of ActorSpriteManager::logic.
virtual void logic()
void controlParticle(Particle *particle)
Take control of a particle.
int getHeight() const
void setMap(Map *map) override
void setupSpriteDisplay(const SpriteDisplay &display, bool forceDisplay=true)
CompoundSprite mSprites
std::vector< ParticleHandle > mChildParticleEffects
int getPixelX() const
Returns the pixels X coordinate of the actor.
Definition actor.h:65
int getPixelY() const
Returns the pixel Y coordinate of the actor.
Definition actor.h:71
virtual void setPosition(const Vector &pos)
Sets the pixel position of this actor.
Definition actor.h:59
Vector mPos
Position in pixels relative to map.
Definition actor.h:114
const Vector & getPosition() const
Returns the pixel position of this actor.
Definition actor.h:53
Map * mMap
Definition actor.h:113
Holds information about a certain type of monster.
Definition beinginfo.h:59
const Attack & getAttack(int id) const
ActorSprite::TargetCursorSize targetCursorSize
Definition beinginfo.h:68
unsigned char walkMask
Definition beinginfo.h:70
SpriteDisplay display
Definition beinginfo.h:67
Map::BlockType blockType
Definition beinginfo.h:71
const std::string & getSound(SoundEvent event) const
Definition beinginfo.cpp:98
Cursor hoverCursor
Definition beinginfo.h:69
bool targetSelection
Definition beinginfo.h:72
std::string name
Definition beinginfo.h:66
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
bool mIsGM
Definition being.h:538
Text * mText
Definition being.h:525
void event(Event::Channel channel, const Event &event) override
Definition being.cpp:1365
AttackType
Definition being.h:91
@ FLEE
Definition being.h:96
@ CRITICAL
Definition being.h:93
int mSubType
Subtype (graphical view, basically)
Definition being.h:506
const ItemInfo * getEquippedWeapon() const
Definition being.h:184
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
bool mRestoreParticlesOnLogic
Definition being.h:530
void setGuildName(const std::string &name)
Sets the name of the primary guild the being is in.
Definition being.cpp:482
TargetCursorSize getTargetCursorSize() const override
Returns the required size of a target cursor for this being.
Definition being.cpp:153
void setShowName(bool doShowName)
Definition being.cpp:473
int mDamageTaken
Definition being.h:563
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
void fireMissile(Being *target, const std::string &particle)
Shoots a missile particle from this being, to target being.
Definition being.cpp:574
const BeingInfo & getInfo() const
Definition being.h:294
void setMap(Map *map) final
Definition being.cpp:1398
Action mAction
Action the being is performing.
Definition being.h:505
void updateMovement()
Definition being.cpp:858
void updateName()
Definition being.cpp:1029
std::string mSpeech
Definition being.h:524
unsigned char getWalkMask() const
Gets the way the object is blocked by other objects.
Definition being.cpp:163
int getIp() const
Returns the player's IP or an IP hash.
Definition being.h:435
Type getType() const final
Returns the type of the ActorSprite.
Definition being.h:122
uint8_t mSpriteDirection
Facing direction.
Definition being.h:509
virtual void updateStatusEffect(int index, bool newStatus)
Notify self that a status effect has flipped.
Definition being.cpp:612
std::vector< SpriteState > mSpriteStates
Definition being.h:529
std::map< int, Guild * > mGuilds
Definition being.h:535
std::string mName
Name of character.
Definition being.h:510
SpriteDirection getSpriteDirection() const
Returns the direction the being is facing.
Definition being.h:366
SpeechBubble * mSpeechBubble
Speech Bubble components.
Definition being.h:549
bool drawnWhenBehind() const override
Determines wether the actor should be drawn translucent when behind another object.
Definition being.cpp:1307
void setPath(const Path &path)
Sets the new path for this being.
Definition being.cpp:259
void setSpriteColor(unsigned slot, const std::string &color=std::string())
Definition being.cpp:1301
void lookAt(const Vector &destVec)
Make the being look at a given pixel position.
Definition being.cpp:702
void updateColors()
Definition being.cpp:1107
int getCollisionRadius() const
Returns the being's pixel radius used to detect collisions.
Definition being.cpp:804
void drawSpeech(int offsetX, int offsetY)
Draws the speech text above the being.
Definition being.cpp:963
void updateNamePosition()
Updates name's location.
Definition being.cpp:1011
const ItemInfo * mEquippedWeapon
Engine-related infos about weapon.
Definition being.h:521
void setName(const std::string &name)
Sets the name for the being.
Definition being.cpp:463
void setIp(int ip)
Sets the IP or an IP hash.
Definition being.cpp:1344
virtual void pathFinished()
Called when the being has reached the end of its path.
Definition being.h:488
int getSpeechTextYPosition() const
Gets the advised Y chat text position.
Definition being.cpp:182
Vector mDest
destination coordinates.
Definition being.h:527
@ RIGHT
Definition being.h:107
@ DOWN
Definition being.h:104
@ UP
Definition being.h:106
@ LEFT
Definition being.h:105
@ NAME_IN_BUBBLE
Definition being.h:87
@ NO_NAME_IN_BUBBLE
Definition being.h:86
@ TEXT_OVERHEAD
Definition being.h:85
@ NO_SPEECH
Definition being.h:84
Gender mGender
Definition being.h:532
@ SIT
Definition being.h:77
@ MOVE
Definition being.h:75
@ ATTACK
Definition being.h:76
@ STAND
Definition being.h:74
@ HURT
Definition being.h:79
@ DEAD
Definition being.h:78
bool isAlive() const
Returns whether this being is still alive.
Definition being.h:351
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
virtual void setAction(Action action, int attackId=1)
Sets the current action.
Definition being.cpp:624
void talkTo()
Definition being.cpp:1360
Cursor getHoverCursor() const
Definition being.cpp:158
void setType(Type type, int subtype)
Can be used to change the type of the being.
Definition being.cpp:93
Type mType
Definition being.h:543
const gcn::Color * mNameColor
Definition being.h:517
void setParty(Party *party)
Definition being.cpp:549
Timer mSpeechTimer
Time until the last speech sentence disappears.
Definition being.h:501
void logic() override
Performs being logic.
Definition being.cpp:810
~Being() override
Definition being.cpp:81
FlashText * mDispName
Holds a text object when the being displays its name, 0 otherwise.
Definition being.h:516
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
const BeingInfo * mInfo
Definition being.h:496
Map::BlockType getBlockType() const override
Gets the way the monster blocks pathfinding for other objects.
Definition being.cpp:168
Timer mActionTimer
Time spent in current action.
Definition being.h:498
void flashName(int time)
Definition being.cpp:1023
Party * mParty
Definition being.h:536
void addGuild(Guild *guild)
Adds a guild to the being.
Definition being.cpp:495
void updatePlayerSprites()
Updates the visible sprite IDs of the player, taking into account the item replacements.
Definition being.cpp:1149
void removeGuild(int id)
Removers a guild from the being.
Definition being.cpp:504
Vector mMoveSpeed
Walk speed for x and y movement values.
Definition being.h:556
bool isTargetSelection() const
Definition being.cpp:148
std::map< int, ParticleHandle > mStatusParticleEffects
Definition being.h:546
Guild * getGuild(const std::string &guildName) const
Returns a pointer to the specified guild that the being is in.
Definition being.cpp:518
uint8_t mDirection
Facing direction.
Definition being.h:508
void death(const gcn::Event &event) override
Definition being.cpp:1392
void takeDamage(Being *attacker, int damage, AttackType type, int attackId=1)
Puts a damage bubble above this being.
Definition being.cpp:316
Vector mSpeedPixelsPerSecond
Being speed in pixel per second.
Definition being.h:561
void clearPath()
Removes all path nodes from this being.
Definition being.cpp:254
void setSpriteID(unsigned slot, int id)
Definition being.cpp:1295
void setSpeech(const std::string &text, int time=5000)
Puts a "speech balloon" above this being for the specified amount of time.
Definition being.cpp:264
Being(int id, Type type, int subtype, Map *map)
Constructor.
Definition being.cpp:65
bool canTalk()
Definition being.cpp:1355
void addSpriteParticles(SpriteState &spriteState, const SpriteDisplay &display)
Definition being.cpp:1078
void restoreAllSpriteParticles()
Definition being.cpp:1092
int mIp
Definition being.h:564
std::set< int > mStatusEffects
set of active status effects
Definition being.h:545
bool mShowName
Definition being.h:518
Path mPath
Definition being.h:523
void clearGuilds()
Removes all guilds the being is in.
Definition being.cpp:536
Gender getGender() const
Definition being.h:411
int getDamageTaken() const
Definition being.h:401
void doRedraw() const
int getNumberOfLayers() const
bool play(const std::string &action)
void ensureSize(size_t layerCount)
void set(int layer, Sprite *sprite)
bool setDirection(SpriteDirection direction)
int getMaxDuration() const
std::string getStringValue(const std::string &key) const
int getIntValue(const std::string &key) const
returns a value corresponding to the given key.
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...
void listen(Event::Channel channel)
Definition event.h:42
@ ConfigOptionChanged
Definition event.h:68
@ Being
Definition event.h:63
@ Player
Definition event.h:92
Channel
Definition event.h:45
@ ChatChannel
Definition event.h:49
@ ConfigChannel
Definition event.h:51
void flash(int time)
Flash the text for so many milliseconds.
Definition text.h:87
static Game * instance()
Provides access to the game instance.
Definition game.h:53
gcn::Font * getInfoParticleFont() const
Return the Font used for "Info Particles", i.e.
Definition gui.h:114
Definition guild.h:55
GuildMember * addMember(int id, const std::string &name)
Adds member to the list.
Definition guild.cpp:44
short getId() const
Get the id of the guild.
Definition guild.h:103
bool exists(int id) const
Definition itemdb.cpp:138
const ItemInfo & get(int id) const
Definition itemdb.cpp:145
Defines a class for storing generic item infos.
Definition iteminfo.h:100
int hitEffectId
Definition iteminfo.h:121
const std::string & getSprite(Gender gender, int race) const
Definition iteminfo.cpp:27
std::string attackAction
Attack type, in case of weapon.
Definition iteminfo.h:128
std::string missileParticleFile
Effects to be shown when weapon attacks - see also effects.xml.
Definition iteminfo.h:120
const std::string & getSound(EquipmentSoundEvent event) const
Definition iteminfo.cpp:50
int criticalHitEffectId
Definition iteminfo.h:122
Being * getTarget() const
Returns the current target of the player.
bool isPathSetByMouse() const
Tells if the path has been set by mouse.
bool getShowIp() const
A tile map.
Definition map.h:147
Path findPixelPath(int startPixelX, int startPixelY, int destPixelX, int destPixelY, int radius, unsigned char walkmask, int maxCost=20)
Find a pixel path from one location to the next using free offsets.
Definition map.cpp:700
int getTileHeight() const
Returns the tile height used by this map.
Definition map.h:271
BlockType
Definition map.h:150
int getTileWidth() const
Returns the tile width of this map.
Definition map.h:265
Position checkNodeOffsets(int radius, unsigned char walkMask, const Position &position) const
Check the current position against surrounding blocking tiles, and correct the position offset within...
Definition map.cpp:615
bool getWalk(int x, int y, unsigned char walkmask=BLOCKMASK_WALL) const
Gets walkability for a tile with a blocking bitmask.
Definition map.cpp:541
Path findTilePath(int startPixelX, int startPixelY, int endPixelX, int endPixelY, unsigned char walkMask, int maxCost=20)
Find a tile-centered path in pixel coordinates from one location to the next.
Definition map.cpp:676
virtual void talk(int npcId)=0
virtual Vector getPixelsPerSecondMoveSpeed(const Vector &speed, Map *map=nullptr)=0
Convert the original server-dependant speed for internal use.
virtual Vector getDefaultMoveSpeed() const =0
Get the original default movement speed.
const gcn::Color & getColor(int type) const
Gets the color associated with the type.
Definition palette.h:72
A handle on a particle.
Definition particle.h:299
A particle spawned by a ParticleEmitter.
Definition particle.h:42
void moveBy(const Vector &change)
Changes the particle position relative.
Definition particle.cpp:228
Particle * createChild()
Creates a blank particle as a child of the current particle Useful for creating target particles.
Definition particle.cpp:242
void setDieDistance(float dist)
Sets the distance in pixel the particle can come near the target particle before it is destroyed.
Definition particle.h:216
void setLifetime(int lifetime)
Sets the time in game ticks until the particle is destroyed.
Definition particle.h:150
void setDestination(Particle *target, float accel, float moment)
Makes the particle move toward another particle with a given acceleration and momentum.
Definition particle.h:208
Particle * addTextSplashEffect(const std::string &text, int x, int y, const gcn::Color *color, gcn::Font *font, bool outline=false)
Creates a standalone text particle.
Definition particle.cpp:364
Particle * addEffect(const std::string &particleEffectFile, int pixelX, int pixelY, int rotation=0)
Creates a child particle that hosts some emitters described in the particleEffectFile.
Definition particle.cpp:249
static bool enabled
true when non-crucial particle effects are disabled
Definition particle.h:59
Definition party.h:59
void removeMember(PartyMember *member)
Removes a member from the party.
Definition party.cpp:78
bool removeTab(Guild *guild)
bool addTab(Guild *guild)
void playSfx(const std::string &path, int x=0, int y=0)
Plays a sound at the specified location.
Definition sound.cpp:248
void setCaption(const std::string &name, const gcn::Color *color=&Theme::getThemeColor(Theme::TEXT))
Sets the name displayed for the speech bubble, and in what color.
void setText(const std::string &text, bool showName=true)
Sets the text to be displayed.
Animates a sprite by adding playback state.
Definition sprite.h:37
static Sprite * load(const std::string &filename, int variant=0)
An helper function, which will request the sprite to animate from the resource manager.
Definition sprite.cpp:42
bool setDirection(SpriteDirection direction)
Sets the direction.
Definition sprite.cpp:149
static const StatusEffect * getStatusEffect(int id)
Retrieves a status effect.
bool persistentParticleEffect
Determines whether the particle effect should be restarted when the being changes maps.
Definition text.h:34
int getHeight() const
Definition text.h:54
void setColor(const gcn::Color *color)
Definition text.cpp:84
void adviseXY(int x, int y)
Allows the originator of the text to specify the ideal coordinates.
Definition text.cpp:89
static const gcn::Color & getThemeColor(int type)
Gets the color associated with the type in the default palette (0).
Definition theme.cpp:313
@ BUBBLE_TEXT
Definition theme.h:239
bool passed() const
Returns whether the timer has passed.
Definition time.h:88
int32_t elapsed() const
Returns the number of milliseconds elapsed since the set time, or a negative value if the timer hasn'...
Definition time.cpp:65
void set(uint32_t ms=0)
Sets the timer with an optional duration in milliseconds.
Definition time.h:69
@ HIT_LOCAL_PLAYER_MONSTER
Definition userpalette.h:51
@ HIT_LOCAL_PLAYER_MISS
Definition userpalette.h:53
@ HIT_LOCAL_PLAYER_CRITICAL
Definition userpalette.h:52
Vector class.
Definition vector.h:33
float length() const
Returns the length of this vector.
Definition vector.h:140
float y
Definition vector.h:172
Vector normalized() const
Returns a normalized version of this vector.
Definition vector.h:165
float x
Definition vector.h:171
bool isNull() const
Returns true if all coordinates are set to 0, otherwise returns false.
Definition vector.h:47
Config config
Global settings (config.xml)
Definition client.cpp:97
Configuration paths
XML default paths information reader.
Definition client.cpp:99
UserPalette * userPalette
Definition client.cpp:103
Sound sound
Definition client.cpp:109
ItemDB * itemDb
Items info database.
Definition client.cpp:106
EffectManager * effectManager
Definition game.cpp:114
BadEvent
Definition event.h:32
Particle * particleEngine
Definition game.cpp:113
SocialWindow * socialWindow
Definition game.cpp:108
#define _(s)
Definition gettext.h:38
Gui * gui
The GUI system.
Definition gui.cpp:50
gcn::Font * boldFont
Bolded text font.
Definition gui.cpp:54
Cursor
Cursors are in graphic order from left to right.
Definition gui.h:55
@ SPRITE_ALL
Definition iteminfo.h:80
@ DIRECTION_DEAD
Definition iteminfo.h:73
@ DIRECTION_ALL
Definition iteminfo.h:72
LocalPlayer * local_player
void info(const char *log_text,...) LOG_PRINTF_ATTR
BeingInfo * get(int id)
BeingInfo * get(int id)
Definition npcdb.cpp:91
ServerType getNetworkType()
Definition net.cpp:200
GameHandler * getGameHandler()
Definition net.cpp:75
CharHandler * getCharHandler()
Definition net.cpp:65
PlayerHandler * getPlayerHandler()
Definition net.cpp:110
NpcHandler * getNpcHandler()
Definition net.cpp:100
float deltaTime()
The time in seconds since the last frame, but never more than 1.
Definition time.cpp:44
std::list< Position > Path
Definition position.h:40
unsigned char uint8_t
Definition sha256.cpp:81
SpriteDirection
Definition spritedef.h:74
@ DIRECTION_DOWN
Definition spritedef.h:77
@ DIRECTION_LEFT
Definition spritedef.h:78
@ DIRECTION_UP
Definition spritedef.h:76
@ DIRECTION_DEFAULT
Definition spritedef.h:75
@ DIRECTION_RIGHT
Definition spritedef.h:79
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
std::string & trim(std::string &str)
Trims spaces off the end and the beginning of the given string.
const char * ipToString(int address)
Converts the given IP address to a string.
std::string & removeColors(std::string &msg)
Removes colors from a string.
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
Definition stringutils.h:68
std::string missileParticleFilename
Definition beinginfo.h:40
int effectId
Definition beinginfo.h:37
std::string action
Definition beinginfo.h:36
int hitEffectId
Definition beinginfo.h:38
int criticalHitEffectId
Definition beinginfo.h:39
std::vector< ParticleHandle > particles
Definition being.h:461
bool visibleNames
Being::Speech speech
bool showOwnName
bool showGender
bool showMonstersTakedDamage
A position along a being's path.
Definition position.h:31
int y
Definition position.h:37
int x
Definition position.h:36
std::vector< std::string > particles
Definition spritedef.h:45