summaryrefslogtreecommitdiff
path: root/src/being/being.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/being/being.cpp')
-rw-r--r--src/being/being.cpp5470
1 files changed, 0 insertions, 5470 deletions
diff --git a/src/being/being.cpp b/src/being/being.cpp
deleted file mode 100644
index 6bbf50a48..000000000
--- a/src/being/being.cpp
+++ /dev/null
@@ -1,5470 +0,0 @@
-/*
- * The ManaPlus Client
- * Copyright (C) 2004-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- * Copyright (C) 2011-2017 The ManaPlus Developers
- *
- * This file is part of The ManaPlus Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "being/being.h"
-
-#include "actormanager.h"
-#include "beingequipbackend.h"
-#include "configuration.h"
-#include "effectmanager.h"
-#include "guild.h"
-#include "itemcolormanager.h"
-#include "party.h"
-#include "settings.h"
-#include "soundmanager.h"
-#include "text.h"
-
-#include "being/beingcacheentry.h"
-#include "being/beingflag.h"
-#include "being/beingspeech.h"
-#include "being/castingeffect.h"
-#include "being/localplayer.h"
-#include "being/playerinfo.h"
-#include "being/playerrelations.h"
-#include "being/homunculusinfo.h"
-#include "being/mercenaryinfo.h"
-
-#include "const/utils/timer.h"
-
-#include "const/resources/spriteaction.h"
-
-#include "enums/being/beingdirection.h"
-
-#include "enums/resources/map/blockmask.h"
-
-#include "fs/files.h"
-
-#include "gui/gui.h"
-#include "gui/userpalette.h"
-
-#include "gui/fonts/font.h"
-
-#include "gui/popups/speechbubble.h"
-
-#include "gui/windows/chatwindow.h"
-#include "gui/windows/equipmentwindow.h"
-#include "gui/windows/skilldialog.h"
-#include "gui/windows/socialwindow.h"
-
-#include "net/charserverhandler.h"
-#include "net/gamehandler.h"
-#include "net/homunculushandler.h"
-#include "net/mercenaryhandler.h"
-#include "net/net.h"
-#include "net/npchandler.h"
-#include "net/packetlimiter.h"
-#include "net/playerhandler.h"
-#include "net/serverfeatures.h"
-
-#include "particle/particleinfo.h"
-
-#include "resources/attack.h"
-#include "resources/chatobject.h"
-#include "resources/emoteinfo.h"
-#include "resources/emotesprite.h"
-#include "resources/horseinfo.h"
-#include "resources/iteminfo.h"
-
-#include "resources/db/avatardb.h"
-#include "resources/db/badgesdb.h"
-#include "resources/db/groupdb.h"
-#include "resources/db/elementaldb.h"
-#include "resources/db/emotedb.h"
-#include "resources/db/homunculusdb.h"
-#include "resources/db/horsedb.h"
-#include "resources/db/languagedb.h"
-#include "resources/db/mercenarydb.h"
-#include "resources/db/monsterdb.h"
-#include "resources/db/npcdb.h"
-#include "resources/db/petdb.h"
-#include "resources/db/skillunitdb.h"
-
-#include "resources/image/image.h"
-
-#include "resources/item/item.h"
-
-#include "resources/map/map.h"
-
-#include "resources/skill/skilldata.h"
-#include "resources/skill/skillinfo.h"
-
-#include "resources/sprite/animatedsprite.h"
-
-#include "gui/widgets/createwidget.h"
-
-#include "gui/widgets/tabs/chat/langtab.h"
-
-#include "utils/checkutils.h"
-#include "utils/delete2.h"
-#include "utils/foreach.h"
-#include "utils/gettext.h"
-#include "utils/likely.h"
-#include "utils/stdmove.h"
-#include "utils/timer.h"
-
-#include "debug.h"
-
-const unsigned int CACHE_SIZE = 50;
-
-time_t Being::mUpdateConfigTime = 0;
-unsigned int Being::mConfLineLim = 0;
-int Being::mSpeechType = 0;
-bool Being::mHighlightMapPortals = false;
-bool Being::mHighlightMonsterAttackRange = false;
-bool Being::mLowTraffic = true;
-bool Being::mDrawHotKeys = true;
-bool Being::mShowBattleEvents = false;
-bool Being::mShowMobHP = false;
-bool Being::mShowOwnHP = false;
-bool Being::mShowGender = false;
-bool Being::mShowLevel = false;
-bool Being::mShowPlayersStatus = false;
-bool Being::mEnableReorderSprites = true;
-bool Being::mHideErased = false;
-Move Being::mMoveNames = Move_false;
-bool Being::mUseDiagonal = true;
-BadgeDrawType::Type Being::mShowBadges = BadgeDrawType::Top;
-int Being::mAwayEffect = -1;
-VisibleNamePos::Type Being::mVisibleNamePos = VisibleNamePos::Bottom;
-
-std::list<BeingCacheEntry*> beingInfoCache;
-typedef std::map<int, Guild*>::const_iterator GuildsMapCIter;
-typedef std::map<int, int>::const_iterator IntMapCIter;
-
-static const unsigned int SPEECH_TIME = 500;
-static const unsigned int SPEECH_MIN_TIME = 200;
-static const unsigned int SPEECH_MAX_TIME = 800;
-
-#define for_each_badges() \
- for (int f = 0; f < BadgeIndex::BadgeIndexSize; f++)
-
-#define for_each_horses(name) \
- FOR_EACH (STD_VECTOR<AnimatedSprite*>::const_iterator, it, name)
-
-Being::Being(const BeingId id,
- const ActorTypeT type) :
- ActorSprite(id),
- mNextSound(),
- mInfo(BeingInfo::unknown),
- mEmotionSprite(nullptr),
- mAnimationEffect(nullptr),
- mCastingEffect(nullptr),
- mBadges(),
- mSpriteAction(SpriteAction::STAND),
- mName(),
- mExtName(),
- mRaceName(),
- mPartyName(),
- mGuildName(),
- mSpeech(),
- mDispName(nullptr),
- mNameColor(nullptr),
- mEquippedWeapon(nullptr),
- mPath(),
- mText(nullptr),
- mTextColor(nullptr),
- mDest(),
- mSlots(),
- mSpriteParticles(),
- mGuilds(),
- mParty(nullptr),
- mActionTime(0),
- mEmotionTime(0),
- mSpeechTime(0),
- mAttackSpeed(350),
- mLevel(0),
- mGroupId(0),
- mAttackRange(1),
- mLastAttackX(0),
- mLastAttackY(0),
- mPreStandTime(0),
- mGender(Gender::UNSPECIFIED),
- mAction(BeingAction::STAND),
- mSubType(fromInt(0xFFFF, BeingTypeId)),
- mDirection(BeingDirection::DOWN),
- mDirectionDelayed(0),
- mSpriteDirection(SpriteDirection::DOWN),
- mShowName(false),
- mIsGM(false),
- mType(type),
- mSpeechBubble(nullptr),
- mWalkSpeed(playerHandler != nullptr ?
- playerHandler->getDefaultWalkSpeed() : 1),
- mSpeed(playerHandler != nullptr ?
- playerHandler->getDefaultWalkSpeed() : 1),
- mIp(),
- mSpriteRemap(new int[20]),
- mSpriteHide(new int[20]),
- mSpriteDraw(new int[20]),
- mComment(),
- mBuyBoard(),
- mSellBoard(),
- mOwner(nullptr),
- mSpecialParticle(nullptr),
- mChat(nullptr),
- mHorseInfo(nullptr),
- mDownHorseSprites(),
- mUpHorseSprites(),
- mSpiritParticles(),
- mX(0),
- mY(0),
- mCachedX(0),
- mCachedY(0),
- mSortOffsetY(0),
- mPixelOffsetY(0),
- mFixedOffsetY(0),
- mOldHeight(0),
- mDamageTaken(0),
- mHP(0),
- mMaxHP(0),
- mDistance(0),
- mReachable(Reachable::REACH_UNKNOWN),
- mGoodStatus(-1),
- mMoveTime(0),
- mAttackTime(0),
- mTalkTime(0),
- mOtherTime(0),
- mTestTime(cur_time),
- mAttackDelay(0),
- mMinHit(0),
- mMaxHit(0),
- mCriticalHit(0),
- mPvpRank(0),
- mNumber(100),
- mSpiritBalls(0U),
- mUsageCounter(1),
- mKarma(0),
- mManner(0),
- mAreaSize(11),
- mCastEndTime(0),
- mLanguageId(-1),
- mBadgesX(0),
- mBadgesY(0),
- mCreatorId(BeingId_zero),
- mTeamId(0U),
- mLook(0U),
- mBadgesCount(0U),
- mHairColor(ItemColor_zero),
- mErased(false),
- mEnemy(false),
- mGotComment(false),
- mAdvanced(false),
- mShop(false),
- mAway(false),
- mInactive(false),
- mNeedPosUpdate(true),
- mBotAi(true)
-{
- for (int f = 0; f < 20; f ++)
- {
- mSpriteRemap[f] = f;
- mSpriteHide[f] = 0;
- mSpriteDraw[f] = 0;
- }
-
- for_each_badges()
- mBadges[f] = nullptr;
-}
-
-void Being::postInit(const BeingTypeId subtype,
- Map *const map)
-{
- setMap(map);
- setSubtype(subtype, 0);
-
- VisibleName::Type showName1 = VisibleName::Hide;
-
- switch (mType)
- {
- case ActorType::Player:
- case ActorType::Mercenary:
- case ActorType::Pet:
- case ActorType::Homunculus:
- case ActorType::Elemental:
- showName1 = static_cast<VisibleName::Type>(
- config.getIntValue("visiblenames"));
- break;
- case ActorType::Portal:
- case ActorType::SkillUnit:
- showName1 = VisibleName::Hide;
- break;
- default:
- case ActorType::Unknown:
- case ActorType::Npc:
- case ActorType::Monster:
- case ActorType::FloorItem:
- case ActorType::Avatar:
- break;
- }
-
- if (mType != ActorType::Npc)
- mGotComment = true;
-
- config.addListener("visiblenames", this);
-
- reReadConfig();
-
- if (mType == ActorType::Npc ||
- showName1 == VisibleName::Show)
- {
- setShowName(true);
- }
-
- updateColors();
- updatePercentHP();
-}
-
-Being::~Being()
-{
- config.removeListener("visiblenames", this);
- CHECKLISTENERS
-
- delete [] mSpriteRemap;
- mSpriteRemap = nullptr;
- delete [] mSpriteHide;
- mSpriteHide = nullptr;
- delete [] mSpriteDraw;
- mSpriteDraw = nullptr;
-
- for_each_badges()
- delete2(mBadges[f]);
-
- delete2(mSpeechBubble);
- delete2(mDispName);
- delete2(mText);
- delete2(mEmotionSprite);
- delete2(mAnimationEffect);
- delete2(mCastingEffect);
- mBadgesCount = 0;
- delete2(mChat);
- removeHorse();
-
- removeAllItemsParticles();
- mSpiritParticles.clear();
-}
-
-void Being::createSpeechBubble() restrict2
-{
- CREATEWIDGETV0(mSpeechBubble, SpeechBubble);
-}
-
-void Being::setSubtype(const BeingTypeId subtype,
- const uint16_t look) restrict2
-{
- if (mInfo == nullptr)
- return;
-
- if (subtype == mSubType && mLook == look)
- return;
-
- mSubType = subtype;
- mLook = look;
-
- switch (mType)
- {
- case ActorType::Monster:
- mInfo = MonsterDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_true,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Pet:
- mInfo = PETDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_true,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Mercenary:
- mInfo = MercenaryDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_true,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Homunculus:
- mInfo = HomunculusDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_true,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::SkillUnit:
- mInfo = SkillUnitDb::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_false,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Elemental:
- mInfo = ElementalDb::get(mSubType);
- if (mInfo != nullptr)
- {
- setName(mInfo->getName());
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_false,
- DisplayType::Item,
- mInfo->getColor(fromInt(mLook, ItemColor)));
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Npc:
- mInfo = NPCDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_false,
- DisplayType::Item,
- std::string());
- mYDiff = mInfo->getSortOffsetY();
- }
- break;
- case ActorType::Avatar:
- mInfo = AvatarDB::get(mSubType);
- if (mInfo != nullptr)
- {
- setupSpriteDisplay(mInfo->getDisplay(),
- ForceDisplay_false,
- DisplayType::Item,
- std::string());
- }
- break;
- case ActorType::Player:
- {
- int id = -100 - toInt(subtype, int);
- // Prevent showing errors when sprite doesn't exist
- if (!ItemDB::exists(id))
- {
- id = -100;
- // TRANSLATORS: default race name
- setRaceName(_("Human"));
- if (charServerHandler != nullptr)
- {
- setSpriteId(charServerHandler->baseSprite(),
- id);
- }
- }
- else
- {
- const ItemInfo &restrict info = ItemDB::get(id);
- setRaceName(info.getName());
- if (charServerHandler != nullptr)
- {
- setSpriteColor(charServerHandler->baseSprite(),
- id,
- info.getColor(fromInt(mLook, ItemColor)));
- }
- }
- break;
- }
- case ActorType::Portal:
- break;
- case ActorType::Unknown:
- case ActorType::FloorItem:
- default:
- reportAlways("Wrong being type %d in setSubType",
- CAST_S32(mType));
- break;
- }
-}
-
-TargetCursorSizeT Being::getTargetCursorSize() const restrict2
-{
- if (mInfo == nullptr)
- return TargetCursorSize::SMALL;
-
- return mInfo->getTargetCursorSize();
-}
-
-void Being::setPixelPositionF(const Vector &restrict pos) restrict2
-{
- Actor::setPixelPositionF(pos);
-
- updateCoords();
-
- if (mText != nullptr)
- {
- mText->adviseXY(CAST_S32(pos.x),
- CAST_S32(pos.y) - getHeight() - mText->getHeight() - 9,
- mMoveNames);
- }
-}
-
-void Being::setDestination(const int dstX,
- const int dstY) restrict2
-{
- if (mMap == nullptr)
- return;
-
- setPath(mMap->findPath(mX, mY, dstX, dstY, getBlockWalkMask()));
-}
-
-void Being::clearPath() restrict2
-{
- mPath.clear();
-}
-
-void Being::setPath(const Path &restrict path) restrict2
-{
- mPath = path;
- if (mPath.empty())
- return;
-
- if (mAction != BeingAction::MOVE && mAction != BeingAction::DEAD)
- {
- nextTile();
- mActionTime = tick_time;
- }
-}
-
-void Being::setSpeech(const std::string &restrict text,
- const std::string &restrict channel,
- int time) restrict2
-{
- if (userPalette == nullptr)
- return;
-
- if (!channel.empty() &&
- ((langChatTab == nullptr) || langChatTab->getChannelName() != channel))
- {
- return;
- }
-
- // Remove colors
- mSpeech = removeColors(text);
-
- // Trim whitespace
- trim(mSpeech);
-
- const unsigned int lineLim = mConfLineLim;
- if (lineLim > 0 && mSpeech.length() > lineLim)
- mSpeech = mSpeech.substr(0, lineLim);
-
- trim(mSpeech);
- if (mSpeech.empty())
- return;
-
- if (time == 0)
- {
- const size_t sz = mSpeech.size();
- if (sz < 200)
- time = CAST_S32(SPEECH_TIME - 300 + (3 * sz));
- }
-
- if (time < CAST_S32(SPEECH_MIN_TIME))
- time = CAST_S32(SPEECH_MIN_TIME);
-
- // Check for links
- size_t start = mSpeech.find('[');
- size_t e = mSpeech.find(']', start);
-
- while (start != std::string::npos && e != std::string::npos)
- {
- // Catch multiple embeds and ignore them so it doesn't crash the client.
- while ((mSpeech.find('[', start + 1) != std::string::npos) &&
- (mSpeech.find('[', start + 1) < e))
- {
- start = mSpeech.find('[', start + 1);
- }
-
- size_t position = mSpeech.find('|');
- if (mSpeech[start + 1] == '@' && mSpeech[start + 2] == '@')
- {
- mSpeech.erase(e, 1);
- mSpeech.erase(start, (position - start) + 1);
- }
- position = mSpeech.find("@@");
-
- while (position != std::string::npos)
- {
- mSpeech.erase(position, 2);
- position = mSpeech.find('@');
- }
-
- start = mSpeech.find('[', start + 1);
- e = mSpeech.find(']', start);
- }
-
- if (!mSpeech.empty())
- {
- mSpeechTime = time <= CAST_S32(SPEECH_MAX_TIME)
- ? time : CAST_S32(SPEECH_MAX_TIME);
- }
-
- const int speech = mSpeechType;
- if (speech == BeingSpeech::TEXT_OVERHEAD)
- {
- delete mText;
- mText = nullptr;
- mText = new Text(mSpeech,
- mPixelX,
- mPixelY - getHeight(),
- Graphics::CENTER,
- &userPalette->getColor(UserColorId::PARTICLE),
- Speech_true);
- mText->adviseXY(mPixelX,
- (mY + 1) * mapTileSize - getHeight() - mText->getHeight() - 9,
- mMoveNames);
- }
- else
- {
- const bool isShowName = (speech == BeingSpeech::NAME_IN_BUBBLE);
- if (mSpeechBubble == nullptr)
- createSpeechBubble();
- if (mSpeechBubble != nullptr)
- {
- mSpeechBubble->setCaption(isShowName ? mName : "");
- mSpeechBubble->setText(mSpeech, isShowName);
- }
- }
-}
-
-void Being::takeDamage(Being *restrict const attacker,
- const int amount,
- const AttackTypeT type,
- const int attackId,
- const int level) restrict2
-{
- if (userPalette == nullptr || attacker == nullptr)
- return;
-
- BLOCK_START("Being::takeDamage1")
-
- Font *font = nullptr;
- const Color *color;
-
- if (gui != nullptr)
- font = gui->getInfoParticleFont();
-
- // Selecting the right color
- if (type == AttackType::CRITICAL || type == AttackType::FLEE)
- {
- if (type == AttackType::CRITICAL)
- attacker->setCriticalHit(amount);
-
- if (attacker == localPlayer)
- {
- color = &userPalette->getColor(
- UserColorId::HIT_LOCAL_PLAYER_CRITICAL);
- }
- else
- {
- color = &userPalette->getColor(UserColorId::HIT_CRITICAL);
- }
- }
- else if (amount == 0)
- {
- if (attacker == localPlayer)
- {
- // This is intended to be the wrong direction to visually
- // differentiate between hits and misses
- color = &userPalette->getColor(UserColorId::HIT_LOCAL_PLAYER_MISS);
- }
- else
- {
- color = &userPalette->getColor(UserColorId::MISS);
- }
- }
- else if (mType == ActorType::Monster ||
- mType == ActorType::Mercenary ||
- mType == ActorType::Pet ||
- mType == ActorType::Homunculus ||
- mType == ActorType::SkillUnit)
- {
- if (attacker == localPlayer)
- {
- color = &userPalette->getColor(
- UserColorId::HIT_LOCAL_PLAYER_MONSTER);
- }
- else
- {
- color = &userPalette->getColor(
- UserColorId::HIT_PLAYER_MONSTER);
- }
- }
- else if (mType == ActorType::Player &&
- attacker != localPlayer &&
- this == localPlayer)
- {
- // here player was attacked by other player. mark him as enemy.
- color = &userPalette->getColor(UserColorId::HIT_PLAYER_PLAYER);
- attacker->setEnemy(true);
- attacker->updateColors();
- }
- else
- {
- color = &userPalette->getColor(UserColorId::HIT_MONSTER_PLAYER);
- }
-
- if (chatWindow != nullptr && mShowBattleEvents)
- {
- if (this == localPlayer)
- {
- if (attacker->mType == ActorType::Player || (amount != 0))
- {
- ChatWindow::battleChatLog(strprintf("%s : Hit you -%d",
- attacker->getName().c_str(), amount),
- ChatMsgType::BY_OTHER);
- }
- }
- else if (attacker == localPlayer && (amount != 0))
- {
- ChatWindow::battleChatLog(strprintf("%s : You hit %s -%d",
- attacker->mName.c_str(),
- mName.c_str(),
- amount),
- ChatMsgType::BY_PLAYER);
- }
- }
- if (font != nullptr && particleEngine != nullptr)
- {
- const std::string damage = amount != 0 ? toString(amount) :
- // TRANSLATORS: dodge or miss message in attacks
- type == AttackType::FLEE ? _("dodge") : _("miss");
- // Show damage number
- particleEngine->addTextSplashEffect(damage,
- mPixelX,
- mPixelY - 16,
- color,
- font,
- true);
- }
- BLOCK_END("Being::takeDamage1")
- BLOCK_START("Being::takeDamage2")
-
- if (type != AttackType::SKILL)
- attacker->updateHit(amount);
-
- if (amount > 0)
- {
- if ((localPlayer != nullptr) && localPlayer == this)
- localPlayer->setLastHitFrom(attacker->mName);
-
- mDamageTaken += amount;
- if (mInfo != nullptr)
- {
- playSfx(mInfo->getSound(ItemSoundEvent::HURT),
- this,
- false,
- mX,
- mY);
-
- if (!mInfo->isStaticMaxHP())
- {
- if ((mHP == 0) && mInfo->getMaxHP() < mDamageTaken)
- mInfo->setMaxHP(mDamageTaken);
- }
- }
- if ((mHP != 0) && isAlive())
- {
- mHP -= amount;
- if (mHP < 0)
- mHP = 0;
- }
-
- if (mType == ActorType::Monster)
- {
- updatePercentHP();
- updateName();
- }
- else if (mType == ActorType::Player &&
- (socialWindow != nullptr) &&
- !mName.empty())
- {
- socialWindow->updateAvatar(mName);
- }
-
- if (effectManager != nullptr)
- {
- const int hitEffectId = getHitEffect(attacker,
- type,
- attackId,
- level);
- if (hitEffectId >= 0)
- effectManager->trigger(hitEffectId, this);
- }
- }
- else
- {
- if (effectManager != nullptr)
- {
- int hitEffectId = -1;
- if (type == AttackType::SKILL)
- {
- hitEffectId = getHitEffect(attacker,
- AttackType::SKILLMISS,
- attackId,
- level);
- }
- else
- {
- hitEffectId = getHitEffect(attacker,
- AttackType::MISS,
- attackId,
- level);
- }
- if (hitEffectId >= 0)
- effectManager->trigger(hitEffectId, this);
- }
- }
- BLOCK_END("Being::takeDamage2")
-}
-
-int Being::getHitEffect(const Being *restrict const attacker,
- const AttackTypeT type,
- const int attackId,
- const int level) const restrict2
-{
- if (effectManager == nullptr)
- return 0;
-
- BLOCK_START("Being::getHitEffect")
- // Init the particle effect path based on current
- // weapon or default.
- int hitEffectId = 0;
- if (type == AttackType::SKILL || type == AttackType::SKILLMISS)
- {
- const SkillData *restrict const data =
- skillDialog->getSkillDataByLevel(attackId, level);
- if (data == nullptr)
- return -1;
- if (type == AttackType::SKILL)
- {
- hitEffectId = data->hitEffectId;
- if (hitEffectId == -1)
- hitEffectId = paths.getIntValue("skillHitEffectId");
- }
- else
- {
- hitEffectId = data->missEffectId;
- if (hitEffectId == -1)
- hitEffectId = paths.getIntValue("skillMissEffectId");
- }
- }
- else
- {
- if (attacker != nullptr)
- {
- const ItemInfo *restrict const attackerWeapon
- = attacker->getEquippedWeapon();
- if (attackerWeapon != nullptr &&
- attacker->getType() == ActorType::Player)
- {
- if (type == AttackType::MISS)
- hitEffectId = attackerWeapon->getMissEffectId();
- else if (type != AttackType::CRITICAL)
- hitEffectId = attackerWeapon->getHitEffectId();
- else
- hitEffectId = attackerWeapon->getCriticalHitEffectId();
- }
- else if (attacker->getType() == ActorType::Monster)
- {
- const BeingInfo *restrict const info = attacker->getInfo();
- if (info != nullptr)
- {
- const Attack *restrict const atk =
- info->getAttack(attackId);
- if (atk != nullptr)
- {
- if (type == AttackType::MISS)
- hitEffectId = atk->mMissEffectId;
- else if (type != AttackType::CRITICAL)
- hitEffectId = atk->mHitEffectId;
- else
- hitEffectId = atk->mCriticalHitEffectId;
- }
- else
- {
- hitEffectId = getDefaultEffectId(type);
- }
- }
- }
- else
- {
- hitEffectId = getDefaultEffectId(type);
- }
- }
- else
- {
- hitEffectId = getDefaultEffectId(type);
- }
- }
- BLOCK_END("Being::getHitEffect")
- return hitEffectId;
-}
-
-int Being::getDefaultEffectId(const AttackTypeT &restrict type)
-{
- if (type == AttackType::MISS)
- return paths.getIntValue("missEffectId");
- else if (type != AttackType::CRITICAL)
- return paths.getIntValue("hitEffectId");
- else
- return paths.getIntValue("criticalHitEffectId");
-}
-
-void Being::handleAttack(Being *restrict const victim,
- const int damage,
- const int attackId) restrict2
-{
- if ((victim == nullptr) || (mInfo == nullptr))
- return;
-
- BLOCK_START("Being::handleAttack")
-
- if (this != localPlayer)
- setAction(BeingAction::ATTACK, attackId);
-
- mLastAttackX = victim->mX;
- mLastAttackY = victim->mY;
-
- if (mType == ActorType::Player && (mEquippedWeapon != nullptr))
- fireMissile(victim, mEquippedWeapon->getMissileConst());
- else if (mInfo->getAttack(attackId) != nullptr)
- fireMissile(victim, mInfo->getAttack(attackId)->mMissile);
-
- reset();
- mActionTime = tick_time;
-
- if (Net::getNetworkType() == ServerType::TMWATHENA &&
- this != localPlayer)
- {
- const uint8_t dir = calcDirection(victim->mX,
- victim->mY);
- if (dir != 0u)
- setDirection(dir);
- }
-
- if ((damage != 0) && victim->mType == ActorType::Player
- && victim->mAction == BeingAction::SIT)
- {
- victim->setAction(BeingAction::STAND, 0);
- }
-
- if (mType == ActorType::Player)
- {
- if (mSlots.size() >= 10)
- {
- // here 10 is weapon slot
- int weaponId = mSlots[10].spriteId;
- if (weaponId == 0)
- weaponId = -100 - toInt(mSubType, int);
- const ItemInfo &info = ItemDB::get(weaponId);
- playSfx(info.getSound(
- (damage > 0) ? ItemSoundEvent::HIT : ItemSoundEvent::MISS),
- victim,
- true,
- mX, mY);
- }
- }
- else
- {
- playSfx(mInfo->getSound((damage > 0) ?
- ItemSoundEvent::HIT : ItemSoundEvent::MISS), victim, true, mX, mY);
- }
- BLOCK_END("Being::handleAttack")
-}
-
-void Being::handleSkillCasting(Being *restrict const victim,
- const int skillId,
- const int skillLevel) restrict2
-{
- if ((victim == nullptr) || (mInfo == nullptr) || (skillDialog == nullptr))
- return;
-
- setAction(BeingAction::CAST, skillId);
-
- const SkillData *restrict const data = skillDialog->getSkillDataByLevel(
- skillId,
- skillLevel);
-
- if (data != nullptr)
- {
- effectManager->triggerDefault(data->castingSrcEffectId,
- this,
- paths.getIntValue("skillCastingSrcEffectId"));
- effectManager->triggerDefault(data->castingDstEffectId,
- victim,
- paths.getIntValue("skillCastingDstEffectId"));
- fireMissile(victim, data->castingMissile);
- }
-}
-
-void Being::handleSkill(Being *restrict const victim,
- const int damage,
- const int skillId,
- const int skillLevel) restrict2
-{
- if ((victim == nullptr) || (mInfo == nullptr) || (skillDialog == nullptr))
- return;
-
- const SkillInfo *restrict const skill = skillDialog->getSkill(skillId);
- const SkillData *restrict const data = skill != nullptr
- ? skill->getData1(skillLevel) : nullptr;
- if (data != nullptr)
- {
- effectManager->triggerDefault(data->srcEffectId,
- this,
- paths.getIntValue("skillSrcEffectId"));
- effectManager->triggerDefault(data->dstEffectId,
- victim,
- paths.getIntValue("skillDstEffectId"));
- fireMissile(victim, data->missile);
- }
-
- if (this != localPlayer && (skill != nullptr))
- {
- const SkillType::SkillType type = skill->type;
- if ((type & SkillType::Attack) != 0 ||
- (type & SkillType::Ground) != 0)
- {
- setAction(BeingAction::ATTACK, 1);
- }
- else
- {
- setAction(BeingAction::STAND, 1);
- }
- }
-
- reset();
- mActionTime = tick_time;
-
- if (Net::getNetworkType() == ServerType::TMWATHENA &&
- this != localPlayer)
- {
- const uint8_t dir = calcDirection(victim->mX,
- victim->mY);
- if (dir != 0u)
- setDirection(dir);
- }
- if ((damage != 0) && victim->mType == ActorType::Player
- && victim->mAction == BeingAction::SIT)
- {
- victim->setAction(BeingAction::STAND, 0);
- }
- if (data != nullptr)
- {
- if (damage > 0)
- playSfx(data->soundHit, victim, true, mX, mY);
- else
- playSfx(data->soundMiss, victim, true, mX, mY);
- }
- else
- {
- playSfx(mInfo->getSound((damage > 0) ?
- ItemSoundEvent::HIT : ItemSoundEvent::MISS),
- victim,
- true,
- mX, mY);
- }
-}
-
-void Being::showNameBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Name]);
- if (show &&
- !mName.empty() &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = BadgesDB::getNameBadge(mName);
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Name] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
-}
-
-void Being::setName(const std::string &restrict name) restrict2
-{
- mExtName = name;
- if (mType == ActorType::Npc)
- {
- mName = name.substr(0, name.find('#', 0));
- showName();
- }
- else if (mType == ActorType::Player)
- {
- if (mName != name)
- {
- mName = name;
- showNameBadge(!mName.empty());
- }
- if (getShowName())
- showName();
- }
- else
- {
- if (mType == ActorType::Portal)
- mName = name.substr(0, name.find('#', 0));
- else
- mName = name;
-
- if (getShowName())
- showName();
- }
-}
-
-void Being::setShowName(const bool doShowName) restrict2
-{
- if (mShowName == doShowName)
- return;
-
- mShowName = doShowName;
-
- if (doShowName)
- showName();
- else
- delete2(mDispName)
-}
-
-void Being::showGuildBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Guild]);
- if (show &&
- !mGuildName.empty() &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = BadgesDB::getGuildBadge(mGuildName);
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Guild] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
-}
-
-void Being::setGuildName(const std::string &restrict name) restrict2
-{
- if (mGuildName != name)
- {
- mGuildName = name;
- showGuildBadge(!mGuildName.empty());
- updateBadgesCount();
- }
-}
-
-void Being::setGuildPos(const std::string &restrict pos A_UNUSED) restrict2
-{
-}
-
-void Being::addGuild(Guild *restrict const guild) restrict2
-{
- if (guild == nullptr)
- return;
-
- mGuilds[guild->getId()] = guild;
-
- if (this == localPlayer && (socialWindow != nullptr))
- socialWindow->addTab(guild);
-}
-
-void Being::removeGuild(const int id) restrict2
-{
- if (this == localPlayer && (socialWindow != nullptr))
- socialWindow->removeTab(mGuilds[id]);
-
- if (mGuilds[id] != nullptr)
- mGuilds[id]->removeMember(mName);
- mGuilds.erase(id);
-}
-
-const Guild *Being::getGuild(const std::string &restrict guildName) const
- restrict2
-{
- FOR_EACH (GuildsMapCIter, itr, mGuilds)
- {
- const Guild *restrict const guild = itr->second;
- if ((guild != nullptr) && guild->getName() == guildName)
- return guild;
- }
-
- return nullptr;
-}
-
-const Guild *Being::getGuild(const int id) const restrict2
-{
- const std::map<int, Guild*>::const_iterator itr = mGuilds.find(id);
- if (itr != mGuilds.end())
- return itr->second;
-
- return nullptr;
-}
-
-Guild *Being::getGuild() const restrict2
-{
- const std::map<int, Guild*>::const_iterator itr = mGuilds.begin();
- if (itr != mGuilds.end())
- return itr->second;
-
- return nullptr;
-}
-
-void Being::clearGuilds() restrict2
-{
- FOR_EACH (GuildsMapCIter, itr, mGuilds)
- {
- Guild *const guild = itr->second;
-
- if (guild != nullptr)
- {
- if (this == localPlayer && (socialWindow != nullptr))
- socialWindow->removeTab(guild);
-
- guild->removeMember(mId);
- }
- }
-
- mGuilds.clear();
-}
-
-void Being::setParty(Party *restrict const party) restrict2
-{
- if (party == mParty)
- return;
-
- Party *const old = mParty;
- mParty = party;
-
- if (old != nullptr)
- old->removeMember(mId);
-
- if (party != nullptr)
- party->addMember(mId, mName);
-
- updateColors();
-
- if (this == localPlayer && (socialWindow != nullptr))
- {
- if (old != nullptr)
- socialWindow->removeTab(old);
-
- if (party != nullptr)
- socialWindow->addTab(party);
- }
-}
-
-void Being::updateGuild() restrict2
-{
- if (localPlayer == nullptr)
- return;
-
- Guild *restrict const guild = localPlayer->getGuild();
- if (guild == nullptr)
- {
- clearGuilds();
- updateColors();
- return;
- }
- if (guild->getMember(mName) != nullptr)
- {
- setGuild(guild);
- if (!guild->getName().empty())
- setGuildName(guild->getName());
- }
- updateColors();
-}
-
-void Being::setGuild(Guild *restrict const guild) restrict2
-{
- Guild *restrict const old = getGuild();
- if (guild == old)
- return;
-
- clearGuilds();
- addGuild(guild);
-
- if (old != nullptr)
- old->removeMember(mName);
-
- updateColors();
-
- if (this == localPlayer && (socialWindow != nullptr))
- {
- if (old != nullptr)
- socialWindow->removeTab(old);
-
- if (guild != nullptr)
- socialWindow->addTab(guild);
- }
-}
-
-void Being::fireMissile(Being *restrict const victim,
- const MissileInfo &restrict missile) const restrict2
-{
- BLOCK_START("Being::fireMissile")
-
- if (victim == nullptr ||
- missile.particle.empty() ||
- particleEngine == nullptr)
- {
- BLOCK_END("Being::fireMissile")
- return;
- }
-
- Particle *restrict const target = particleEngine->createChild();
-
- if (target == nullptr)
- {
- BLOCK_END("Being::fireMissile")
- return;
- }
-
- Particle *restrict const missileParticle = target->addEffect(
- missile.particle,
- mPixelX,
- mPixelY);
-
- target->moveBy(Vector(0.0F, 0.0F, missile.z));
- target->setLifetime(missile.lifeTime);
- victim->controlAutoParticle(target);
-
- if (missileParticle != nullptr)
- {
- missileParticle->setDestination(target, missile.speed, 0.0F);
- missileParticle->setDieDistance(missile.dieDistance);
- missileParticle->setLifetime(missile.lifeTime);
- }
- BLOCK_END("Being::fireMissile")
-}
-
-std::string Being::getSitAction() const restrict2
-{
- if (mHorseId != 0)
- return SpriteAction::SITRIDE;
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if ((mask & BlockMask::GROUNDTOP) != 0)
- return SpriteAction::SITTOP;
- else if ((mask & BlockMask::AIR) != 0)
- return SpriteAction::SITSKY;
- else if ((mask & BlockMask::WATER) != 0)
- return SpriteAction::SITWATER;
- }
- return SpriteAction::SIT;
-}
-
-
-std::string Being::getMoveAction() const restrict2
-{
- if (mHorseId != 0)
- return SpriteAction::RIDE;
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if ((mask & BlockMask::AIR) != 0)
- return SpriteAction::FLY;
- else if ((mask & BlockMask::WATER) != 0)
- return SpriteAction::SWIM;
- }
- return SpriteAction::MOVE;
-}
-
-std::string Being::getWeaponAttackAction(const ItemInfo *restrict const weapon)
- const restrict2
-{
- if (weapon == nullptr)
- return getAttackAction();
-
- if (mHorseId != 0)
- return weapon->getRideAttackAction();
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if ((mask & BlockMask::AIR) != 0)
- return weapon->getSkyAttackAction();
- else if ((mask & BlockMask::WATER) != 0)
- return weapon->getWaterAttackAction();
- }
- return weapon->getAttackAction();
-}
-
-std::string Being::getAttackAction(const Attack *restrict const attack1) const
- restrict2
-{
- if (attack1 == nullptr)
- return getAttackAction();
-
- if (mHorseId != 0)
- return attack1->mRideAction;
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if ((mask & BlockMask::AIR) != 0)
- return attack1->mSkyAction;
- else if ((mask & BlockMask::WATER) != 0)
- return attack1->mWaterAction;
- }
- return attack1->mAction;
-}
-
-std::string Being::getCastAction(const SkillInfo *restrict const skill) const
- restrict2
-{
- if (skill == nullptr)
- return getCastAction();
-
- if (mHorseId != 0)
- return skill->castingRideAction;
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if ((mask & BlockMask::AIR) != 0)
- return skill->castingSkyAction;
- else if ((mask & BlockMask::WATER) != 0)
- return skill->castingWaterAction;
- }
- return skill->castingAction;
-}
-
-#define getSpriteAction(func, action) \
- std::string Being::get##func##Action() const restrict2\
-{ \
- if (mHorseId != 0) \
- return SpriteAction::action##RIDE; \
- if (mMap) \
- { \
- const unsigned char mask = mMap->getBlockMask(mX, mY); \
- if (mask & BlockMask::AIR) \
- return SpriteAction::action##SKY; \
- else if (mask & BlockMask::WATER) \
- return SpriteAction::action##WATER; \
- } \
- return SpriteAction::action; \
-}
-
-getSpriteAction(Attack, ATTACK)
-getSpriteAction(Cast, CAST)
-getSpriteAction(Dead, DEAD)
-getSpriteAction(Spawn, SPAWN)
-
-std::string Being::getStandAction() const restrict2
-{
- if (mHorseId != 0)
- return SpriteAction::STANDRIDE;
- if (mMap != nullptr)
- {
- const unsigned char mask = mMap->getBlockMask(mX, mY);
- if (mTrickDead)
- {
- if ((mask & BlockMask::AIR) != 0)
- return SpriteAction::DEADSKY;
- else if ((mask & BlockMask::WATER) != 0)
- return SpriteAction::DEADWATER;
- else
- return SpriteAction::DEAD;
- }
- if ((mask & BlockMask::AIR) != 0)
- return SpriteAction::STANDSKY;
- else if ((mask & BlockMask::WATER) != 0)
- return SpriteAction::STANDWATER;
- }
- return SpriteAction::STAND;
-}
-
-void Being::setAction(const BeingActionT &restrict action,
- const int attackId) restrict2
-{
- std::string currentAction = SpriteAction::INVALID;
-
- switch (action)
- {
- case BeingAction::MOVE:
- if (mInfo != nullptr)
- {
- playSfx(mInfo->getSound(
- ItemSoundEvent::MOVE), nullptr, true, mX, mY);
- }
- currentAction = getMoveAction();
- // Note: When adding a run action,
- // Differentiate walk and run with action name,
- // while using only the ACTION_MOVE.
- break;
- case BeingAction::SIT:
- currentAction = getSitAction();
- if (mInfo != nullptr)
- {
- ItemSoundEvent::Type event;
- if (currentAction == SpriteAction::SITTOP)
- event = ItemSoundEvent::SITTOP;
- else
- event = ItemSoundEvent::SIT;
- playSfx(mInfo->getSound(event), nullptr, true, mX, mY);
- }
- break;
- case BeingAction::ATTACK:
- if (mEquippedWeapon != nullptr)
- {
- currentAction = getWeaponAttackAction(mEquippedWeapon);
- reset();
- }
- else
- {
- if (mInfo == nullptr || mInfo->getAttack(attackId) == nullptr)
- break;
-
- currentAction = getAttackAction(mInfo->getAttack(attackId));
- reset();
-
- // attack particle effect
- if (ParticleEngine::enabled && (effectManager != nullptr))
- {
- const int effectId = mInfo->getAttack(attackId)->mEffectId;
- if (effectId >= 0)
- {
- effectManager->triggerDirection(effectId,
- this,
- mSpriteDirection);
- }
- }
- }
- break;
- case BeingAction::CAST:
- if (skillDialog != nullptr)
- {
- const SkillInfo *restrict const info =
- skillDialog->getSkill(attackId);
- currentAction = getCastAction(info);
- }
- break;
- case BeingAction::HURT:
- if (mInfo != nullptr)
- {
- playSfx(mInfo->getSound(ItemSoundEvent::HURT),
- this, false, mX, mY);
- }
- break;
- case BeingAction::DEAD:
- currentAction = getDeadAction();
- if (mInfo != nullptr)
- {
- playSfx(mInfo->getSound(ItemSoundEvent::DIE),
- this,
- false,
- mX, mY);
- if (mType == ActorType::Monster ||
- mType == ActorType::Npc ||
- mType == ActorType::SkillUnit)
- {
- mYDiff = mInfo->getDeadSortOffsetY();
- }
- }
- break;
- case BeingAction::STAND:
- currentAction = getStandAction();
- break;
- case BeingAction::SPAWN:
- if (mInfo != nullptr)
- {
- playSfx(mInfo->getSound(ItemSoundEvent::SPAWN),
- nullptr, true, mX, mY);
- }
- currentAction = getSpawnAction();
- break;
- case BeingAction::PRESTAND:
- break;
- default:
- logger->log("Being::setAction unknown action: "
- + toString(CAST_U32(action)));
- break;
- }
-
- if (currentAction != SpriteAction::INVALID)
- {
- mSpriteAction = currentAction;
- play(currentAction);
- if (mEmotionSprite != nullptr)
- mEmotionSprite->play(currentAction);
- if (mAnimationEffect != nullptr)
- mAnimationEffect->play(currentAction);
- for_each_badges()
- {
- AnimatedSprite *const sprite = mBadges[f];
- if (sprite != nullptr)
- sprite->play(currentAction);
- }
- for_each_horses(mDownHorseSprites)
- (*it)->play(currentAction);
- for_each_horses(mUpHorseSprites)
- (*it)->play(currentAction);
- mAction = action;
- }
-
- if (currentAction != SpriteAction::MOVE
- && currentAction != SpriteAction::FLY
- && currentAction != SpriteAction::SWIM)
- {
- mActionTime = tick_time;
- }
-}
-
-void Being::setDirection(const uint8_t direction) restrict2
-{
- if (mDirection == direction)
- return;
-
- mDirection = direction;
-
- mDirectionDelayed = 0;
-
- // if the direction does not change much, keep the common component
- int mFaceDirection = mDirection & direction;
- if (mFaceDirection == 0)
- mFaceDirection = direction;
-
- SpriteDirection::Type dir;
- if ((mFaceDirection & BeingDirection::UP) != 0)
- {
- if ((mFaceDirection & BeingDirection::LEFT) != 0)
- dir = SpriteDirection::UPLEFT;
- else if ((mFaceDirection & BeingDirection::RIGHT) != 0)
- dir = SpriteDirection::UPRIGHT;
- else
- dir = SpriteDirection::UP;
- }
- else if ((mFaceDirection & BeingDirection::DOWN) != 0)
- {
- if ((mFaceDirection & BeingDirection::LEFT) != 0)
- dir = SpriteDirection::DOWNLEFT;
- else if ((mFaceDirection & BeingDirection::RIGHT) != 0)
- dir = SpriteDirection::DOWNRIGHT;
- else
- dir = SpriteDirection::DOWN;
- }
- else if ((mFaceDirection & BeingDirection::RIGHT) != 0)
- {
- dir = SpriteDirection::RIGHT;
- }
- else
- {
- dir = SpriteDirection::LEFT;
- }
- mSpriteDirection = dir;
-
- CompoundSprite::setSpriteDirection(dir);
- if (mEmotionSprite != nullptr)
- mEmotionSprite->setSpriteDirection(dir);
- if (mAnimationEffect != nullptr)
- mAnimationEffect->setSpriteDirection(dir);
-
- for_each_badges()
- {
- AnimatedSprite *const sprite = mBadges[f];
- if (sprite != nullptr)
- sprite->setSpriteDirection(dir);
- }
-
- for_each_horses(mDownHorseSprites)
- (*it)->setSpriteDirection(dir);
- for_each_horses(mUpHorseSprites)
- (*it)->setSpriteDirection(dir);
- recalcSpritesOrder();
-}
-
-uint8_t Being::calcDirection() const restrict2
-{
- uint8_t dir = 0;
- if (mDest.x > mX)
- dir |= BeingDirection::RIGHT;
- else if (mDest.x < mX)
- dir |= BeingDirection::LEFT;
- if (mDest.y > mY)
- dir |= BeingDirection::DOWN;
- else if (mDest.y < mY)
- dir |= BeingDirection::UP;
- return dir;
-}
-
-uint8_t Being::calcDirection(const int dstX,
- const int dstY) const restrict2
-{
- uint8_t dir = 0;
- if (dstX > mX)
- dir |= BeingDirection::RIGHT;
- else if (dstX < mX)
- dir |= BeingDirection::LEFT;
- if (dstY > mY)
- dir |= BeingDirection::DOWN;
- else if (dstY < mY)
- dir |= BeingDirection::UP;
- return dir;
-}
-
-void Being::nextTile() restrict2
-{
- if (mPath.empty())
- {
- mAction = BeingAction::PRESTAND;
- mPreStandTime = tick_time;
- return;
- }
-
- const Position pos = mPath.front();
- mPath.pop_front();
-
- const uint8_t dir = calcDirection(pos.x, pos.y);
- if (dir != 0u)
- setDirection(dir);
-
- if (mMap == nullptr ||
- !mMap->getWalk(pos.x, pos.y, getBlockWalkMask()))
- {
- setAction(BeingAction::STAND, 0);
- return;
- }
-
- mActionTime += mSpeed / 10;
- if ((mType != ActorType::Player || mUseDiagonal)
- && mX != pos.x && mY != pos.y)
- {
- mSpeed = mWalkSpeed * 14 / 10;
- }
- else
- {
- mSpeed = mWalkSpeed;
- }
-
- if (mX != pos.x || mY != pos.y)
- {
- mOldHeight = mMap->getHeightOffset(mX, mY);
- if (mReachable == Reachable::REACH_NO &&
- mMap->getBlockMask(mX, mY) != mMap->getBlockMask(pos.x, pos.y))
- {
- mReachable = Reachable::REACH_UNKNOWN;
- }
- }
- mX = pos.x;
- mY = pos.y;
- const uint8_t height = mMap->getHeightOffset(mX, mY);
- mPixelOffsetY = height - mOldHeight;
- mFixedOffsetY = height;
- mNeedPosUpdate = true;
- setAction(BeingAction::MOVE, 0);
-}
-
-void Being::logic() restrict2
-{
- BLOCK_START("Being::logic")
- if (A_UNLIKELY(mSpeechTime != 0))
- {
- mSpeechTime--;
- if (mSpeechTime == 0 && mText != nullptr)
- delete2(mText)
- }
-
- if (A_UNLIKELY(mOwner != nullptr))
- {
- if (mType == ActorType::Homunculus ||
- mType == ActorType::Mercenary)
- {
- botLogic();
- }
- }
-
- const int time = tick_time * MILLISECONDS_IN_A_TICK;
- if (mEmotionSprite != nullptr)
- mEmotionSprite->update(time);
- for_each_horses(mDownHorseSprites)
- (*it)->update(time);
- for_each_horses(mUpHorseSprites)
- (*it)->update(time);
-
- if (A_UNLIKELY(mCastEndTime != 0 && mCastEndTime < tick_time))
- {
- mCastEndTime = 0;
- delete2(mCastingEffect);
- }
-
- if (A_UNLIKELY(mAnimationEffect))
- {
- mAnimationEffect->update(time);
- if (mAnimationEffect->isTerminated())
- delete2(mAnimationEffect)
- }
- if (A_UNLIKELY(mCastingEffect))
- {
- mCastingEffect->update(time);
- if (mCastingEffect->isTerminated())
- delete2(mCastingEffect)
- }
- for_each_badges()
- {
- AnimatedSprite *restrict const sprite = mBadges[f];
- if (sprite != nullptr)
- sprite->update(time);
- }
-
- int frameCount = CAST_S32(getFrameCount());
-
- switch (mAction)
- {
- case BeingAction::STAND:
- case BeingAction::SIT:
- case BeingAction::DEAD:
- case BeingAction::HURT:
- case BeingAction::SPAWN:
- case BeingAction::CAST:
- default:
- break;
-
- case BeingAction::MOVE:
- {
- if (get_elapsed_time(mActionTime) >= mSpeed)
- nextTile();
- break;
- }
-
- case BeingAction::ATTACK:
- {
- if (mActionTime == 0)
- break;
-
- int curFrame = 0;
- if (mAttackSpeed != 0)
- {
- curFrame = (get_elapsed_time(mActionTime) * frameCount)
- / mAttackSpeed;
- }
-
- if (this == localPlayer && curFrame >= frameCount)
- nextTile();
-
- break;
- }
-
- case BeingAction::PRESTAND:
- {
- if (get_elapsed_time1(mPreStandTime) > 10)
- setAction(BeingAction::STAND, 0);
- break;
- }
- }
-
- if (mAction == BeingAction::MOVE || mNeedPosUpdate)
- {
- const int xOffset = getOffset<BeingDirection::LEFT,
- BeingDirection::RIGHT>();
- const int yOffset = getOffset<BeingDirection::UP,
- BeingDirection::DOWN>();
- int offset = xOffset;
- if (offset == 0)
- offset = yOffset;
-
- if ((xOffset == 0) && (yOffset == 0))
- mNeedPosUpdate = false;
-
- const int halfTile = mapTileSize / 2;
- const float offset2 = static_cast<float>(
- mPixelOffsetY * abs(offset)) / 2;
-// mSortOffsetY = (mOldHeight - mFixedOffsetY + mPixelOffsetY)
-// * halfTile - offset2;
- mSortOffsetY = 0;
- const float yOffset3 = (mY + 1) * mapTileSize + yOffset
- - (mOldHeight + mPixelOffsetY) * halfTile + offset2;
-
- // Update pixel coordinates
- setPixelPositionF(static_cast<float>(mX * mapTileSize
- + mapTileSize / 2 + xOffset), yOffset3);
- }
-
- if (A_UNLIKELY(mEmotionSprite))
- {
- mEmotionTime--;
- if (mEmotionTime == 0)
- delete2(mEmotionSprite)
- }
-
- ActorSprite::logic();
-
- if (frameCount < 10)
- frameCount = 10;
-
- if (A_UNLIKELY(!isAlive() &&
- mSpeed != 0 &&
- gameHandler->removeDeadBeings() &&
- get_elapsed_time(mActionTime) / mSpeed >= frameCount))
- {
- if (mType != ActorType::Player && (actorManager != nullptr))
- actorManager->destroy(this);
- }
-
- const SoundInfo *restrict const sound = mNextSound.sound;
- if (A_UNLIKELY(sound))
- {
- const int time2 = tick_time;
- if (time2 > mNextSound.time)
- {
- soundManager.playSfx(sound->sound, mNextSound.x, mNextSound.y);
-
- mNextSound.sound = nullptr;
- mNextSound.time = time2 + sound->delay;
- }
- }
-
- BLOCK_END("Being::logic")
-}
-
-void Being::botLogic() restrict2
-{
- if ((mOwner == nullptr) || (mMap == nullptr) || (mInfo == nullptr))
- return;
-
- const int time = tick_time;
- const int thinkTime = mInfo->getThinkTime();
- if (abs(CAST_S32(mMoveTime) - time) < thinkTime)
- return;
-
- mMoveTime = time;
-
- int dstX = mOwner->mX;
- int dstY = mOwner->mY;
- const int warpDist = mInfo->getWarpDist();
- const int divX = abs(dstX - mX);
- const int divY = abs(dstY - mY);
-
- if (divX >= warpDist || divY >= warpDist)
- {
- if (mType == ActorType::Homunculus)
- homunculusHandler->moveToMaster();
- else
- mercenaryHandler->moveToMaster();
- mBotAi = true;
- return;
- }
- if (!mBotAi)
- return;
- if (mAction == BeingAction::MOVE)
- {
- if (mOwner->mAction == BeingAction::MOVE)
- {
- updateBotFollow(dstX, dstY,
- divX, divY);
- }
- return;
- }
-
- switch (mOwner->mAction)
- {
- case BeingAction::MOVE:
- case BeingAction::PRESTAND:
- updateBotFollow(dstX, dstY,
- divX, divY);
- break;
- case BeingAction::STAND:
- case BeingAction::SPAWN:
- botFixOffset(dstX, dstY);
- moveBotTo(dstX, dstY);
- break;
- case BeingAction::ATTACK:
- {
- const Being *const target = localPlayer->getTarget();
- if (target == nullptr)
- return;
- const BeingId targetId = target->getId();
- if (mType == ActorType::Homunculus)
- {
- homunculusHandler->attack(targetId,
- Keep_true);
- }
- else
- {
- mercenaryHandler->attack(targetId,
- Keep_true);
- }
- break;
- }
- case BeingAction::SIT:
- botFixOffset(dstX, dstY);
- moveBotTo(dstX, dstY);
- break;
- case BeingAction::DEAD:
- botFixOffset(dstX, dstY);
- moveBotTo(dstX, dstY);
- break;
- case BeingAction::CAST:
- case BeingAction::HURT:
- default:
- break;
- }
-}
-
-void Being::botFixOffset(int &restrict dstX,
- int &restrict dstY) const
-{
- if ((mInfo == nullptr) || (mOwner == nullptr))
- return;
-
- int offsetX1;
- int offsetY1;
- switch (mOwner->getCurrentAction())
- {
- case BeingAction::SIT:
- offsetX1 = mInfo->getSitOffsetX();
- offsetY1 = mInfo->getSitOffsetY();
- break;
-
- case BeingAction::MOVE:
- offsetX1 = mInfo->getMoveOffsetX();
- offsetY1 = mInfo->getMoveOffsetY();
- break;
-
- case BeingAction::DEAD:
- offsetX1 = mInfo->getDeadOffsetX();
- offsetY1 = mInfo->getDeadOffsetY();
- break;
-
- case BeingAction::ATTACK:
- offsetX1 = mInfo->getAttackOffsetX();
- offsetY1 = mInfo->getAttackOffsetY();
- break;
-
- case BeingAction::SPAWN:
- case BeingAction::HURT:
- case BeingAction::STAND:
- case BeingAction::PRESTAND:
- case BeingAction::CAST:
- default:
- offsetX1 = mInfo->getTargetOffsetX();
- offsetY1 = mInfo->getTargetOffsetY();
- break;
- }
-
- int offsetX = offsetX1;
- int offsetY = offsetY1;
- switch (mOwner->mDirection)
- {
- case BeingDirection::LEFT:
- offsetX = -offsetY1;
- offsetY = offsetX1;
- break;
- case BeingDirection::RIGHT:
- offsetX = offsetY1;
- offsetY = -offsetX1;
- break;
- case BeingDirection::UP:
- offsetY = -offsetY;
- offsetX = -offsetX;
- break;
- default:
- case BeingDirection::DOWN:
- break;
- }
- dstX += offsetX;
- dstY += offsetY;
- if (mMap != nullptr)
- {
- if (!mMap->getWalk(dstX, dstY, getBlockWalkMask()))
- {
- dstX = mOwner->mX;
- dstY = mOwner->mY;
- }
- }
-}
-
-void Being::updateBotFollow(int dstX,
- int dstY,
- const int divX,
- const int divY)
-{
- const int followDist = mInfo->getStartFollowDist();
- const int dist = mInfo->getFollowDist();
- if (divX > followDist || divY > followDist)
- {
- if (dist > 0)
- {
- if (divX > followDist)
- {
- if (dstX > mX + dist)
- dstX -= dist;
- else if (dstX + dist <= mX)
- dstX += dist;
- }
- else
- {
- dstX = mX;
- }
- if (divY > followDist)
- {
- if (dstY > mY + dist)
- dstY -= dist;
- else if (dstX + dist <= mX)
- dstY += dist;
- }
- else
- {
- dstY = mY;
- }
- }
- botFixOffset(dstX, dstY);
- moveBotTo(dstX, dstY);
- }
-}
-
-void Being::moveBotTo(int dstX,
- int dstY)
-{
- const int dstX0 = mOwner->mX;
- const int dstY0 = mOwner->mY;
- const unsigned char blockWalkMask = getBlockWalkMask();
- if (!mMap->getWalk(dstX, dstY, blockWalkMask))
- {
- if (dstX != dstX0)
- {
- dstX = dstX0;
- if (!mMap->getWalk(dstX, dstY, blockWalkMask))
- dstY = dstY0;
- }
- else if (dstY != dstY0)
- {
- dstY = dstY0;
- if (!mMap->getWalk(dstX, dstY, blockWalkMask))
- dstX = dstX0;
- }
- }
- if (mX != dstX || mY != dstY)
- {
- if (mType == ActorType::Homunculus)
- homunculusHandler->move(dstX, dstY);
- else
- mercenaryHandler->move(dstX, dstY);
- return;
- }
- updateBotDirection(dstX, dstY);
-}
-
-void Being::updateBotDirection(const int dstX,
- const int dstY)
-{
- int directionType = 0;
- switch (mOwner->getCurrentAction())
- {
- case BeingAction::STAND:
- case BeingAction::MOVE:
- case BeingAction::HURT:
- case BeingAction::SPAWN:
- case BeingAction::CAST:
- case BeingAction::PRESTAND:
- default:
- directionType = mInfo->getDirectionType();
- break;
- case BeingAction::SIT:
- directionType = mInfo->getSitDirectionType();
- break;
- case BeingAction::DEAD:
- directionType = mInfo->getDeadDirectionType();
- break;
- case BeingAction::ATTACK:
- directionType = mInfo->getAttackDirectionType();
- break;
- }
-
- uint8_t newDir = 0;
- switch (directionType)
- {
- case 0:
- default:
- return;
-
- case 1:
- newDir = mOwner->mDirection;
- break;
-
- case 2:
- {
- const int dstX0 = mOwner->mX;
- const int dstY0 = mOwner->mY;
- if (dstX > dstX0)
- newDir |= BeingDirection::LEFT;
- else if (dstX < dstX0)
- newDir |= BeingDirection::RIGHT;
- if (dstY > dstY0)
- newDir |= BeingDirection::UP;
- else if (dstY < dstY0)
- newDir |= BeingDirection::DOWN;
- break;
- }
- case 3:
- {
- const int dstX0 = mOwner->mX;
- const int dstY0 = mOwner->mY;
- if (dstX > dstX0)
- newDir |= BeingDirection::RIGHT;
- else if (dstX < dstX0)
- newDir |= BeingDirection::LEFT;
- if (dstY > dstY0)
- newDir |= BeingDirection::DOWN;
- else if (dstY < dstY0)
- newDir |= BeingDirection::UP;
- break;
- }
- case 4:
- {
- const int dstX2 = mOwner->getLastAttackX();
- const int dstY2 = mOwner->getLastAttackY();
- if (dstX > dstX2)
- newDir |= BeingDirection::LEFT;
- else if (dstX < dstX2)
- newDir |= BeingDirection::RIGHT;
- if (dstY > dstY2)
- newDir |= BeingDirection::UP;
- else if (dstY < dstY2)
- newDir |= BeingDirection::DOWN;
- break;
- }
- }
- if ((newDir != 0u) && newDir != mDirection)
- {
- if (mType == ActorType::Homunculus)
- homunculusHandler->setDirection(newDir);
- else
- mercenaryHandler->setDirection(newDir);
- }
-}
-
-void Being::updateBadgesPosition()
-{
- const int px = mPixelX - mapTileSize / 2;
- const int py = mPixelY - mapTileSize * 2 - mapTileSize;
- if (mShowBadges != BadgeDrawType::Hide &&
- mBadgesCount != 0u)
- {
- if (mDispName != nullptr &&
- gui != nullptr)
- {
- if (mShowBadges == BadgeDrawType::Right)
- {
- const Font *restrict const font = gui->getFont();
- mBadgesX = mDispName->getX() + mDispName->getWidth();
- mBadgesY = mDispName->getY() - font->getHeight();
- }
- else if (mShowBadges == BadgeDrawType::Bottom)
- {
- mBadgesX = px + 8 - mBadgesCount * 8;
- if (mVisibleNamePos == VisibleNamePos::Bottom)
- {
- mBadgesY = mDispName->getY();
- }
- else
- {
- mBadgesY = py + settings.playerNameOffset + 16;
- }
- }
- else
- {
- mBadgesX = px + 8 - mBadgesCount * 8;
- if (mVisibleNamePos == VisibleNamePos::Top)
- mBadgesY = py - mDispName->getHeight();
- else
- mBadgesY = py;
- }
- }
- else
- {
- if (mShowBadges == BadgeDrawType::Right)
- {
- mBadgesX = px + settings.playerBadgeAtRightOffset;
- mBadgesY = py;
- }
- else if (mShowBadges == BadgeDrawType::Bottom)
- {
- mBadgesX = px + 8 - mBadgesCount * 8;
- const int height = settings.playerNameOffset;
- if (mVisibleNamePos == VisibleNamePos::Bottom)
- mBadgesY = py + height;
- else
- mBadgesY = py + height + 16;
- }
- else
- {
- mBadgesX = px + 8 - mBadgesCount * 8;
- mBadgesY = py;
- }
- }
- }
-}
-
-void Being::drawEmotion(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- if (mErased)
- return;
-
- const int px = mPixelX - offsetX - mapTileSize / 2;
- const int py = mPixelY - offsetY - mapTileSize * 2 - mapTileSize;
- if (mAnimationEffect != nullptr)
- mAnimationEffect->draw(graphics, px, py);
- if (mShowBadges != BadgeDrawType::Hide &&
- mBadgesCount != 0u)
- {
- int x = mBadgesX - offsetX;
- const int y = mBadgesY - offsetY;
- for_each_badges()
- {
- const AnimatedSprite *restrict const sprite = mBadges[f];
- if (sprite != nullptr)
- {
- sprite->draw(graphics, x, y);
- x += 16;
- }
- }
- }
- if (mEmotionSprite != nullptr)
- mEmotionSprite->draw(graphics, px, py);
-}
-
-void Being::drawSpeech(const int offsetX,
- const int offsetY) restrict2
-{
- if (mErased)
- return;
- if (mSpeech.empty())
- return;
-
- const int px = mPixelX - offsetX;
- const int py = mPixelY - offsetY;
- const int speech = mSpeechType;
-
- // Draw speech above this being
- if (mSpeechTime == 0)
- {
- if (mSpeechBubble != nullptr &&
- mSpeechBubble->mVisible == Visible_true)
- {
- mSpeechBubble->setVisible(Visible_false);
- }
- mSpeech.clear();
- }
- else if (mSpeechTime > 0 && (speech == BeingSpeech::NAME_IN_BUBBLE ||
- speech == BeingSpeech::NO_NAME_IN_BUBBLE))
- {
- delete2(mText)
-
- if (mSpeechBubble != nullptr)
- {
- mSpeechBubble->setPosition(px - (mSpeechBubble->getWidth() / 2),
- py - getHeight() - (mSpeechBubble->getHeight()));
- mSpeechBubble->setVisible(Visible_true);
- mSpeechBubble->requestMoveToBackground();
- }
- }
- else if (mSpeechTime > 0 && speech == BeingSpeech::TEXT_OVERHEAD)
- {
- if (mSpeechBubble != nullptr)
- mSpeechBubble->setVisible(Visible_false);
-
- if ((mText == nullptr) && (userPalette != nullptr))
- {
- mText = new Text(mSpeech,
- mPixelX,
- mPixelY - getHeight(),
- Graphics::CENTER,
- &theme->getColor(ThemeColorId::BUBBLE_TEXT, 255),
- Speech_true);
- mText->adviseXY(mPixelX,
- (mY + 1) * mapTileSize - getHeight() - mText->getHeight() - 9,
- mMoveNames);
- }
- }
- else if (speech == BeingSpeech::NO_SPEECH)
- {
- if (mSpeechBubble != nullptr)
- mSpeechBubble->setVisible(Visible_false);
- delete2(mText)
- }
-}
-
-template<signed char pos, signed char neg>
-int Being::getOffset() const restrict2
-{
- // Check whether we're walking in the requested direction
- if (mAction != BeingAction::MOVE || !(mDirection & (pos | neg)))
- return 0;
-
- int offset = 0;
-
- if (mMap && mSpeed)
- {
- const int time = get_elapsed_time(mActionTime);
- offset = (pos == BeingDirection::LEFT &&
- neg == BeingDirection::RIGHT) ?
- (time * mMap->getTileWidth() / mSpeed)
- : (time * mMap->getTileHeight() / mSpeed);
- }
-
- // We calculate the offset _from_ the _target_ location
- offset -= mapTileSize;
- if (offset > 0)
- offset = 0;
-
- // Going into negative direction? Invert the offset.
- if (mDirection & pos)
- offset = -offset;
-
- if (offset > mapTileSize)
- offset = mapTileSize;
- if (offset < -mapTileSize)
- offset = -mapTileSize;
-
- return offset;
-}
-
-void Being::updateCoords() restrict2
-{
- if (mDispName != nullptr)
- {
- int offsetX = mPixelX;
- int offsetY = mPixelY;
- if (mInfo != nullptr)
- {
- offsetX += mInfo->getNameOffsetX();
- offsetY += mInfo->getNameOffsetY();
- }
- // Monster names show above the sprite instead of below it
- if (mType == ActorType::Monster ||
- mVisibleNamePos == VisibleNamePos::Top)
- {
- offsetY += - settings.playerNameOffset - mDispName->getHeight();
- }
- mDispName->adviseXY(offsetX, offsetY, mMoveNames);
- }
- updateBadgesPosition();
-}
-
-void Being::optionChanged(const std::string &restrict value) restrict2
-{
- if (mType == ActorType::Player && value == "visiblenames")
- {
- setShowName(config.getIntValue("visiblenames") == VisibleName::Show);
- updateBadgesPosition();
- }
-}
-
-void Being::flashName(const int time) restrict2
-{
- if (mDispName != nullptr)
- mDispName->flash(time);
-}
-
-std::string Being::getGenderSignWithSpace() const restrict2
-{
- const std::string &restrict str = getGenderSign();
- if (str.empty())
- return str;
- else
- return std::string(" ").append(str);
-}
-
-std::string Being::getGenderSign() const restrict2
-{
- std::string str;
- if (mShowGender)
- {
- if (getGender() == Gender::FEMALE)
- str = "\u2640";
- else if (getGender() == Gender::MALE)
- str = "\u2642";
- }
- if (mShowPlayersStatus &&
- mShowBadges == BadgeDrawType::Hide)
- {
- if (mShop)
- str.append("$");
- if (mAway)
- {
- // TRANSLATORS: this away status writed in player nick
- str.append(_("A"));
- }
- else if (mInactive)
- {
- // TRANSLATORS: this inactive status writed in player nick
- str.append(_("I"));
- }
- }
- return str;
-}
-
-void Being::showName() restrict2
-{
- if (mName.empty())
- return;
-
- delete2(mDispName);
-
- if (mHideErased && playerRelations.getRelation(mName) == Relation::ERASED)
- return;
-
- std::string displayName(mName);
-
- if (mType != ActorType::Monster && (mShowGender || mShowLevel))
- {
- displayName.append(" ");
- if (mShowLevel && getLevel() != 0)
- displayName.append(toString(getLevel()));
-
- displayName.append(getGenderSign());
- }
-
- if (mType == ActorType::Monster)
- {
- if (config.getBoolValue("showMonstersTakedDamage"))
- displayName.append(", ").append(toString(getDamageTaken()));
- }
-
- Font *font = nullptr;
- if ((localPlayer != nullptr) && localPlayer->getTarget() == this
- && mType != ActorType::Monster)
- {
- font = boldFont;
- }
- else if (mType == ActorType::Player
- && !playerRelations.isGoodName(this) && (gui != nullptr))
- {
- font = gui->getSecureFont();
- }
-
- if (mInfo != nullptr)
- {
- mDispName = new FlashText(displayName,
- mPixelX + mInfo->getNameOffsetX(),
- mPixelY + mInfo->getNameOffsetY(),
- Graphics::CENTER,
- mNameColor,
- font);
- }
- else
- {
- mDispName = new FlashText(displayName,
- mPixelX,
- mPixelY,
- Graphics::CENTER,
- mNameColor,
- font);
- }
-
- updateCoords();
-}
-
-void Being::setDefaultNameColor(const UserColorIdT defaultColor) restrict2
-{
- switch (mTeamId)
- {
- case 0:
- default:
- mNameColor = &userPalette->getColor(defaultColor);
- break;
- case 1:
- mNameColor = &userPalette->getColor(UserColorId::TEAM1);
- break;
- case 2:
- mNameColor = &userPalette->getColor(UserColorId::TEAM2);
- break;
- case 3:
- mNameColor = &userPalette->getColor(UserColorId::TEAM3);
- break;
- }
-}
-
-void Being::updateColors()
-{
- if (userPalette != nullptr)
- {
- if (mType == ActorType::Monster)
- {
- setDefaultNameColor(UserColorId::MONSTER);
- mTextColor = &userPalette->getColor(UserColorId::MONSTER);
- }
- else if (mType == ActorType::Npc)
- {
- setDefaultNameColor(UserColorId::NPC);
- mTextColor = &userPalette->getColor(UserColorId::NPC);
- }
- else if (mType == ActorType::Pet)
- {
- setDefaultNameColor(UserColorId::PET);
- mTextColor = &userPalette->getColor(UserColorId::PET);
- }
- else if (mType == ActorType::Homunculus)
- {
- setDefaultNameColor(UserColorId::HOMUNCULUS);
- mTextColor = &userPalette->getColor(UserColorId::HOMUNCULUS);
- }
- else if (mType == ActorType::SkillUnit)
- {
- setDefaultNameColor(UserColorId::SKILLUNIT);
- mTextColor = &userPalette->getColor(UserColorId::SKILLUNIT);
- }
- else if (this == localPlayer)
- {
- mNameColor = &userPalette->getColor(UserColorId::SELF);
- mTextColor = &theme->getColor(ThemeColorId::PLAYER, 255);
- }
- else
- {
- mTextColor = &theme->getColor(ThemeColorId::PLAYER, 255);
-
- if (playerRelations.getRelation(mName) != Relation::ERASED)
- mErased = false;
- else
- mErased = true;
-
- if (mIsGM)
- {
- mTextColor = &userPalette->getColor(UserColorId::GM);
- mNameColor = &userPalette->getColor(UserColorId::GM);
- }
- else if (mEnemy)
- {
- mNameColor = &userPalette->getColor(UserColorId::ENEMY);
- }
- else if ((mParty != nullptr) && (localPlayer != nullptr)
- && mParty == localPlayer->getParty())
- {
- mNameColor = &userPalette->getColor(UserColorId::PARTY);
- }
- else if ((localPlayer != nullptr) && (getGuild() != nullptr)
- && getGuild() == localPlayer->getGuild())
- {
- mNameColor = &userPalette->getColor(UserColorId::GUILD);
- }
- else if (playerRelations.getRelation(mName) == Relation::FRIEND)
- {
- mNameColor = &userPalette->getColor(UserColorId::FRIEND);
- }
- else if (playerRelations.getRelation(mName) ==
- Relation::DISREGARDED
- || playerRelations.getRelation(mName) ==
- Relation::BLACKLISTED)
- {
- mNameColor = &userPalette->getColor(UserColorId::DISREGARDED);
- }
- else if (playerRelations.getRelation(mName)
- == Relation::IGNORED ||
- playerRelations.getRelation(mName) == Relation::ENEMY2)
- {
- mNameColor = &userPalette->getColor(UserColorId::IGNORED);
- }
- else if (playerRelations.getRelation(mName) == Relation::ERASED)
- {
- mNameColor = &userPalette->getColor(UserColorId::ERASED);
- }
- else
- {
- setDefaultNameColor(UserColorId::PC);
- }
- }
-
- if (mDispName != nullptr)
- mDispName->setColor(mNameColor);
- }
-}
-
-void Being::updateSprite(const unsigned int slot,
- const int id,
- const std::string &restrict color) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- if ((slot != 0u) && mSlots[slot].spriteId == id)
- return;
- setSpriteColor(slot,
- id,
- color);
-}
-
-// set sprite id, reset colors, reset cards
-void Being::setSpriteId(const unsigned int slot,
- const int id) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = mSlots[slot].spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"), filename));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- addItemParticles(id, info.getDisplay());
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-
- BeingSlot &beingSlot = mSlots[slot];
- beingSlot.spriteId = id;
- beingSlot.color.clear();
- beingSlot.colorId = ItemColor_one;
- beingSlot.cardsId = CardsList(nullptr);
- recalcSpritesOrder();
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-// reset sprite id, reset colors, reset cards
-void Being::unSetSprite(const unsigned int slot) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- BeingSlot &beingSlot = mSlots[slot];
- const int id1 = beingSlot.spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
-
- beingSlot.spriteId = 0;
- beingSlot.color.clear();
- beingSlot.colorId = ItemColor_one;
- beingSlot.cardsId = CardsList(nullptr);
- recalcSpritesOrder();
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-// set sprite id, use color string, reset cards
-void Being::setSpriteColor(const unsigned int slot,
- const int id,
- const std::string &color) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- // disabled for now, because it may broke replace/reorder sprites logic
-// if (slot && mSlots[slot].spriteId == id)
-// return;
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = mSlots[slot].spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- addItemParticles(id, info.getDisplay());
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-
- BeingSlot &beingSlot = mSlots[slot];
- beingSlot.spriteId = id;
- beingSlot.color = color;
- beingSlot.colorId = ItemColor_one;
- beingSlot.cardsId = CardsList(nullptr);
- recalcSpritesOrder();
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-// set sprite id, use color id, reset cards
-void Being::setSpriteColorId(const unsigned int slot,
- const int id,
- ItemColor colorId) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- // disabled for now, because it may broke replace/reorder sprites logic
-// if (slot && mSlots[slot].spriteId == id)
-// return;
-
- std::string color;
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = mSlots[slot].spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- color = info.getDyeColorsString(colorId);
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- addItemParticles(id, info.getDisplay());
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-
- BeingSlot &beingSlot = mSlots[slot];
- beingSlot.spriteId = id;
- beingSlot.color = STD_MOVE(color);
- beingSlot.colorId = colorId;
- beingSlot.cardsId = CardsList(nullptr);
- recalcSpritesOrder();
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-// set sprite id, colors from cards, cards
-void Being::setSpriteCards(const unsigned int slot,
- const int id,
- const CardsList &cards) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- // disabled for now, because it may broke replace/reorder sprites logic
-// if (slot && mSlots[slot].spriteId == id)
-// return;
-
- ItemColor colorId = ItemColor_one;
- std::string color;
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = mSlots[slot].spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!cards.isEmpty())
- colorId = ItemColorManager::getColorFromCards(cards);
-
- if (!filename.empty())
- {
- if (color.empty())
- color = info.getDyeColorsString(colorId);
-
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- addItemParticlesCards(id,
- info.getDisplay(),
- cards);
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-
- BeingSlot &beingSlot = mSlots[slot];
- beingSlot.spriteId = id;
- beingSlot.color = STD_MOVE(color);
- beingSlot.colorId = colorId;
- beingSlot.cardsId = CardsList(cards);
- recalcSpritesOrder();
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-void Being::setWeaponId(const int id) restrict2
-{
- if (id == 0)
- mEquippedWeapon = nullptr;
- else
- mEquippedWeapon = &ItemDB::get(id);
-}
-
-void Being::setTempSprite(const unsigned int slot,
- const int id) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- BeingSlot &beingSlot = mSlots[slot];
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = beingSlot.spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
-
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- ItemColor colorId = ItemColor_one;
- const CardsList &cards = beingSlot.cardsId;
- if (!cards.isEmpty())
- colorId = ItemColorManager::getColorFromCards(cards);
- std::string color = beingSlot.color;
- if (color.empty())
- color = info.getDyeColorsString(colorId);
-
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- // +++ here probably need use existing cards
- addItemParticles(id, info.getDisplay());
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-}
-
-void Being::setHairTempSprite(const unsigned int slot,
- const int id) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- const CardsList &cards = mSlots[slot].cardsId;
-
- // id = 0 means unequip
- if (id == 0)
- {
- removeSprite(slot);
- mSpriteDraw[slot] = 0;
-
- const int id1 = mSlots[slot].spriteId;
- if (id1 != 0)
- removeItemParticles(id1);
- }
- else
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- ItemColor colorId = ItemColor_one;
- if (!cards.isEmpty())
- colorId = ItemColorManager::getColorFromCards(cards);
-
- std::string color = info.getDyeColorsString(mHairColor);
- if (color.empty())
- color = info.getDyeColorsString(colorId);
-
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
- mSpriteDraw[slot] = id;
-
- addItemParticles(id, info.getDisplay());
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-}
-
-void Being::setHairColorSpriteID(const unsigned int slot,
- const int id) restrict2
-{
- BeingSlot &beingSlot = mSlots[slot];
- setSpriteColor(slot,
- id,
- beingSlot.color);
-}
-
-void Being::setSpriteColor(const unsigned int slot,
- const std::string &restrict color) restrict2
-{
- if (charServerHandler == nullptr || slot >= charServerHandler->maxSprite())
- return;
-
- if (slot >= CAST_U32(mSprites.size()))
- ensureSize(slot + 1);
-
- if (slot >= CAST_U32(mSlots.size()))
- mSlots.resize(slot + 1, BeingSlot());
-
- // disabled for now, because it may broke replace/reorder sprites logic
-// if (slot && mSlots[slot].spriteId == id)
-// return;
-
- BeingSlot &beingSlot = mSlots[slot];
- const int id = beingSlot.spriteId;
-
- // id = 0 means unequip
- if (id != 0)
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(slot, equipmentSprite);
-
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
- }
-
- beingSlot.color = color;
- beingSlot.colorId = ItemColor_one;
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
-}
-
-void Being::setHairStyle(const unsigned int slot,
- const int id) restrict2
-{
- if (id != 0)
- {
- setSpriteColor(slot,
- id,
- ItemDB::get(id).getDyeColorsString(mHairColor));
- }
- else
- {
- setSpriteColor(slot,
- 0,
- std::string());
- }
-}
-
-void Being::setHairColor(const unsigned int slot,
- const ItemColor color) restrict2
-{
- mHairColor = color;
- BeingSlot &beingSlot = mSlots[slot];
- const int id = beingSlot.spriteId;
- if (id != 0)
- {
- setSpriteColor(slot,
- id,
- ItemDB::get(id).getDyeColorsString(color));
- }
-}
-
-void Being::setSpriteSlot(const unsigned int slot,
- const BeingSlot &beingSlot)
-{
- mSlots[slot] = beingSlot;
-}
-
-void Being::dumpSprites() const restrict2
-{
- STD_VECTOR<BeingSlot>::const_iterator it1 = mSlots.begin();
- const STD_VECTOR<BeingSlot>::const_iterator it1_end = mSlots.end();
-
- logger->log("sprites");
- for (; it1 != it1_end;
- ++ it1)
- {
- logger->log("%d,%s,%d",
- (*it1).spriteId,
- (*it1).color.c_str(),
- toInt((*it1).colorId, int));
- }
-}
-
-void Being::updateName() restrict2
-{
- if (mShowName)
- showName();
-}
-
-void Being::reReadConfig()
-{
- BLOCK_START("Being::reReadConfig")
- if (mUpdateConfigTime + 1 < cur_time)
- {
- mAwayEffect = paths.getIntValue("afkEffectId");
- mHighlightMapPortals = config.getBoolValue("highlightMapPortals");
- mConfLineLim = config.getIntValue("chatMaxCharLimit");
- mSpeechType = config.getIntValue("speech");
- mHighlightMonsterAttackRange =
- config.getBoolValue("highlightMonsterAttackRange");
- mLowTraffic = config.getBoolValue("lowTraffic");
- mDrawHotKeys = config.getBoolValue("drawHotKeys");
- mShowBattleEvents = config.getBoolValue("showBattleEvents");
- mShowMobHP = config.getBoolValue("showMobHP");
- mShowOwnHP = config.getBoolValue("showOwnHP");
- mShowGender = config.getBoolValue("showgender");
- mShowLevel = config.getBoolValue("showlevel");
- mShowPlayersStatus = config.getBoolValue("showPlayersStatus");
- mEnableReorderSprites = config.getBoolValue("enableReorderSprites");
- mHideErased = config.getBoolValue("hideErased");
- mMoveNames = fromBool(config.getBoolValue("moveNames"), Move);
- mUseDiagonal = config.getBoolValue("useDiagonalSpeed");
- mShowBadges = static_cast<BadgeDrawType::Type>(
- config.getIntValue("showBadges"));
- mVisibleNamePos = static_cast<VisibleNamePos::Type>(
- config.getIntValue("visiblenamespos"));
-
- mUpdateConfigTime = cur_time;
- }
- BLOCK_END("Being::reReadConfig")
-}
-
-bool Being::updateFromCache() restrict2
-{
- const BeingCacheEntry *restrict const entry =
- Being::getCacheEntry(getId());
-
- if ((entry != nullptr) && entry->getTime() + 120 >= cur_time)
- {
- if (!entry->getName().empty())
- setName(entry->getName());
- setPartyName(entry->getPartyName());
- setGuildName(entry->getGuildName());
- setLevel(entry->getLevel());
- setPvpRank(entry->getPvpRank());
- setIp(entry->getIp());
- setTeamId(entry->getTeamId());
-
- mAdvanced = entry->isAdvanced();
- if (mAdvanced)
- {
- const int flags = entry->getFlags();
- if ((serverFeatures != nullptr) &&
- Net::getNetworkType() == ServerType::TMWATHENA)
- {
- mShop = ((flags & BeingFlag::SHOP) != 0);
- }
- mAway = ((flags & BeingFlag::AWAY) != 0);
- mInactive = ((flags & BeingFlag::INACTIVE) != 0);
- if (mShop || mAway || mInactive)
- updateName();
- }
- else
- {
- if (Net::getNetworkType() == ServerType::TMWATHENA)
- mShop = false;
- mAway = false;
- mInactive = false;
- }
-
- showShopBadge(mShop);
- showInactiveBadge(mInactive);
- showAwayBadge(mAway);
- updateAwayEffect();
- if (mType == ActorType::Player || (mTeamId != 0u))
- updateColors();
- return true;
- }
- return false;
-}
-
-void Being::addToCache() const restrict2
-{
- if (localPlayer == this)
- return;
-
- BeingCacheEntry *entry = Being::getCacheEntry(getId());
- if (entry == nullptr)
- {
- entry = new BeingCacheEntry(getId());
- beingInfoCache.push_front(entry);
-
- if (beingInfoCache.size() >= CACHE_SIZE)
- {
- delete beingInfoCache.back();
- beingInfoCache.pop_back();
- }
- }
- if (!mLowTraffic)
- return;
-
- entry->setName(mName);
- entry->setLevel(getLevel());
- entry->setPartyName(getPartyName());
- entry->setGuildName(getGuildName());
- entry->setTime(cur_time);
- entry->setPvpRank(getPvpRank());
- entry->setIp(getIp());
- entry->setAdvanced(isAdvanced());
- entry->setTeamId(getTeamId());
- if (isAdvanced())
- {
- int flags = 0;
- if (Net::getNetworkType() == ServerType::TMWATHENA && mShop)
- flags += BeingFlag::SHOP;
- if (mAway)
- flags += BeingFlag::AWAY;
- if (mInactive)
- flags += BeingFlag::INACTIVE;
- entry->setFlags(flags);
- }
- else
- {
- entry->setFlags(0);
- }
-}
-
-BeingCacheEntry* Being::getCacheEntry(const BeingId id)
-{
- FOR_EACH (std::list<BeingCacheEntry*>::iterator, i, beingInfoCache)
- {
- if (*i == nullptr)
- continue;
-
- if (id == (*i)->getId())
- {
- // Raise priority: move it to front
- if ((*i)->getTime() + 120 < cur_time)
- {
- beingInfoCache.splice(beingInfoCache.begin(),
- beingInfoCache, i);
- }
- return *i;
- }
- }
- return nullptr;
-}
-
-
-void Being::setGender(const GenderT gender) restrict2
-{
- if (charServerHandler == nullptr)
- return;
-
- if (gender != mGender)
- {
- mGender = gender;
-
- const unsigned int sz = CAST_U32(mSlots.size());
-
- if (sz > CAST_U32(mSprites.size()))
- ensureSize(sz);
-
- // Reload all subsprites
- for (unsigned int i = 0;
- i < sz;
- i++)
- {
- BeingSlot &beingSlot = mSlots[i];
- const int id = beingSlot.spriteId;
- if (id != 0)
- {
- const ItemInfo &info = ItemDB::get(id);
- const std::string &restrict filename = info.getSprite(
- mGender, mSubType);
- int lastTime = 0;
- int startTime = 0;
- AnimatedSprite *restrict equipmentSprite = nullptr;
-
- if (!filename.empty())
- {
- equipmentSprite = AnimatedSprite::delayedLoad(
- pathJoin(paths.getStringValue("sprites"),
- combineDye(filename, beingSlot.color)));
- }
-
- if (equipmentSprite != nullptr)
- {
- equipmentSprite->setSpriteDirection(getSpriteDirection());
- startTime = getStartTime();
- lastTime = getLastTime();
- }
-
- CompoundSprite::setSprite(i, equipmentSprite);
- setAction(mAction, 0);
- if (equipmentSprite != nullptr)
- {
- if (lastTime > 0)
- {
- equipmentSprite->setLastTime(startTime);
- equipmentSprite->update(lastTime);
- }
- }
-
- if (beingEquipmentWindow != nullptr)
- beingEquipmentWindow->updateBeing(this);
- }
- }
-
- updateName();
- }
-}
-
-void Being::showGmBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Gm]);
- if (show &&
- mIsGM &&
- mShowBadges != BadgeDrawType::Hide &&
- GroupDb::getShowBadge(mGroupId))
- {
- const std::string &gmBadge = GroupDb::getBadge(mGroupId);
- if (!gmBadge.empty())
- {
- mBadges[BadgeIndex::Gm] = AnimatedSprite::load(
- paths.getStringValue("badges") + gmBadge);
- }
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-void Being::setGM(const bool gm) restrict2
-{
- if (mIsGM != gm)
- {
- mIsGM = gm;
-
- showGmBadge(mIsGM);
- updateColors();
- }
-}
-
-void Being::talkTo() const restrict2
-{
- if (npcHandler == nullptr)
- return;
-
- if (!PacketLimiter::limitPackets(PacketType::PACKET_NPC_TALK))
- {
- // using workaround...
- if ((playerHandler != nullptr) &&
- PacketLimiter::limitPackets(PacketType::PACKET_ATTACK))
- {
- playerHandler->attack(mId, Keep_false);
- }
- return;
- }
-
- npcHandler->talk(this);
-}
-
-void Being::drawPlayer(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- if (!mErased)
- {
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- if (mHorseInfo != nullptr)
- {
- HorseOffset &offset = mHorseInfo->offsets[mSpriteDirection];
- for_each_horses(mDownHorseSprites)
- {
- (*it)->draw(graphics,
- px + offset.downOffsetX,
- py + offset.downOffsetY);
- }
-
- drawBeingCursor(graphics, px, py);
- drawPlayerSpriteAt(graphics,
- px + offset.riderOffsetX,
- py + offset.riderOffsetY);
-
- for_each_horses(mUpHorseSprites)
- {
- (*it)->draw(graphics,
- px + offset.upOffsetX,
- py + offset.upOffsetY);
- }
- }
- else
- {
- drawBeingCursor(graphics, px, py);
- drawPlayerSpriteAt(graphics, px, py);
- }
- }
-}
-
-void Being::drawBeingCursor(Graphics *const graphics,
- const int offsetX,
- const int offsetY) const
-{
- if (mUsedTargetCursor != nullptr)
- {
- mUsedTargetCursor->update(tick_time * MILLISECONDS_IN_A_TICK);
- if (mInfo == nullptr)
- {
- mUsedTargetCursor->draw(graphics,
- offsetX - mCursorPaddingX,
- offsetY - mCursorPaddingY);
- }
- else
- {
- mUsedTargetCursor->draw(graphics,
- offsetX + mInfo->getTargetOffsetX() - mCursorPaddingX,
- offsetY + mInfo->getTargetOffsetY() - mCursorPaddingY);
- }
- }
-}
-
-void Being::drawOther(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawBeingCursor(graphics, px, py);
- drawOtherSpriteAt(graphics, px, py);
-}
-
-void Being::drawMonster(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawBeingCursor(graphics, px, py);
- drawMonsterSpriteAt(graphics, px, py);
-}
-
-void Being::drawHomunculus(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawBeingCursor(graphics, px, py);
- drawHomunculusSpriteAt(graphics, px, py);
-}
-
-void Being::drawMercenary(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawBeingCursor(graphics, px, py);
- drawMercenarySpriteAt(graphics, px, py);
-}
-
-void Being::drawElemental(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawBeingCursor(graphics, px, py);
- drawElementalSpriteAt(graphics, px, py);
-}
-
-void Being::drawPortal(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- // getActorX() + offsetX;
- const int px = mPixelX - mapTileSize / 2 + offsetX;
- // getActorY() + offsetY;
- const int py = mPixelY - mapTileSize + offsetY;
- drawPortalSpriteAt(graphics, px, py);
-}
-
-void Being::draw(Graphics *restrict const graphics,
- const int offsetX,
- const int offsetY) const restrict2
-{
- switch (mType)
- {
- case ActorType::Player:
- drawPlayer(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Portal:
- drawPortal(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Homunculus:
- drawHomunculus(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Mercenary:
- drawMercenary(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Elemental:
- drawElemental(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Monster:
- drawMonster(graphics,
- offsetX,
- offsetY);
- break;
- case ActorType::Pet:
- case ActorType::SkillUnit:
- case ActorType::Unknown:
- case ActorType::Npc:
- case ActorType::FloorItem:
- case ActorType::Avatar:
- default:
- drawOther(graphics,
- offsetX,
- offsetY);
- break;
- }
-}
-
-void Being::drawPlayerSprites(Graphics *restrict const graphics,
- const int posX,
- const int posY) const restrict2
-{
- const int sz = CompoundSprite::getNumberOfLayers();
- for (int f = 0; f < sz; f ++)
- {
- const int rSprite = mSpriteHide[mSpriteRemap[f]];
- if (rSprite == 1)
- continue;
-
- Sprite *restrict const sprite = mSprites[mSpriteRemap[f]];
- if (sprite != nullptr)
- {
- sprite->setAlpha(mAlpha);
- sprite->draw(graphics, posX, posY);
- }
- }
-}
-
-void Being::drawSpritesSDL(Graphics *restrict const graphics,
- const int posX,
- const int posY) const restrict2
-{
- const size_t sz = mSprites.size();
- for (size_t f = 0; f < sz; f ++)
- {
- const int rSprite = mSpriteHide[mSpriteRemap[f]];
- if (rSprite == 1)
- continue;
-
- const Sprite *restrict const sprite = mSprites[mSpriteRemap[f]];
- if (sprite != nullptr)
- sprite->draw(graphics, posX, posY);
- }
-}
-
-void Being::drawBasic(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- drawCompound(graphics, x, y);
-}
-
-void Being::drawCompound(Graphics *const graphics,
- const int posX,
- const int posY) const
-{
- FUNC_BLOCK("CompoundSprite::draw", 1)
- if (mNeedsRedraw)
- updateImages();
-
- if (mSprites.empty()) // Nothing to draw
- return;
-
- if (mAlpha == 1.0F && (mImage != nullptr))
- {
- graphics->drawImage(mImage,
- posX + mOffsetX,
- posY + mOffsetY);
- }
- else if ((mAlpha != 0.0f) && (mAlphaImage != nullptr))
- {
- mAlphaImage->setAlpha(mAlpha);
- graphics->drawImage(mAlphaImage,
- posX + mOffsetX,
- posY + mOffsetY);
- }
- else
- {
- Being::drawPlayerSprites(graphics, posX, posY);
- }
-}
-
-void Being::drawPlayerSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- drawCompound(graphics, x, y);
-
- if (mShowOwnHP &&
- (mInfo != nullptr) &&
- localPlayer == this &&
- mAction != BeingAction::DEAD)
- {
- drawHpBar(graphics,
- PlayerInfo::getAttribute(Attributes::PLAYER_MAX_HP),
- PlayerInfo::getAttribute(Attributes::PLAYER_HP),
- 0,
- UserColorId::PLAYER_HP,
- UserColorId::PLAYER_HP2,
- x - 50 + mapTileSize / 2 + mInfo->getHpBarOffsetX(),
- y + mapTileSize - 6 + mInfo->getHpBarOffsetY(),
- 2 * 50,
- 4);
- }
-}
-
-void Being::drawOtherSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- CompoundSprite::drawSimple(graphics, x, y);
-}
-
-void Being::drawMonsterSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- if (mHighlightMonsterAttackRange &&
- mType == ActorType::Monster &&
- mAction != BeingAction::DEAD)
- {
- if (userPalette == nullptr)
- {
- CompoundSprite::drawSimple(graphics, x, y);
- return;
- }
-
- int attackRange;
- if (mAttackRange != 0)
- attackRange = mapTileSize * mAttackRange;
- else
- attackRange = mapTileSize;
-
- graphics->setColor(userPalette->getColorWithAlpha(
- UserColorId::MONSTER_ATTACK_RANGE));
-
- graphics->fillRectangle(Rect(
- x - attackRange, y - attackRange,
- 2 * attackRange + mapTileSize, 2 * attackRange + mapTileSize));
- }
-
- CompoundSprite::drawSimple(graphics, x, y);
-
- if (mShowMobHP &&
- (mInfo != nullptr) &&
- (localPlayer != nullptr) &&
- localPlayer->getTarget() == this &&
- mType == ActorType::Monster)
- {
- // show hp bar here
- int maxHP = mMaxHP;
- if (maxHP == 0)
- maxHP = mInfo->getMaxHP();
-
- drawHpBar(graphics,
- maxHP,
- mHP,
- mDamageTaken,
- UserColorId::MONSTER_HP,
- UserColorId::MONSTER_HP2,
- x - 50 + mapTileSize / 2 + mInfo->getHpBarOffsetX(),
- y + mapTileSize - 6 + mInfo->getHpBarOffsetY(),
- 2 * 50,
- 4);
- }
-}
-
-void Being::drawHomunculusSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- if (mHighlightMonsterAttackRange &&
- mAction != BeingAction::DEAD)
- {
- if (userPalette == nullptr)
- {
- CompoundSprite::drawSimple(graphics, x, y);
- return;
- }
-
- int attackRange;
- if (mAttackRange != 0)
- attackRange = mapTileSize * mAttackRange;
- else
- attackRange = mapTileSize;
-
- graphics->setColor(userPalette->getColorWithAlpha(
- UserColorId::MONSTER_ATTACK_RANGE));
-
- graphics->fillRectangle(Rect(
- x - attackRange, y - attackRange,
- 2 * attackRange + mapTileSize, 2 * attackRange + mapTileSize));
- }
-
- CompoundSprite::drawSimple(graphics, x, y);
-
- if (mShowMobHP &&
- (mInfo != nullptr))
- {
- const HomunculusInfo *const info = PlayerInfo::getHomunculus();
- if ((info != nullptr) &&
- mId == info->id)
- {
- // show hp bar here
- int maxHP = PlayerInfo::getStatBase(Attributes::HOMUN_MAX_HP);
- if (maxHP == 0)
- maxHP = mInfo->getMaxHP();
-
- drawHpBar(graphics,
- maxHP,
- PlayerInfo::getStatBase(Attributes::HOMUN_HP),
- mDamageTaken,
- UserColorId::HOMUN_HP,
- UserColorId::HOMUN_HP2,
- x - 50 + mapTileSize / 2 + mInfo->getHpBarOffsetX(),
- y + mapTileSize - 6 + mInfo->getHpBarOffsetY(),
- 2 * 50,
- 4);
- }
- }
-}
-
-void Being::drawMercenarySpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- if (mHighlightMonsterAttackRange &&
- mAction != BeingAction::DEAD)
- {
- if (userPalette == nullptr)
- {
- CompoundSprite::drawSimple(graphics, x, y);
- return;
- }
-
- int attackRange;
- if (mAttackRange != 0)
- attackRange = mapTileSize * mAttackRange;
- else
- attackRange = mapTileSize;
-
- graphics->setColor(userPalette->getColorWithAlpha(
- UserColorId::MONSTER_ATTACK_RANGE));
-
- graphics->fillRectangle(Rect(
- x - attackRange, y - attackRange,
- 2 * attackRange + mapTileSize, 2 * attackRange + mapTileSize));
- }
-
- CompoundSprite::drawSimple(graphics, x, y);
-
- if (mShowMobHP &&
- (mInfo != nullptr))
- {
- const MercenaryInfo *const info = PlayerInfo::getMercenary();
- if ((info != nullptr) &&
- mId == info->id)
- {
- // show hp bar here
- int maxHP = PlayerInfo::getStatBase(Attributes::MERC_MAX_HP);
- if (maxHP == 0)
- maxHP = mInfo->getMaxHP();
-
- drawHpBar(graphics,
- maxHP,
- PlayerInfo::getStatBase(Attributes::MERC_HP),
- mDamageTaken,
- UserColorId::MERC_HP,
- UserColorId::MERC_HP2,
- x - 50 + mapTileSize / 2 + mInfo->getHpBarOffsetX(),
- y + mapTileSize - 6 + mInfo->getHpBarOffsetY(),
- 2 * 50,
- 4);
- }
- }
-}
-
-void Being::drawElementalSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- if (mHighlightMonsterAttackRange &&
- mAction != BeingAction::DEAD)
- {
- if (userPalette == nullptr)
- {
- CompoundSprite::drawSimple(graphics, x, y);
- return;
- }
-
- int attackRange;
- if (mAttackRange != 0)
- attackRange = mapTileSize * mAttackRange;
- else
- attackRange = mapTileSize;
-
- graphics->setColor(userPalette->getColorWithAlpha(
- UserColorId::MONSTER_ATTACK_RANGE));
-
- graphics->fillRectangle(Rect(
- x - attackRange, y - attackRange,
- 2 * attackRange + mapTileSize, 2 * attackRange + mapTileSize));
- }
-
- CompoundSprite::drawSimple(graphics, x, y);
-
- if (mShowMobHP &&
- (mInfo != nullptr))
- {
- if (mId == PlayerInfo::getElementalId())
- {
- // show hp bar here
- int maxHP = PlayerInfo::getStatBase(Attributes::ELEMENTAL_MAX_HP);
- if (maxHP == 0)
- maxHP = mInfo->getMaxHP();
-
- drawHpBar(graphics,
- maxHP,
- PlayerInfo::getStatBase(Attributes::ELEMENTAL_HP),
- mDamageTaken,
- UserColorId::ELEMENTAL_HP,
- UserColorId::ELEMENTAL_HP2,
- x - 50 + mapTileSize / 2 + mInfo->getHpBarOffsetX(),
- y + mapTileSize - 6 + mInfo->getHpBarOffsetY(),
- 2 * 50,
- 4);
- }
- }
-}
-
-void Being::drawPortalSpriteAt(Graphics *restrict const graphics,
- const int x,
- const int y) const restrict2
-{
- if (mHighlightMapPortals &&
- (mMap != nullptr) &&
- !mMap->getHasWarps())
- {
- if (userPalette == nullptr)
- {
- CompoundSprite::drawSimple(graphics, x, y);
- return;
- }
-
- graphics->setColor(userPalette->
- getColorWithAlpha(UserColorId::PORTAL_HIGHLIGHT));
-
- graphics->fillRectangle(Rect(x, y,
- mapTileSize, mapTileSize));
-
- if (mDrawHotKeys && !mName.empty())
- {
- const Color &color = userPalette->getColor(UserColorId::BEING);
- gui->getFont()->drawString(graphics, color, color, mName, x, y);
- }
- }
-
- CompoundSprite::drawSimple(graphics, x, y);
-}
-
-void Being::drawHpBar(Graphics *restrict const graphics,
- const int maxHP,
- const int hp,
- const int damage,
- const UserColorIdT color1,
- const UserColorIdT color2,
- const int x,
- const int y,
- const int width,
- const int height) const restrict2
-{
- if (maxHP <= 0 || (userPalette == nullptr))
- return;
-
- float p;
-
- if (hp != 0)
- {
- p = static_cast<float>(maxHP) / static_cast<float>(hp);
- }
- else if (maxHP != damage)
- {
- p = static_cast<float>(maxHP)
- / static_cast<float>(maxHP - damage);
- }
- else
- {
- p = 1;
- }
-
- if (p <= 0 || p > width)
- return;
-
- const int dx = static_cast<int>(static_cast<float>(width) / p);
-
-#ifdef TMWA_SUPPORT
- if (!serverFeatures->haveServerHp())
- { // old servers
- if ((damage == 0 && (this != localPlayer || hp == maxHP))
- || (hp == 0 && maxHP == damage))
- {
- graphics->setColor(userPalette->getColorWithAlpha(color1));
- graphics->fillRectangle(Rect(
- x, y, dx, height));
- return;
- }
- else if (width - dx <= 0)
- {
- graphics->setColor(userPalette->getColorWithAlpha(color2));
- graphics->fillRectangle(Rect(
- x, y, width, height));
- return;
- }
- }
- else
-#endif // TMWA_SUPPORT
- {
- if (hp == maxHP)
- {
- graphics->setColor(userPalette->getColorWithAlpha(color1));
- graphics->fillRectangle(Rect(
- x, y, dx, height));
- return;
- }
- else if (width - dx <= 0)
- {
- graphics->setColor(userPalette->getColorWithAlpha(color2));
- graphics->fillRectangle(Rect(
- x, y, width, height));
- return;
- }
- }
-
- graphics->setColor(userPalette->getColorWithAlpha(color1));
- graphics->fillRectangle(Rect(
- x, y, dx, height));
-
- graphics->setColor(userPalette->getColorWithAlpha(color2));
- graphics->fillRectangle(Rect(x + dx, y, width - dx, height));
-}
-
-void Being::setHP(const int hp) restrict2
-{
- mHP = hp;
- if (mMaxHP < mHP)
- mMaxHP = mHP;
- if (mType == ActorType::Monster)
- updatePercentHP();
-}
-
-void Being::setMaxHP(const int hp) restrict2
-{
- mMaxHP = hp;
- if (mMaxHP < mHP)
- mMaxHP = mHP;
-}
-
-void Being::resetCounters() restrict2
-{
- mMoveTime = 0;
- mAttackTime = 0;
- mTalkTime = 0;
- mOtherTime = 0;
- mTestTime = cur_time;
-}
-
-void Being::recalcSpritesOrder() restrict2
-{
- if (!mEnableReorderSprites)
- return;
-
-// logger->log("recalcSpritesOrder");
- const size_t sz = mSprites.size();
- if (sz < 1)
- return;
-
- STD_VECTOR<int> slotRemap;
- IntMap itemSlotRemap;
-
- STD_VECTOR<int>::iterator it;
- int oldHide[20];
- bool updatedSprite[20];
- int dir = mSpriteDirection;
- if (dir < 0 || dir >= 9)
- dir = 0;
- // hack for allow different logic in dead player
- if (mAction == BeingAction::DEAD)
- dir = 9;
-
- const unsigned int hairSlot = charServerHandler->hairSprite();
-
- for (size_t slot = sz; slot < 20; slot ++)
- {
- oldHide[slot] = 0;
- updatedSprite[slot] = false;
- }
-
- for (size_t slot = 0; slot < sz; slot ++)
- {
- oldHide[slot] = mSpriteHide[slot];
- mSpriteHide[slot] = 0;
- updatedSprite[slot] = false;
- }
-
- size_t spriteIdSize = mSlots.size();
- if (reportTrue(spriteIdSize > 20))
- spriteIdSize = 20;
-
- for (size_t slot = 0; slot < sz; slot ++)
- {
- slotRemap.push_back(CAST_S32(slot));
-
- if (spriteIdSize <= slot)
- continue;
-
- const int id = mSlots[slot].spriteId;
- if (id == 0)
- continue;
-
- const ItemInfo &info = ItemDB::get(id);
-
- if (info.isRemoveSprites())
- {
- const SpriteToItemMap *restrict const spriteToItems
- = info.getSpriteToItemReplaceMap(dir);
-
- if (spriteToItems != nullptr)
- {
- FOR_EACHP (SpriteToItemMapCIter, itr, spriteToItems)
- {
- const int remSprite = itr->first;
- const IntMap &restrict itemReplacer = itr->second;
- if (remSprite >= 0)
- { // slot known
- if (itemReplacer.empty())
- {
- mSpriteHide[remSprite] = 1;
- }
- else if (mSpriteHide[remSprite] != 1)
- {
- IntMapCIter repIt = itemReplacer.find(
- mSlots[remSprite].spriteId);
- if (repIt == itemReplacer.end())
- {
- repIt = itemReplacer.find(0);
- if (repIt->second == 0)
- repIt = itemReplacer.end();
- }
- if (repIt != itemReplacer.end())
- {
- mSpriteHide[remSprite] = repIt->second;
- if (repIt->second != 1)
- {
- if (CAST_U32(remSprite)
- != hairSlot)
- {
- setTempSprite(remSprite,
- repIt->second);
- }
- else
- {
- setHairTempSprite(remSprite,
- repIt->second);
- }
- updatedSprite[remSprite] = true;
- }
- }
- }
- }
- else
- { // slot unknown. Search for real slot, this can be slow
- FOR_EACH (IntMapCIter, repIt, itemReplacer)
- {
- for (unsigned int slot2 = 0; slot2 < sz; slot2 ++)
- {
- if (mSlots[slot2].spriteId == repIt->first)
- {
- mSpriteHide[slot2] = repIt->second;
- if (repIt->second != 1)
- {
- if (slot2 != hairSlot)
- {
- setTempSprite(slot2,
- repIt->second);
- }
- else
- {
- setHairTempSprite(slot2,
- repIt->second);
- }
- updatedSprite[slot2] = true;
- }
- }
- }
- }
- }
- }
- }
- }
-
- if (info.mDrawBefore[dir] > 0)
- {
- const int id2 = mSlots[info.mDrawBefore[dir]].spriteId;
- if (itemSlotRemap.find(id2) != itemSlotRemap.end())
- {
-// logger->log("found duplicate (before)");
- const ItemInfo &info2 = ItemDB::get(id2);
- if (info.mDrawPriority[dir] < info2.mDrawPriority[dir])
- {
-// logger->log("old more priority");
- continue;
- }
- else
- {
-// logger->log("new more priority");
- itemSlotRemap.erase(id2);
- }
- }
-
- itemSlotRemap[id] = -info.mDrawBefore[dir];
- }
- else if (info.mDrawAfter[dir] > 0)
- {
- const int id2 = mSlots[info.mDrawAfter[dir]].spriteId;
- if (itemSlotRemap.find(id2) != itemSlotRemap.end())
- {
- const ItemInfo &info2 = ItemDB::get(id2);
- if (info.mDrawPriority[dir] < info2.mDrawPriority[dir])
- {
-// logger->log("old more priority");
- continue;
- }
- else
- {
-// logger->log("new more priority");
- itemSlotRemap.erase(id2);
- }
- }
-
- itemSlotRemap[id] = info.mDrawAfter[dir];
-// logger->log("item slot->slot %d %d->%d", id, slot, itemSlotRemap[id]);
- }
- }
-// logger->log("preparation end");
-
- int lastRemap = 0;
- unsigned cnt = 0;
-
- while (cnt < 15 && lastRemap >= 0)
- {
- lastRemap = -1;
- cnt ++;
-// logger->log("iteration");
-
- for (unsigned int slot0 = 0; slot0 < sz; slot0 ++)
- {
- const int slot = searchSlotValue(slotRemap, slot0);
- const int val = slotRemap.at(slot);
- int id = 0;
-
- if (CAST_S32(spriteIdSize) > val)
- id = mSlots[val].spriteId;
-
- int idx = -1;
- int idx1 = -1;
-// logger->log("item %d, id=%d", slot, id);
- int reorder = 0;
- const IntMapCIter orderIt = itemSlotRemap.find(id);
- if (orderIt != itemSlotRemap.end())
- reorder = orderIt->second;
-
- if (reorder < 0)
- {
-// logger->log("move item %d before %d", slot, -reorder);
- searchSlotValueItr(it, idx, slotRemap, -reorder);
- if (it == slotRemap.end())
- return;
- searchSlotValueItr(it, idx1, slotRemap, val);
- if (it == slotRemap.end())
- return;
- lastRemap = idx1;
- if (idx1 + 1 != idx)
- {
- slotRemap.erase(it);
- searchSlotValueItr(it, idx, slotRemap, -reorder);
- slotRemap.insert(it, val);
- }
- }
- else if (reorder > 0)
- {
-// logger->log("move item %d after %d", slot, reorder);
- searchSlotValueItr(it, idx, slotRemap, reorder);
- searchSlotValueItr(it, idx1, slotRemap, val);
- if (it == slotRemap.end())
- return;
- lastRemap = idx1;
- if (idx1 != idx + 1)
- {
- slotRemap.erase(it);
- searchSlotValueItr(it, idx, slotRemap, reorder);
- if (it != slotRemap.end())
- {
- ++ it;
- if (it != slotRemap.end())
- slotRemap.insert(it, val);
- else
- slotRemap.push_back(val);
- }
- else
- {
- slotRemap.push_back(val);
- }
- }
- }
- }
- }
-
-// logger->log("after remap");
- for (unsigned int slot = 0; slot < sz; slot ++)
- {
- mSpriteRemap[slot] = slotRemap[slot];
- if (mSpriteHide[slot] == 0)
- {
- if (oldHide[slot] != 0 && oldHide[slot] != 1)
- {
- const BeingSlot &beingSlot = mSlots[slot];
- const int id = beingSlot.spriteId;
- if (id == 0)
- continue;
-
- updatedSprite[slot] = true;
- setTempSprite(slot,
- id);
- }
- }
- }
- for (size_t slot = 0; slot < spriteIdSize; slot ++)
- {
- if (mSpriteHide[slot] == 0)
- {
- const BeingSlot &beingSlot = mSlots[slot];
- const int id = beingSlot.spriteId;
- if (updatedSprite[slot] == false &&
- mSpriteDraw[slot] != id)
- {
- setTempSprite(static_cast<unsigned int>(slot),
- id);
- }
- }
- }
-}
-
-int Being::searchSlotValue(const STD_VECTOR<int> &restrict slotRemap,
- const int val) const restrict2
-{
- const size_t sz = mSprites.size();
- for (size_t slot = 0; slot < sz; slot ++)
- {
- if (slotRemap[slot] == val)
- return CAST_S32(slot);
- }
- return CompoundSprite::getNumberOfLayers() - 1;
-}
-
-void Being::searchSlotValueItr(STD_VECTOR<int>::iterator &restrict it,
- int &restrict idx,
- STD_VECTOR<int> &restrict slotRemap,
- const int val)
-{
-// logger->log("searching %d", val);
- it = slotRemap.begin();
- const STD_VECTOR<int>::iterator it_end = slotRemap.end();
- idx = 0;
- while (it != it_end)
- {
-// logger->log("testing %d", *it);
- if (*it == val)
- {
-// logger->log("found at %d", idx);
- return;
- }
- ++ it;
- idx ++;
- }
-// logger->log("not found");
- idx = -1;
-}
-
-void Being::updateHit(const int amount) restrict2
-{
- if (amount > 0)
- {
- if ((mMinHit == 0) || amount < mMinHit)
- mMinHit = amount;
- if (amount != mCriticalHit && ((mMaxHit == 0) || amount > mMaxHit))
- mMaxHit = amount;
- }
-}
-
-Equipment *Being::getEquipment() restrict2
-{
- Equipment *restrict const eq = new Equipment;
- Equipment::Backend *restrict const bk = new BeingEquipBackend(this);
- eq->setBackend(bk);
- return eq;
-}
-
-void Being::undressItemById(const int id) restrict2
-{
- const size_t sz = mSlots.size();
-
- for (size_t f = 0; f < sz; f ++)
- {
- if (id == mSlots[f].spriteId)
- {
- unSetSprite(CAST_U32(f));
- break;
- }
- }
-}
-
-void Being::clearCache()
-{
- delete_all(beingInfoCache);
- beingInfoCache.clear();
-}
-
-void Being::updateComment() restrict2
-{
- if (mGotComment || mName.empty())
- return;
-
- mGotComment = true;
- mComment = loadComment(mName, mType);
-}
-
-std::string Being::loadComment(const std::string &restrict name,
- const ActorTypeT &restrict type)
-{
- std::string str;
- switch (type)
- {
- case ActorType::Player:
- str = settings.usersDir;
- break;
- case ActorType::Npc:
- str = settings.npcsDir;
- break;
- case ActorType::Unknown:
- case ActorType::Monster:
- case ActorType::FloorItem:
- case ActorType::Portal:
- case ActorType::Avatar:
- case ActorType::Mercenary:
- case ActorType::Homunculus:
- case ActorType::Pet:
- case ActorType::SkillUnit:
- case ActorType::Elemental:
- default:
- return "";
- }
-
- str = pathJoin(str, stringToHexPath(name), "comment.txt");
- if (Files::existsLocal(str))
- {
- StringVect lines;
- Files::loadTextFileLocal(str, lines);
- if (lines.size() >= 2)
- return lines[1];
- }
- return std::string();
-}
-
-void Being::saveComment(const std::string &restrict name,
- const std::string &restrict comment,
- const ActorTypeT &restrict type)
-{
- std::string dir;
- switch (type)
- {
- case ActorType::Player:
- dir = settings.usersDir;
- break;
- case ActorType::Npc:
- dir = settings.npcsDir;
- break;
- case ActorType::Monster:
- case ActorType::FloorItem:
- case ActorType::Portal:
- case ActorType::Avatar:
- case ActorType::Unknown:
- case ActorType::Pet:
- case ActorType::Mercenary:
- case ActorType::Homunculus:
- case ActorType::SkillUnit:
- case ActorType::Elemental:
- default:
- return;
- }
- dir = pathJoin(dir, stringToHexPath(name));
- Files::saveTextFile(dir,
- "comment.txt",
- (name + "\n").append(comment));
-}
-
-void Being::setState(const uint8_t state) restrict2
-{
- const bool shop = ((state & BeingFlag::SHOP) != 0);
- const bool away = ((state & BeingFlag::AWAY) != 0);
- const bool inactive = ((state & BeingFlag::INACTIVE) != 0);
- const bool needUpdate = (shop != mShop || away != mAway
- || inactive != mInactive);
-
- if (Net::getNetworkType() == ServerType::TMWATHENA)
- mShop = shop;
- mAway = away;
- mInactive = inactive;
- updateAwayEffect();
- showShopBadge(mShop);
- showInactiveBadge(mInactive);
- showAwayBadge(mAway);
-
- if (needUpdate)
- {
- if (shop || away || inactive)
- mAdvanced = true;
- updateName();
- addToCache();
- }
-}
-
-void Being::setEmote(const uint8_t emotion,
- const int emote_time) restrict2
-{
- if ((emotion & BeingFlag::SPECIAL) == BeingFlag::SPECIAL)
- {
- setState(emotion);
- mAdvanced = true;
- }
- else
- {
- const int emotionIndex = emotion - 1;
- if (emotionIndex >= 0 && emotionIndex <= EmoteDB::getLast())
- {
- delete2(mEmotionSprite)
- const EmoteInfo *const info = EmoteDB::get2(emotionIndex, true);
- if (info != nullptr)
- {
- const EmoteSprite *restrict const sprite =
- info->sprites.front();
- if (sprite != nullptr)
- {
- mEmotionSprite = AnimatedSprite::clone(sprite->sprite);
- if (mEmotionSprite != nullptr)
- mEmotionTime = info->time;
- else
- mEmotionTime = emote_time;
- }
- const int effectId = info->effectId;
- if (effectId >= 0)
- {
- effectManager->trigger(effectId, this);
- }
- }
- }
-
- if (mEmotionSprite != nullptr)
- {
- mEmotionSprite->play(mSpriteAction);
- mEmotionSprite->setSpriteDirection(mSpriteDirection);
- }
- else
- {
- mEmotionTime = 0;
- }
- }
-}
-
-void Being::updatePercentHP() restrict2
-{
- if (mMaxHP == 0)
- return;
- BLOCK_START("Being::updatePercentHP")
- if (mHP != 0)
- {
- const unsigned num = mHP * 100 / mMaxHP;
- if (num != mNumber)
- {
- mNumber = num;
- if (updateNumber(mNumber))
- setAction(mAction, 0);
- }
- }
- BLOCK_END("Being::updatePercentHP")
-}
-
-int Being::getSpriteID(const int slot) const restrict2
-{
- if (slot < 0 || CAST_SIZE(slot) >= mSlots.size())
- return -1;
-
- return mSlots[slot].spriteId;
-}
-
-const BeingSlot &Being::getSpriteSlot(const int slot) const restrict2
-{
- if (slot < 0 || CAST_SIZE(slot) >= mSlots.size())
- return *emptyBeingSlot;
-
- return mSlots[slot];
-}
-
-ItemColor Being::getSpriteColor(const int slot) const restrict2
-{
- if (slot < 0 || CAST_SIZE(slot) >= mSlots.size())
- return ItemColor_one;
-
- return mSlots[slot].colorId;
-}
-
-void Being::addAfkEffect() restrict2
-{
- addSpecialEffect(mAwayEffect);
-}
-
-void Being::removeAfkEffect() restrict2
-{
- removeSpecialEffect();
-}
-
-void Being::addSpecialEffect(const int effect) restrict2
-{
- if ((effectManager != nullptr) &&
- ParticleEngine::enabled &&
- (mSpecialParticle == nullptr) &&
- effect != -1)
- {
- mSpecialParticle = effectManager->triggerReturn(effect, this);
- }
-}
-
-void Being::removeSpecialEffect() restrict2
-{
- if ((effectManager != nullptr) && (mSpecialParticle != nullptr))
- {
- mChildParticleEffects.removeLocally(mSpecialParticle);
- mSpecialParticle = nullptr;
- }
- delete2(mAnimationEffect);
-}
-
-void Being::updateAwayEffect() restrict2
-{
- if (mAway)
- addAfkEffect();
- else
- removeAfkEffect();
-}
-
-void Being::addEffect(const std::string &restrict name) restrict2
-{
- delete mAnimationEffect;
- mAnimationEffect = AnimatedSprite::load(
- paths.getStringValue("sprites") + name);
-}
-
-void Being::playSfx(const SoundInfo &sound,
- Being *const being,
- const bool main,
- const int x, const int y) const restrict2
-{
- BLOCK_START("Being::playSfx")
-
- if (being != nullptr)
- {
- // here need add timer and delay sound
- const int time = tick_time;
- if (main)
- {
- being->mNextSound.sound = nullptr;
- being->mNextSound.time = time + sound.delay;
- soundManager.playSfx(sound.sound, x, y);
- }
- else if (mNextSound.time <= time)
- { // old event sound time is gone. we can play new sound
- being->mNextSound.sound = nullptr;
- being->mNextSound.time = time + sound.delay;
- soundManager.playSfx(sound.sound, x, y);
- }
- else
- { // old event sound in progress. need save sound and wait
- being->mNextSound.sound = &sound;
- being->mNextSound.x = x;
- being->mNextSound.y = y;
- }
- }
- else
- {
- soundManager.playSfx(sound.sound, x, y);
- }
- BLOCK_END("Being::playSfx")
-}
-
-void Being::setLook(const uint16_t look) restrict2
-{
- if (mType == ActorType::Player)
- setSubtype(mSubType, look);
-}
-
-void Being::setTileCoords(const int x, const int y) restrict2
-{
- mX = x;
- mY = y;
- if (mMap != nullptr)
- {
- mPixelOffsetY = 0;
- mFixedOffsetY = mPixelOffsetY;
- mOldHeight = mMap->getHeightOffset(mX, mY);
- mNeedPosUpdate = true;
- }
-}
-
-void Being::setMap(Map *restrict const map) restrict2
-{
- mCastEndTime = 0;
- delete2(mCastingEffect);
- ActorSprite::setMap(map);
- if (mMap != nullptr)
- {
- mPixelOffsetY = mMap->getHeightOffset(mX, mY);
- mFixedOffsetY = mPixelOffsetY;
- mOldHeight = 0;
- mNeedPosUpdate = true;
- }
-}
-
-void Being::removeAllItemsParticles() restrict2
-{
- FOR_EACH (SpriteParticleInfoIter, it, mSpriteParticles)
- delete (*it).second;
- mSpriteParticles.clear();
-}
-
-void Being::addItemParticles(const int id,
- const SpriteDisplay &restrict display) restrict2
-{
- const SpriteParticleInfoIter it = mSpriteParticles.find(id);
- ParticleInfo *restrict pi = nullptr;
- if (it == mSpriteParticles.end())
- {
- pi = new ParticleInfo;
- mSpriteParticles[id] = pi;
- }
- else
- {
- pi = (*it).second;
- }
-
- if ((pi == nullptr) || !pi->particles.empty())
- return;
-
- // setup particle effects
- if (ParticleEngine::enabled &&
- (particleEngine != nullptr))
- {
- FOR_EACH (StringVectCIter, itr, display.particles)
- {
- Particle *const p = particleEngine->addEffect(*itr, 0, 0);
- controlCustomParticle(p);
- pi->files.push_back(*itr);
- pi->particles.push_back(p);
- }
- }
- else
- {
- FOR_EACH (StringVectCIter, itr, display.particles)
- pi->files.push_back(*itr);
- }
-}
-
-void Being::addItemParticlesCards(const int id,
- const SpriteDisplay &restrict display,
- const CardsList &cards) restrict2
-{
- const SpriteParticleInfoIter it = mSpriteParticles.find(id);
- ParticleInfo *restrict pi = nullptr;
- if (it == mSpriteParticles.end())
- {
- pi = new ParticleInfo;
- mSpriteParticles[id] = pi;
- }
- else
- {
- pi = (*it).second;
- }
-
- if ((pi == nullptr) || !pi->particles.empty())
- return;
-
- // setup particle effects
- if (ParticleEngine::enabled &&
- (particleEngine != nullptr))
- {
- FOR_EACH (StringVectCIter, itr, display.particles)
- {
- Particle *const p = particleEngine->addEffect(*itr, 0, 0);
- controlCustomParticle(p);
- pi->files.push_back(*itr);
- pi->particles.push_back(p);
- }
- for (int f = 0; f < maxCards; f ++)
- {
- const int cardId = cards.cards[f];
- if (!Item::isItem(cardId))
- continue;
- const ItemInfo &info = ItemDB::get(cardId);
- const SpriteDisplay &restrict display2 = info.getDisplay();
- FOR_EACH (StringVectCIter, itr, display2.particles)
- {
- Particle *const p = particleEngine->addEffect(*itr, 0, 0);
- controlCustomParticle(p);
- pi->files.push_back(*itr);
- pi->particles.push_back(p);
- }
- }
- }
- else
- {
- FOR_EACH (StringVectCIter, itr, display.particles)
- {
- pi->files.push_back(*itr);
- }
- for (int f = 0; f < maxCards; f ++)
- {
- const int cardId = cards.cards[f];
- if (!Item::isItem(cardId))
- continue;
- const ItemInfo &info = ItemDB::get(cardId);
- const SpriteDisplay &restrict display2 = info.getDisplay();
- FOR_EACH (StringVectCIter, itr, display2.particles)
- {
- pi->files.push_back(*itr);
- }
- }
- }
-}
-
-void Being::removeItemParticles(const int id) restrict2
-{
- const SpriteParticleInfoIter it = mSpriteParticles.find(id);
- if (it == mSpriteParticles.end())
- return;
- ParticleInfo *restrict const pi = (*it).second;
- if (pi != nullptr)
- {
- FOR_EACH (STD_VECTOR<Particle*>::const_iterator, itp, pi->particles)
- mChildParticleEffects.removeLocally(*itp);
- delete pi;
- }
- mSpriteParticles.erase(it);
-}
-
-void Being::recreateItemParticles() restrict2
-{
- FOR_EACH (SpriteParticleInfoIter, it, mSpriteParticles)
- {
- ParticleInfo *restrict const pi = (*it).second;
- if ((pi != nullptr) && !pi->files.empty())
- {
- FOR_EACH (STD_VECTOR<Particle*>::const_iterator,
- itp, pi->particles)
- {
- mChildParticleEffects.removeLocally(*itp);
- }
-
- FOR_EACH (STD_VECTOR<std::string>::const_iterator, str, pi->files)
- {
- Particle *const p = particleEngine->addEffect(
- *str, 0, 0);
- controlCustomParticle(p);
- pi->particles.push_back(p);
- }
- }
- }
-}
-
-void Being::setTeamId(const uint16_t teamId) restrict2
-{
- if (mTeamId != teamId)
- {
- mTeamId = teamId;
- showTeamBadge(mTeamId != 0);
- updateColors();
- }
-}
-
-void Being::showTeamBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Team]);
- if (show &&
- mTeamId != 0u &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string name = paths.getStringValue("badges") +
- paths.getStringValue(strprintf("team%dbadge",
- mTeamId));
- if (!name.empty())
- mBadges[BadgeIndex::Team] = AnimatedSprite::load(name);
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-void Being::showBadges(const bool show) restrict2
-{
- showTeamBadge(show);
- showGuildBadge(show);
- showGmBadge(show);
- showPartyBadge(show);
- showNameBadge(show);
- showShopBadge(show);
- showInactiveBadge(show);
- showAwayBadge(show);
-}
-
-void Being::showPartyBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Party]);
- if (show &&
- !mPartyName.empty() &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = BadgesDB::getPartyBadge(mPartyName);
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Party] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-
-void Being::setPartyName(const std::string &restrict name) restrict2
-{
- if (mPartyName != name)
- {
- mPartyName = name;
- showPartyBadge(!mPartyName.empty());
- }
-}
-
-void Being::showShopBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Shop]);
- if (show &&
- mShop &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = paths.getStringValue("shopbadge");
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Shop] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-void Being::showInactiveBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Inactive]);
- if (show &&
- mInactive &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = paths.getStringValue("inactivebadge");
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Inactive] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-void Being::showAwayBadge(const bool show) restrict2
-{
- delete2(mBadges[BadgeIndex::Away]);
- if (show &&
- mAway &&
- mShowBadges != BadgeDrawType::Hide)
- {
- const std::string badge = paths.getStringValue("awaybadge");
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Away] = AnimatedSprite::load(
- paths.getStringValue("badges") + badge);
- }
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-void Being::updateBadgesCount() restrict2
-{
- mBadgesCount = 0;
- for_each_badges()
- {
- if (mBadges[f] != nullptr)
- mBadgesCount ++;
- }
-}
-
-void Being::setChat(ChatObject *restrict const obj) restrict2
-{
- delete mChat;
- mChat = obj;
-}
-
-void Being::setSellBoard(const std::string &restrict text) restrict2
-{
- mShop = !text.empty() || !mBuyBoard.empty();
- mSellBoard = text;
- updateName();
- showShopBadge(mShop);
-}
-
-void Being::setBuyBoard(const std::string &restrict text) restrict2
-{
- mShop = !text.empty() || !mSellBoard.empty();
- mBuyBoard = text;
- updateName();
- showShopBadge(mShop);
-}
-
-void Being::enableShop(const bool b) restrict2
-{
- mShop = b;
- updateName();
- showShopBadge(mShop);
-}
-
-bool Being::isBuyShopEnabled() const restrict2
-{
- return mShop && (Net::getNetworkType() == ServerType::TMWATHENA ||
- !mBuyBoard.empty());
-}
-
-bool Being::isSellShopEnabled() const restrict2
-{
- return mShop && (Net::getNetworkType() == ServerType::TMWATHENA ||
- !mSellBoard.empty());
-}
-
-void Being::serverRemove() restrict2 noexcept2
-{
- // remove some flags what can survive player remove and next visible
- mTrickDead = false;
-}
-
-void Being::addCast(const int dstX,
- const int dstY,
- const int skillId,
- const int skillLevel,
- const int range,
- const int waitTimeTicks)
-{
- if (waitTimeTicks <= 0)
- {
- mCastEndTime = 0;
- return;
- }
- mCastEndTime = tick_time + waitTimeTicks;
- SkillData *const data = skillDialog->getSkillDataByLevel(
- skillId,
- skillLevel);
- delete2(mCastingEffect);
- if (data != nullptr)
- {
- const std::string castingAnimation = data->castingAnimation;
- mCastingEffect = new CastingEffect(skillId,
- skillLevel,
- castingAnimation,
- dstX,
- dstY,
- range);
- mCastingEffect->setMap(mMap);
- }
- else
- {
- reportAlways("Want to draw casting for unknown skill %d",
- skillId);
- }
-}
-
-void Being::removeHorse() restrict2
-{
- delete_all(mUpHorseSprites);
- mUpHorseSprites.clear();
- delete_all(mDownHorseSprites);
- mDownHorseSprites.clear();
-}
-
-void Being::setRiding(const bool b) restrict2
-{
- if (serverFeatures->haveExtendedRiding())
- return;
-
- if (b == (mHorseId != 0))
- return;
- if (b)
- setHorse(1);
- else
- setHorse(0);
-}
-
-void Being::setHorse(const int horseId) restrict2
-{
- if (mHorseId == horseId)
- return;
- mHorseId = horseId;
- setAction(mAction, 0);
- removeHorse();
- if (mHorseId != 0)
- {
- mHorseInfo = HorseDB::get(horseId);
- if (mHorseInfo != nullptr)
- {
- FOR_EACH (SpriteRefs, it, mHorseInfo->downSprites)
- {
- const SpriteReference *restrict const ref = *it;
- AnimatedSprite *const sprite = AnimatedSprite::load(
- ref->sprite,
- ref->variant);
- mDownHorseSprites.push_back(sprite);
- sprite->play(mSpriteAction);
- sprite->setSpriteDirection(mSpriteDirection);
- }
- FOR_EACH (SpriteRefs, it, mHorseInfo->upSprites)
- {
- const SpriteReference *restrict const ref = *it;
- AnimatedSprite *const sprite = AnimatedSprite::load(
- ref->sprite,
- ref->variant);
- mUpHorseSprites.push_back(sprite);
- sprite->play(mSpriteAction);
- sprite->setSpriteDirection(mSpriteDirection);
- }
- }
- }
- else
- {
- mHorseInfo = nullptr;
- }
-}
-
-void Being::setTrickDead(const bool b) restrict2
-{
- if (b != mTrickDead)
- {
- mTrickDead = b;
- setAction(mAction, 0);
- }
-}
-
-void Being::setSpiritBalls(const unsigned int balls) restrict2
-{
- if (!ParticleEngine::enabled)
- {
- mSpiritBalls = balls;
- return;
- }
-
- if (balls > mSpiritBalls)
- {
- const int effectId = paths.getIntValue("spiritEffectId");
- if (effectId != -1)
- addSpiritBalls(balls - mSpiritBalls, effectId);
- }
- else if (balls < mSpiritBalls)
- {
- removeSpiritBalls(mSpiritBalls - balls);
- }
- mSpiritBalls = balls;
-}
-
-void Being::addSpiritBalls(const unsigned int balls,
- const int effectId) restrict2
-{
- if (effectManager == nullptr)
- return;
- for (unsigned int f = 0; f < balls; f ++)
- {
- Particle *const particle = effectManager->triggerReturn(
- effectId,
- this);
- mSpiritParticles.push_back(particle);
- }
-}
-
-void Being::removeSpiritBalls(const unsigned int balls) restrict2
-{
- if (particleEngine == nullptr)
- return;
- for (unsigned int f = 0; f < balls && !mSpiritParticles.empty(); f ++)
- {
- const Particle *restrict const particle = mSpiritParticles.back();
- mChildParticleEffects.removeLocally(particle);
- mSpiritParticles.pop_back();
- }
-}
-
-void Being::stopCast(const bool b)
-{
- if (b && mAction == BeingAction::CAST)
- setAction(BeingAction::STAND, 0);
-}
-
-void Being::fixDirectionOffsets(int &offsetX,
- int &offsetY) const
-{
- const uint8_t dir = mDirection;
- if ((dir & BeingDirection::DOWN) != 0)
- {
- // do nothing
- }
- else if ((dir & BeingDirection::UP) != 0)
- {
- offsetX = -offsetX;
- offsetY = -offsetY;
- }
- else if ((dir & BeingDirection::LEFT) != 0)
- {
- const int tmp = offsetY;
- offsetY = offsetX;
- offsetX = -tmp;
- }
- else if ((dir & BeingDirection::RIGHT) != 0)
- {
- const int tmp = offsetY;
- offsetY = -offsetX;
- offsetX = tmp;
- }
-}
-
-void Being::setLanguageId(const int lang) restrict2 noexcept2
-{
- if (lang != mLanguageId)
- {
- delete2(mBadges[BadgeIndex::Lang]);
- const std::string &badge = LanguageDb::getIcon(lang);
- if (!badge.empty())
- {
- mBadges[BadgeIndex::Lang] = AnimatedSprite::load(pathJoin(
- paths.getStringValue("languageIcons"),
- badge));
- }
-
- mLanguageId = lang;
- }
- updateBadgesCount();
- updateBadgesPosition();
-}
-
-Being *Being::createBeing(const BeingId id,
- const ActorTypeT type,
- const BeingTypeId subType,
- Map *const map)
-{
- Being *const being = new Being(id,
- type);
- being->postInit(subType,
- map);
- return being;
-}