diff options
Diffstat (limited to 'src/being')
30 files changed, 0 insertions, 15895 deletions
diff --git a/src/being/actor.cpp b/src/being/actor.cpp deleted file mode 100644 index a881c005e..000000000 --- a/src/being/actor.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/actor.h" - -#include "resources/map/map.h" - -#include "debug.h" - -Actor::Actor() : - mPixelX(0), - mPixelY(0), - mMap(nullptr), - mPos(), - mYDiff(0), - mMapActor() -{ -} - -Actor::~Actor() -{ - if (mMap != nullptr) - { - mMap->removeActor(mMapActor); - mMap = nullptr; - } -} - -void Actor::setMap(Map *const map) -{ - // Remove Actor from potential previous map - if (mMap != nullptr) - mMap->removeActor(mMapActor); - - mMap = map; - - // Add Actor to potential new map - if (mMap != nullptr) - mMapActor = mMap->addActor(this); -} - -int Actor::getTileX() const -{ - if (mMap == nullptr || - mMap->getTileWidth() == 0) - { - return 0; - } - - return getPixelX() / mMap->getTileWidth(); -} - -int Actor::getTileY() const -{ - if (mMap == nullptr || - mMap->getTileHeight() == 0) - { - return 0; - } - - return getPixelY() / mMap->getTileHeight(); -} - -void Actor::setPixelPositionF(const Vector &restrict pos) restrict2 -{ - mPos = pos; - mPixelX = CAST_S32(mPos.x); - mPixelY = CAST_S32(mPos.y); -} diff --git a/src/being/actor.h b/src/being/actor.h deleted file mode 100644 index 50a9dca24..000000000 --- a/src/being/actor.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/>. - */ - -#ifndef BEING_ACTOR_H -#define BEING_ACTOR_H - -#include "vector.h" - -#include "utils/cast.h" - -#include <list> - -#include "localconsts.h" - -class Actor; -class Graphics; -class Map; - -typedef std::list<Actor*> Actors; -typedef Actors::const_iterator ActorsCIter; - -class Actor notfinal -{ - public: - A_DELETE_COPY(Actor) - - virtual ~Actor(); - - /** - * Draws the Actor to the given graphics context. - * - * Note: this function could be simplified if the graphics context - * would support setting a translation offset. It already does this - * partly with the clipping rectangle support. - */ - virtual void draw(Graphics *const graphics, - const int offsetX, - const int offsetY) const A_NONNULL(2) = 0; - - /** - * Returns the horizontal size of the actors graphical representation - * in pixels or 0 when it is undefined. - */ - virtual int getWidth() const A_WARN_UNUSED - { return 0; } - - /** - * Returns the vertical size of the actors graphical representation - * in pixels or 0 when it is undefined. - */ - virtual int getHeight() const A_WARN_UNUSED - { return 0; } - - /** - * Returns the pixel position of this actor. - */ - const Vector &getPixelPositionF() const noexcept2 A_WARN_UNUSED - { return mPos; } - - /** - * Sets the pixel position of this actor. - */ - virtual void setPixelPositionF(const Vector &restrict pos) restrict2; - - /** - * Returns the pixels X coordinate of the actor. - */ - int getPixelX() const noexcept2 A_WARN_UNUSED - { return CAST_S32(mPos.x); } - - /** - * Returns the pixel Y coordinate of the actor. - */ - virtual int getPixelY() const A_WARN_UNUSED - { return CAST_S32(mPos.y); } - - /** - * Returns the pixel Y coordinate of the actor for sorting only. - */ - virtual int getSortPixelY() const A_WARN_UNUSED - { return CAST_S32(mPos.y) - mYDiff; } - - /** - * Returns the x coordinate in tiles of the actor. - */ - virtual int getTileX() const A_WARN_UNUSED; - - /** - * Returns the y coordinate in tiles of the actor. - */ - virtual int getTileY() const A_WARN_UNUSED; - - /** - * Returns the number of Image layers used to draw the actor. - */ - virtual int getNumberOfLayers() const A_WARN_UNUSED - { return 0; } - - /** - * Returns the current alpha value used to draw the actor. - */ - virtual float getAlpha() const A_WARN_UNUSED = 0; - - /** - * Sets the alpha value used to draw the actor. - */ - virtual void setAlpha(float alpha) = 0; - - virtual void setMap(Map *const map); - - const Map* getMap() const noexcept2 A_WARN_UNUSED - { return mMap; } - - int mPixelX; - int mPixelY; - - protected: - Actor(); - - Map *mMap; - Vector mPos; /**< Position in pixels relative to map. */ - int mYDiff; - - private: - Actors::iterator mMapActor; -}; - -#endif // BEING_ACTOR_H diff --git a/src/being/actorsprite.cpp b/src/being/actorsprite.cpp deleted file mode 100644 index 6594c7e3c..000000000 --- a/src/being/actorsprite.cpp +++ /dev/null @@ -1,602 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/actorsprite.h" - -#include "configuration.h" -#include "settings.h" -#include "statuseffect.h" - -#include "being/localplayer.h" - -#include "const/utils/timer.h" - -#include "gui/theme.h" - -#include "listeners/debugmessagelistener.h" - -#include "particle/particle.h" - -#include "resources/db/statuseffectdb.h" - -#include "resources/loaders/imageloader.h" - -#include "resources/sprite/animatedsprite.h" -#include "resources/sprite/imagesprite.h" -#include "resources/sprite/spritereference.h" - -#include "utils/checkutils.h" -#include "utils/delete2.h" -#include "utils/foreach.h" -#include "utils/timer.h" - -#include "debug.h" - -#define for_each_cursors() \ - for (int size = CAST_S32(TargetCursorSize::SMALL); \ - size < CAST_S32(TargetCursorSize::NUM_TC); \ - size ++) \ - { \ - for (int type = CAST_S32(TargetCursorType::NORMAL); \ - type < CAST_S32(TargetCursorType::NUM_TCT); \ - type ++) \ - -#define end_foreach } - -static const unsigned int STATUS_EFFECTS = 32; - -AnimatedSprite *ActorSprite::targetCursor - [CAST_SIZE(TargetCursorType::NUM_TCT)] - [CAST_SIZE(TargetCursorSize::NUM_TC)]; -bool ActorSprite::loaded = false; - -ActorSprite::ActorSprite(const BeingId id) : - CompoundSprite(), - Actor(), - mStatusEffects(), - mStatusParticleEffects(), - mChildParticleEffects(&mStatusParticleEffects, false), - mHorseId(0), - mId(id), - mUsedTargetCursor(nullptr), - mActorSpriteListeners(), - mCursorPaddingX(0), - mCursorPaddingY(0), - mMustResetParticles(false), - mPoison(false), - mHaveCart(false), - mTrickDead(false) -{ -} - -ActorSprite::~ActorSprite() -{ - mChildParticleEffects.clear(); - mMustResetParticles = true; - - mUsedTargetCursor = nullptr; - - if (localPlayer != nullptr && - localPlayer != this && - localPlayer->getTarget() == this) - { - localPlayer->setTarget(nullptr); - } - - // Notify listeners of the destruction. - FOR_EACH (ActorSpriteListenerIterator, iter, mActorSpriteListeners) - { - if (reportFalse(*iter)) - (*iter)->actorSpriteDestroyed(*this); - } -} - -void ActorSprite::logic() -{ - BLOCK_START("ActorSprite::logic") - // Update sprite animations - update(tick_time * MILLISECONDS_IN_A_TICK); - - // Restart status/particle effects, if needed - if (mMustResetParticles) - { - mMustResetParticles = false; - FOR_EACH (std::set<int32_t>::const_iterator, it, mStatusEffects) - { - const StatusEffect *const effect - = StatusEffectDB::getStatusEffect(*it, Enable_true); - if (effect != nullptr && - effect->mIsPersistent) - { - updateStatusEffect(*it, - Enable_true, - IsStart_false); - } - } - } - - // Update particle effects - mChildParticleEffects.moveTo(mPos.x, mPos.y); - BLOCK_END("ActorSprite::logic") -} - -void ActorSprite::setMap(Map *const map) -{ - Actor::setMap(map); - - // Clear particle effect list because child particles became invalid - mChildParticleEffects.clear(); - mMustResetParticles = true; // Reset status particles on next redraw -} - -void ActorSprite::controlAutoParticle(Particle *const particle) -{ - if (particle != nullptr) - { - particle->setActor(mId); - mChildParticleEffects.addLocally(particle); - } -} - -void ActorSprite::controlCustomParticle(Particle *const particle) -{ - if (particle != nullptr) - { - // The effect may not die without the beings permission or we segfault - particle->disableAutoDelete(); - mChildParticleEffects.addLocally(particle); - } -} - -void ActorSprite::controlParticleDeleted(const Particle *const particle) -{ - if (particle != nullptr) - mChildParticleEffects.removeLocally(particle); -} - -void ActorSprite::setTargetType(const TargetCursorTypeT type) -{ - if (type == TargetCursorType::NONE) - { - untarget(); - } - else - { - const size_t sz = CAST_SIZE(getTargetCursorSize()); - mUsedTargetCursor = targetCursor[CAST_S32(type)][sz]; - if (mUsedTargetCursor != nullptr) - { - static const int targetWidths[CAST_SIZE( - TargetCursorSize::NUM_TC)] - = {0, 0, 0}; - static const int targetHeights[CAST_SIZE( - TargetCursorSize::NUM_TC)] - = {-mapTileSize / 2, -mapTileSize / 2, -mapTileSize}; - - mCursorPaddingX = CAST_S32(targetWidths[sz]); - mCursorPaddingY = CAST_S32(targetHeights[sz]); - } - } -} - -void ActorSprite::setStatusEffect(const int32_t index, - const Enable active, - const IsStart start) -{ - const Enable wasActive = fromBool( - mStatusEffects.find(index) != mStatusEffects.end(), Enable); - - if (active != wasActive) - { - updateStatusEffect(index, active, start); - if (active == Enable_true) - { - mStatusEffects.insert(index); - } - else - { - mStatusEffects.erase(index); - } - } -} - -// function for legacy configs only. Must be removed in future -void ActorSprite::setStatusEffectBlock(const int offset, - const uint16_t newEffects) -{ - for (unsigned i = 0; i < STATUS_EFFECTS; i++) - { - const bool val = (newEffects & (1 << i)) > 0; - const int32_t index = StatusEffectDB::blockIdToId( - offset + i); // block-id (offset + i) to id (index) - - if (index != -1) - { - setStatusEffect(index, - fromBool(val, Enable), - IsStart_true); - } - else if (val && config.getBoolValue("unimplimentedLog")) - { - const std::string str = strprintf( - "Error: unknown effect by block-index. " - "Offset: %d, effect int: %d, i: %u", - offset, CAST_S32(newEffects), i); - logger->log(str); - DebugMessageListener::distributeEvent(str); - } - } -} - -static void applyEffectByOption(ActorSprite *const actor, - uint32_t option, - const char *const name, - const OptionsMap& options) -{ - FOR_EACH (OptionsMapCIter, it, options) - { - const uint32_t opt = (*it).first; - const int32_t id = (*it).second; - const Enable enable = (opt & option) != 0 ? Enable_true : Enable_false; - option |= opt; - option ^= opt; - actor->setStatusEffect(id, - enable, - IsStart_false); - } - if (option != 0U && - config.getBoolValue("unimplimentedLog")) - { - const std::string str = strprintf( - "Error: unknown effect by %s. " - "Left value: %u", - name, - option); - logger->log(str); - DebugMessageListener::distributeEvent(str); - } -} - -static void applyEffectByOption1(ActorSprite *const actor, - uint32_t option, - const char *const name, - const OptionsMap& options) -{ - FOR_EACH (OptionsMapCIter, it, options) - { - const uint32_t opt = (*it).first; - const int32_t id = (*it).second; - if (opt == option) - { - actor->setStatusEffect(id, - Enable_true, - IsStart_false); - option = 0U; - } - else - { - actor->setStatusEffect(id, - Enable_false, - IsStart_false); - } - } - if (option != 0 && - config.getBoolValue("unimplimentedLog")) - { - const std::string str = strprintf( - "Error: unknown effect by %s. " - "Left value: %u", - name, - option); - logger->log(str); - DebugMessageListener::distributeEvent(str); - } -} - -void ActorSprite::setStatusEffectOpitons(const uint32_t option, - const uint32_t opt1, - const uint32_t opt2, - const uint32_t opt3) -{ - if (settings.legacyEffects == false) - { - applyEffectByOption(this, option, "option", - StatusEffectDB::getOptionMap()); - applyEffectByOption1(this, opt1, "opt1", - StatusEffectDB::getOpt1Map()); - applyEffectByOption(this, opt2, "opt2", - StatusEffectDB::getOpt2Map()); - applyEffectByOption(this, opt3, "opt3", - StatusEffectDB::getOpt3Map()); - } - else - { - uint32_t statusEffects = opt2; - statusEffects |= option << 16; - setStatusEffectBlock(0, - CAST_U16((statusEffects >> 16) & 0xffffU)); - setStatusEffectBlock(16, - CAST_U16(statusEffects & 0xffffU)); - setStatusEffectBlock(32, - CAST_U16(opt3)); - } -} - -void ActorSprite::setStatusEffectOpitons(const uint32_t option, - const uint32_t opt1, - const uint32_t opt2) -{ - if (settings.legacyEffects == false) - { - applyEffectByOption(this, option, "option", - StatusEffectDB::getOptionMap()); - applyEffectByOption1(this, opt1, "opt1", - StatusEffectDB::getOpt1Map()); - applyEffectByOption(this, opt2, "opt2", - StatusEffectDB::getOpt2Map()); - } - else - { - uint32_t statusEffects = opt2; - statusEffects |= option << 16; - setStatusEffectBlock(0, - CAST_U16((statusEffects >> 16) & 0xffffU)); - setStatusEffectBlock(16, - CAST_U16(statusEffects & 0xffffU)); - } -} - -void ActorSprite::setStatusEffectOpiton0(const uint32_t option) -{ - if (settings.legacyEffects == false) - { - applyEffectByOption(this, option, "option", - StatusEffectDB::getOptionMap()); - } - else - { - const uint32_t statusEffects = option << 16; - setStatusEffectBlock(0, - CAST_U16((statusEffects >> 16) & 0xffff)); - } -} - -void ActorSprite::updateStatusEffect(const int32_t index, - const Enable newStatus, - const IsStart start) -{ - StatusEffect *const effect = StatusEffectDB::getStatusEffect( - index, newStatus); - if (effect == nullptr) - return; - if (effect->mIsPoison && getType() == ActorType::Player) - setPoison(newStatus == Enable_true); - else if (effect->mIsCart && localPlayer == this) - setHaveCart(newStatus == Enable_true); - else if (effect->mIsRiding) - setRiding(newStatus == Enable_true); - else if (effect->mIsTrickDead) - setTrickDead(newStatus == Enable_true); - else if (effect->mIsPostDelay) - stopCast(newStatus == Enable_true); - handleStatusEffect(effect, index, newStatus, start); -} - -void ActorSprite::handleStatusEffect(const StatusEffect *const effect, - const int32_t effectId, - const Enable newStatus, - const IsStart start) -{ - if (effect == nullptr) - return; - - if (newStatus == Enable_true) - { - if (effectId >= 0) - { - Particle *particle = nullptr; - if (start == IsStart_true) - particle = effect->getStartParticle(); - if (particle == nullptr) - particle = effect->getParticle(); - if (particle != nullptr) - mStatusParticleEffects.setLocally(effectId, particle); - } - } - else - { - mStatusParticleEffects.delLocally(effectId); - } -} - -void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, - const ForceDisplay forceDisplay, - const DisplayTypeT displayType, - const std::string &color) -{ - clear(); - - FOR_EACH (SpriteRefs, it, display.sprites) - { - if (*it == nullptr) - continue; - const std::string file = pathJoin(paths.getStringValue("sprites"), - combineDye3((*it)->sprite, color)); - - const int variant = (*it)->variant; - addSprite(AnimatedSprite::delayedLoad(file, variant)); - } - - // Ensure that something is shown, if desired - if (mSprites.empty() && forceDisplay == ForceDisplay_true) - { - if (display.image.empty()) - { - addSprite(AnimatedSprite::delayedLoad(pathJoin( - paths.getStringValue("sprites"), - paths.getStringValue("spriteErrorFile")))); - } - else - { - std::string imagePath; - switch (displayType) - { - case DisplayType::Item: - default: - imagePath = pathJoin(paths.getStringValue("itemIcons"), - display.image); - break; - case DisplayType::Floor: - imagePath = pathJoin(paths.getStringValue("itemIcons"), - display.floor); - break; - } - imagePath = combineDye2(imagePath, color); - Image *img = Loader::getImage(imagePath); - - if (img == nullptr) - img = Theme::getImageFromTheme("unknown-item.png"); - - addSprite(new ImageSprite(img)); - if (img != nullptr) - img->decRef(); - } - } - - mChildParticleEffects.clear(); - - // setup particle effects - if (ParticleEngine::enabled && (particleEngine != nullptr)) - { - FOR_EACH (StringVectCIter, itr, display.particles) - { - Particle *const p = particleEngine->addEffect(*itr, 0, 0); - controlAutoParticle(p); - } - } - - mMustResetParticles = true; -} - -void ActorSprite::load() -{ - if (loaded) - unload(); - - initTargetCursor(); - - loaded = true; -} - -void ActorSprite::unload() -{ - if (reportTrue(!loaded)) - return; - - cleanupTargetCursors(); - loaded = false; -} - -void ActorSprite::addActorSpriteListener(ActorSpriteListener *const listener) -{ - mActorSpriteListeners.push_front(listener); -} - -void ActorSprite::removeActorSpriteListener(ActorSpriteListener *const - listener) -{ - mActorSpriteListeners.remove(listener); -} - -static const char *cursorType(const TargetCursorTypeT type) -{ - switch (type) - { - case TargetCursorType::IN_RANGE: - return "in-range"; - default: - case TargetCursorType::NONE: - case TargetCursorType::NUM_TCT: - case TargetCursorType::NORMAL: - return "normal"; - } -} - -static const char *cursorSize(const TargetCursorSizeT size) -{ - switch (size) - { - case TargetCursorSize::LARGE: - return "l"; - case TargetCursorSize::MEDIUM: - return "m"; - default: - case TargetCursorSize::NUM_TC: - case TargetCursorSize::SMALL: - return "s"; - } -} - -void ActorSprite::initTargetCursor() -{ - static const std::string targetCursorFile("target-cursor-%s-%s.xml"); - - // Load target cursors - for_each_cursors() - { - targetCursor[type][size] = AnimatedSprite::load( - Theme::resolveThemePath(strprintf( - targetCursorFile.c_str(), - cursorType(static_cast<TargetCursorTypeT>(type)), - cursorSize(static_cast<TargetCursorSizeT>(size))))); - } - end_foreach -} - -void ActorSprite::cleanupTargetCursors() -{ - for_each_cursors() - { - delete2(targetCursor[type][size]) - } - end_foreach -} - -std::string ActorSprite::getStatusEffectsString() const -{ - std::string effectsStr; - if (!mStatusEffects.empty()) - { - FOR_EACH (std::set<int32_t>::const_iterator, it, mStatusEffects) - { - const StatusEffect *const effect = - StatusEffectDB::getStatusEffect( - *it, - Enable_true); - if (effect == nullptr) - continue; - if (!effectsStr.empty()) - effectsStr.append(", "); - effectsStr.append(effect->mName); - } - } - return effectsStr; -} diff --git a/src/being/actorsprite.h b/src/being/actorsprite.h deleted file mode 100644 index db912e059..000000000 --- a/src/being/actorsprite.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/>. - */ - -#ifndef BEING_ACTORSPRITE_H -#define BEING_ACTORSPRITE_H - -#include "being/actor.h" -#include "being/compoundsprite.h" - -#include "const/resources/map/map.h" - -#include "enums/being/actortype.h" -#include "enums/being/targetcursorsize.h" -#include "enums/being/targetcursortype.h" - -#include "enums/simpletypes/beingid.h" -#include "enums/simpletypes/enable.h" -#include "enums/simpletypes/forcedisplay.h" -#include "enums/simpletypes/isstart.h" - -#include "enums/resources/displaytype.h" - -#include "enums/resources/map/blocktype.h" - -#include "particle/particlelist.h" -#include "particle/particlevector.h" - -#include "localconsts.h" - -class AnimatedSprite; -class StatusEffect; -class ActorSpriteListener; - -struct SpriteDisplay; - -class ActorSprite notfinal : public CompoundSprite, public Actor -{ - public: - explicit ActorSprite(const BeingId id); - - A_DELETE_COPY(ActorSprite) - - virtual ~ActorSprite(); - - BeingId getId() const noexcept2 A_WARN_UNUSED - { return mId; } - - void setId(const BeingId id) noexcept2 - { mId = id; } - - /** - * Returns the type of the ActorSprite. - */ - virtual ActorTypeT getType() const noexcept2 A_WARN_UNUSED - { return ActorType::Unknown; } - - virtual void logic(); - - void setMap(Map *const map) override; - - /** - * Gets the way the object blocks pathfinding for other objects - */ - virtual BlockTypeT getBlockType() const A_WARN_UNUSED - { return BlockType::NONE; } - - /** - * Take control of a particle. Particle can be auto deleted. - */ - void controlAutoParticle(Particle *const particle); - - /** - * Take control of a particle. Owner must remove particle by self. - */ - void controlCustomParticle(Particle *const particle); - - /** - * Returns the required size of a target cursor for this being. - */ - virtual TargetCursorSizeT getTargetCursorSize() const A_WARN_UNUSED - { return TargetCursorSize::MEDIUM; } - - virtual int getTargetOffsetX() const A_WARN_UNUSED - { return 0; } - - virtual int getTargetOffsetY() const A_WARN_UNUSED - { return 0; } - - /** - * Sets the target animation for this actor. - */ - void setTargetType(const TargetCursorTypeT type); - - /** - * Untargets the actor. - */ - void untarget() - { mUsedTargetCursor = nullptr; } - - void setStatusEffect(const int32_t index, - const Enable active, - const IsStart start); - - void setStatusEffectOpitons(const uint32_t option, - const uint32_t opt1, - const uint32_t opt2, - const uint32_t opt3); - - void setStatusEffectOpitons(const uint32_t option, - const uint32_t opt1, - const uint32_t opt2); - - void setStatusEffectOpiton0(const uint32_t option); - - void setAlpha(const float alpha) override final - { CompoundSprite::setAlpha(alpha); } - - float getAlpha() const override final A_WARN_UNUSED - { return CompoundSprite::getAlpha(); } - - int getWidth() const override A_WARN_UNUSED - { return CompoundSprite::getWidth(); } - - int getHeight() const override A_WARN_UNUSED - { return CompoundSprite::getHeight(); } - - static void load(); - - static void unload(); - - /** - * Add an ActorSprite listener. - */ - void addActorSpriteListener(ActorSpriteListener *const listener); - - /** - * Remove an ActorSprite listener. - */ - void removeActorSpriteListener(ActorSpriteListener *const listener); - - int getActorX() const A_WARN_UNUSED - { return getPixelX() - mapTileSize / 2; } - - int getActorY() const A_WARN_UNUSED - { return getPixelY() - mapTileSize; } - - void setPoison(const bool b) - { mPoison = b; } - - bool getPoison() const A_WARN_UNUSED - { return mPoison; } - - void setHaveCart(const bool b) - { mHaveCart = b; } - - bool getHaveCart() const A_WARN_UNUSED - { return mHaveCart; } - - virtual void setRiding(const bool b) - { mHorseId = b ? 1 : 0; } - - virtual void setTrickDead(const bool b) - { mTrickDead = b; } - - bool isTrickDead() const A_WARN_UNUSED - { return mTrickDead; } - - const std::set<int32_t> &getStatusEffects() const A_WARN_UNUSED - { return mStatusEffects; } - - std::string getStatusEffectsString() const; - - virtual void stopCast(const bool b A_UNUSED) - { } - - size_t getParticlesCount() const - { - return mStatusParticleEffects.usedSize() + - mChildParticleEffects.size(); - } - - void controlParticleDeleted(const Particle *const particle); - - protected: - /** - * A status effect block is a 16 bit mask of status effects. We assign - * each such flag a block ID of offset + bitnr. - * - * These are NOT the same as the status effect indices. - */ - void setStatusEffectBlock(const int offset, - const uint16_t newEffects); - - /** - * Notify self that a status effect has flipped. - * The new flag is passed. - */ - virtual void updateStatusEffect(const int32_t index, - const Enable newStatus, - const IsStart start); - - /** - * Handle an update to a status or stun effect - * - * \param The StatusEffect to effect - * \param effectId -1 for stun, otherwise the effect index - */ - virtual void handleStatusEffect(const StatusEffect *const effect, - const int32_t effectId, - const Enable newStatus, - const IsStart start); - - void setupSpriteDisplay(const SpriteDisplay &display, - const ForceDisplay forceDisplay, - const DisplayTypeT displayType, - const std::string &color); - - /** Load the target cursors into memory */ - static void initTargetCursor(); - - /** Remove the target cursors from memory */ - static void cleanupTargetCursors(); - - /** Animated target cursors. */ - static AnimatedSprite *targetCursor - [CAST_SIZE(TargetCursorType::NUM_TCT)] - [CAST_SIZE(TargetCursorSize::NUM_TC)]; - - static bool loaded; - - /**< set of active status effects */ - std::set<int32_t> mStatusEffects; - - ParticleVector mStatusParticleEffects; - ParticleList mChildParticleEffects; - int mHorseId; - BeingId mId; - - /** Target cursor being used */ - AnimatedSprite *mUsedTargetCursor; - - typedef std::list<ActorSpriteListener*> ActorSpriteListeners; - typedef ActorSpriteListeners::iterator ActorSpriteListenerIterator; - ActorSpriteListeners mActorSpriteListeners; - - int mCursorPaddingX; - int mCursorPaddingY; - - /** Reset particle status effects on next redraw? */ - bool mMustResetParticles; - bool mPoison; - bool mHaveCart; - bool mTrickDead; -}; - -#endif // BEING_ACTORSPRITE_H 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; -} diff --git a/src/being/being.h b/src/being/being.h deleted file mode 100644 index 0ca1ce780..000000000 --- a/src/being/being.h +++ /dev/null @@ -1,1375 +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/>. - */ - -#ifndef BEING_BEING_H -#define BEING_BEING_H - -#include "position.h" - -#include "enums/being/badgeindex.h" -#include "enums/being/reachable.h" - -#include "enums/gui/usercolorid.h" - -#include "enums/simpletypes/move.h" - -#include "enums/being/visiblenamepos.h" - -#include "resources/beinginfo.h" -#include "resources/beingslot.h" - -#include "being/actorsprite.h" - -#include "enums/being/attacktype.h" -#include "enums/being/badgedrawtype.h" -#include "enums/being/beingaction.h" -#include "enums/being/gender.h" - -#include "listeners/configlistener.h" - -#include "localconsts.h" - -static const int DEFAULT_BEING_WIDTH = 32; -static const int DEFAULT_BEING_HEIGHT = 32; - -class AnimatedSprite; -class BeingCacheEntry; -class CastingEffect; -class Color; -class Equipment; -class FlashText; -class Guild; -class ItemInfo; -class Particle; -class Party; -class SpeechBubble; -class Text; - -struct ChatObject; -struct HorseInfo; -struct MissileInfo; -struct SkillInfo; -struct ParticleInfo; - -extern volatile time_t cur_time; - -struct NextSoundInfo final -{ - NextSoundInfo() noexcept2 : - sound(nullptr), - x(0), - y(0), - time(0) - { - } - - A_DELETE_COPY(NextSoundInfo) - - const SoundInfo *sound; - int x; - int y; - int time; -}; - -class Being notfinal : public ActorSprite, - public ConfigListener -{ - public: - friend class ActorManager; - friend class BeingEquipBackend; - friend class LocalPlayer; - - /** - * Constructor. - * - * @param id a unique being id - * @param subtype partly determines the type of the being - * @param map the map the being is on - */ - Being(const BeingId id, - const ActorTypeT type); - - A_DELETE_COPY(Being) - - virtual ~Being(); - - ActorTypeT getType() const restrict2 noexcept2 override final - A_WARN_UNUSED - { return mType; } - - /** - * Removes all path nodes from this being. - */ - void clearPath() restrict2; - - /** - * Returns the time spent in the current action. - */ - int getActionTime() const restrict2 noexcept2 A_WARN_UNUSED - { return mActionTime; } - - /** - * Set the current action time. - * @see Ea::BeingHandler that set it to tick time. - */ - void setActionTime(const int actionTime) restrict2 noexcept2 - { mActionTime = actionTime; } - - /** - * Makes this being take the next tile of its path. - */ - virtual void nextTile() restrict2; - - /** - * Creates a path for the being from current position to ex and ey - */ - void setDestination(const int dstX, - const int dstY) restrict2; - - void setCachedDestination(const int dstX, - const int dstY) restrict2 noexcept2 - { mCachedX = dstX; mCachedY = dstY; } - - int getCachedX() const noexcept2 A_WARN_UNUSED - { return mCachedX; } - - int getCachedY() const noexcept2 A_WARN_UNUSED - { return mCachedY; } - - /** - * Returns the destination for this being. - */ - const Vector &getDestination() const restrict2 noexcept2 A_WARN_UNUSED - { return mDest; } - - /** - * Returns the tile x coord - */ - int getTileX() const restrict2 noexcept2 override A_WARN_UNUSED - { return mX; } - - /** - * Returns the tile y coord - */ - int getTileY() const restrict2 noexcept2 override A_WARN_UNUSED - { return mY; } - - /** - * Sets the tile x and y coord - */ - void setTileCoords(const int x, const int y) restrict2; - - /** - * Puts a "speech balloon" above this being for the specified amount - * of time. - * - * @param text The text that should appear. - * @param time The amount of time the text should stay in milliseconds. - */ - void setSpeech(const std::string &restrict text, - const std::string &restrict channel = "", - int time = 0) restrict2; - - /** - * Puts a damage bubble above this being. - * - * @param attacker the attacking being - * @param amount the amount of damage recieved (0 means miss) - * @param type the attack type - * @param attackId the attack id - * @param level the skill level - */ - void takeDamage(Being *restrict const attacker, - const int amount, - const AttackTypeT type, - const int attackId = 1, - const int level = 1) restrict2; - - /** - * Handles an attack of another being by this being. - * - * @param victim the victim being - * @param damage the amount of damage dealt (0 means miss) - * @param attackId the attack id - */ - void handleAttack(Being *restrict const victim, - const int damage, - const int attackId = 1) restrict2; - - void handleSkillCasting(Being *restrict const victim, - const int skillId, - const int skillLevel) restrict2; - - void handleSkill(Being *restrict const victim, - const int damage, - const int skillId, - const int skillLevel) restrict2; - - const ItemInfo *getEquippedWeapon() const restrict2 A_WARN_UNUSED - { return mEquippedWeapon; } - - /** - * Returns the name of the being. - */ - const std::string &getName() const restrict2 noexcept2 A_WARN_UNUSED - { return mName; } - - const std::string &getExtName() const restrict2 noexcept2 A_WARN_UNUSED - { return mExtName; } - - /** - * Sets the name for the being. - * - * @param name The name that should appear. - */ - void setName(const std::string &restrict name) restrict2; - - bool getShowName() const noexcept2 A_WARN_UNUSED - { return mShowName; } - - void setShowName(const bool doShowName) restrict2; - - /** - * Sets the name of the party the being is in. Shown in BeingPopup. - */ - void setPartyName(const std::string &restrict name) restrict2; - - const std::string &getPartyName() const restrict2 noexcept2 - A_WARN_UNUSED - { return mPartyName; } - - const std::string &getGuildName() const restrict2 noexcept2 - A_WARN_UNUSED - { return mGuildName; } - - /** - * Sets the name of the primary guild the being is in. Shown in - * BeingPopup (eventually). - */ - void setGuildName(const std::string &restrict name) restrict2; - - void setGuildPos(const std::string &restrict pos) restrict2 A_CONST; - - /** - * Adds a guild to the being. - */ - void addGuild(Guild *restrict const guild) restrict2; - - /** - * Removers a guild from the being. - */ - void removeGuild(const int id) restrict2; - - /** - * Returns a pointer to the specified guild that the being is in. - */ - const Guild *getGuild(const std::string &restrict guildName) - const restrict2 A_WARN_UNUSED; - - /** - * Returns a pointer to the specified guild that the being is in. - */ - const Guild *getGuild(const int id) const restrict2 A_WARN_UNUSED; - - /** - * Returns a pointer to the specified guild that the being is in. - */ - Guild *getGuild() const restrict2 A_WARN_UNUSED; - - /** - * Returns all guilds the being is in. - */ - const std::map<int, Guild*> &getGuilds() const restrict2 noexcept2 - A_WARN_UNUSED - { return mGuilds; } - - /** - * Removes all guilds the being is in. - */ - void clearGuilds() restrict2; - - /** - * Get number of guilds the being belongs to. - */ - int16_t getNumberOfGuilds() const restrict2 A_WARN_UNUSED - { return CAST_S16(mGuilds.size()); } - - bool isInParty() const restrict2 noexcept2 A_WARN_UNUSED - { return mParty != nullptr; } - - void setParty(Party *restrict const party) restrict2; - - void setGuild(Guild *restrict const guild) restrict2; - - void updateGuild() restrict2; - - Party *getParty() const restrict2 noexcept2 A_WARN_UNUSED - { return mParty; } - - void setSprite(const unsigned int slot, - const int id, - std::string color, - ItemColor colorId) restrict2; - - void setSpriteColor(const unsigned int slot, - const int id, - const std::string &color) restrict2; - - void setSpriteColorId(const unsigned int slot, - const int id, - ItemColor colorId) restrict2; - - void setSpriteCards(const unsigned int slot, - const int id, - const CardsList &restrict cards) restrict2; - - void setSpriteId(const unsigned int slot, - const int id) restrict2; - - void unSetSprite(const unsigned int slot) restrict2; - - void setWeaponId(const int id) restrict2; - - void setTempSprite(const unsigned int slot, - const int id) restrict2; - - void setHairTempSprite(const unsigned int slot, - const int id) restrict2; - - void updateSprite(const unsigned int slot, - const int id, - const std::string &restrict color = "") - restrict2; - - void setHairColorSpriteID(const unsigned int slot, - const int id) restrict2; - - void setSpriteColor(const unsigned int slot, - const std::string &restrict color = "") restrict2; - - /** - * Get the number of layers used to draw the being - */ - int getNumberOfLayers() const restrict2 override A_WARN_UNUSED - { return CompoundSprite::getNumberOfLayers(); } - - /** - * Performs being logic. - */ - void logic() restrict2 override; - - void botLogic() restrict2; - - /** - * Draws the speech text above the being. - */ - void drawSpeech(const int offsetX, - const int offsetY) restrict2; - - /** - * Draws the emotion picture above the being. - */ - void drawEmotion(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const restrict2 A_NONNULL(2); - - BeingTypeId getSubType() const restrict2 noexcept2 A_WARN_UNUSED - { return mSubType; } - - /** - * Set Being's subtype (mostly for view for monsters and NPCs) - */ - void setSubtype(const BeingTypeId subtype, - const uint16_t look) restrict2; - - const BeingInfo *getInfo() const restrict2 noexcept2 A_WARN_UNUSED - { return mInfo; } - - TargetCursorSizeT getTargetCursorSize() const restrict2 override final - A_WARN_UNUSED; - - int getTargetOffsetX() const restrict2 override A_WARN_UNUSED - { - if (mInfo == nullptr) - return 0; - return mInfo->getTargetOffsetX(); - } - - int getTargetOffsetY() const restrict2 override A_WARN_UNUSED - { - if (mInfo == nullptr) - return 0; - return mInfo->getTargetOffsetY(); - } - - /** - * Gets the way the object is blocked by other objects. - */ - virtual unsigned char getBlockWalkMask() const restrict2 A_WARN_UNUSED - { - if (mInfo == nullptr) - return 0; - return mInfo->getBlockWalkMask(); - } - - /** - * Gets the way the monster blocks pathfinding for other objects - */ - BlockTypeT getBlockType() const restrict2 override A_WARN_UNUSED - { - if (mInfo == nullptr) - return BlockType::NONE; - return mInfo->getBlockType(); - } - - /** - * Sets the walk speed in pixels per second. - */ - void setWalkSpeed(const int speed) restrict2 - { mWalkSpeed = speed; mSpeed = speed; } - - /** - * Gets the walk speed in pixels per second. - */ - int getWalkSpeed() const restrict2 noexcept2 A_WARN_UNUSED - { return mWalkSpeed; } - - /** - * Sets the attack speed. - */ - void setAttackSpeed(const int speed) restrict2 noexcept2 - { mAttackSpeed = speed; } - - /** - * Gets the attack speed. - */ - int getAttackSpeed() const restrict2 noexcept2 A_WARN_UNUSED - { return mAttackSpeed; } - - /** - * Sets the current action. - */ - virtual void setAction(const BeingActionT &restrict action, - const int attackId) restrict2; - - /** - * Get the being's action currently performed. - */ - BeingActionT getCurrentAction() const restrict2 noexcept2 A_WARN_UNUSED - { return mAction; } - - /** - * Returns whether this being is still alive. - */ - bool isAlive() const restrict2 noexcept2 A_WARN_UNUSED - { return mAction != BeingAction::DEAD; } - - /** - * Returns the current direction. - */ - uint8_t getDirection() const restrict2 noexcept2 A_WARN_UNUSED - { return mDirection; } - - /** - * Sets the current direction. - */ - virtual void setDirection(const uint8_t direction) restrict2; - - void setDirectionDelayed(const uint8_t direction) restrict2 noexcept2 - { mDirectionDelayed = direction; } - - uint8_t getDirectionDelayed() const restrict2 noexcept2 A_WARN_UNUSED - { return mDirectionDelayed; } - - /** - * Returns the direction the being is facing. - */ - SpriteDirection::Type getSpriteDirection() const restrict2 noexcept2 - A_WARN_UNUSED - { return mSpriteDirection; } - - void setPixelPositionF(const Vector &restrict pos) restrict2 override; - - /** - * Overloaded method provided for convenience. - * - * @see setPosition(const Vector &pos) - */ - inline void setPixelPositionF(const float x, - const float y, - const float z = 0.0F) restrict2 A_INLINE - { setPixelPositionF(Vector(x, y, z)); } - - /** - * Returns the horizontal size of the current base sprite of the being. - */ - int getWidth() const restrict2 override final A_WARN_UNUSED - { return std::max(CompoundSprite::getWidth(), DEFAULT_BEING_WIDTH); } - - /** - * Returns the vertical size of the current base sprite of the being. - */ - int getHeight() const restrict2 override final A_WARN_UNUSED - { return std::max(CompoundSprite::getHeight(), DEFAULT_BEING_HEIGHT); } - - /** - * Shoots a missile particle from this being, to target being - */ - void fireMissile(Being *restrict const victim, - const MissileInfo &restrict missile) const restrict2; - - /** - * Returns the path this being is following. An empty path is returned - * when this being isn't following any path currently. - */ - const Path &getPath() const restrict2 noexcept2 A_WARN_UNUSED - { return mPath; } - - int getDistance() const restrict2 noexcept2 A_WARN_UNUSED - { return mDistance; } - - void setDistance(const int n) restrict2 noexcept2 - { mDistance = n; } - - /** - * Set the Emoticon type and time displayed above - * the being. - */ - void setEmote(const uint8_t emotion, - const int emote_time) restrict2; - - void setState(const uint8_t state) restrict2; - - void drawPlayerSprites(Graphics *restrict const graphics, - const int posX, - const int posY) const - restrict2 A_NONNULL(2); - - void drawSpritesSDL(Graphics *restrict const graphics, - const int posX, - const int posY) const - restrict2 override final A_NONNULL(2); - - void 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 A_NONNULL(2); - - void optionChanged(const std::string &restrict value) - restrict2 override; - - void flashName(const int time) restrict2; - - int getDamageTaken() const restrict2 noexcept2 A_WARN_UNUSED - { return mDamageTaken; } - - void setDamageTaken(const int damage) restrict2 noexcept2 - { mDamageTaken = damage; } - - void updateName() restrict2; - - void setLevel(const int n) restrict2 noexcept2 - { mLevel = n; } - - virtual int getLevel() const restrict2 A_WARN_UNUSED - { return mLevel; } - - void setReachable(const ReachableT n) restrict2 noexcept2 - { mReachable = n; } - - ReachableT getReachable() const restrict2 noexcept2 A_WARN_UNUSED - { return mReachable; } - - static void reReadConfig(); - - static BeingCacheEntry* getCacheEntry(const BeingId id) A_WARN_UNUSED; - - void addToCache() const restrict2; - - bool updateFromCache() restrict2; - - /** - * Sets the gender of this being. - */ - virtual void setGender(const GenderT gender) restrict2; - - GenderT getGender() const restrict2 noexcept2 A_WARN_UNUSED - { return mGender; } - - /** - * Return sprite sit action for current environment. - */ - std::string getSitAction() const restrict2 A_WARN_UNUSED; - - std::string getCastAction() const restrict2 A_WARN_UNUSED; - - std::string getCastAction(const SkillInfo *restrict const skill) const - restrict2 A_WARN_UNUSED; - - std::string getMoveAction() const restrict2 A_WARN_UNUSED; - - std::string getDeadAction() const restrict2 A_WARN_UNUSED; - - std::string getStandAction() const restrict2 A_WARN_UNUSED; - - std::string getSpawnAction() const restrict2 A_WARN_UNUSED; - - std::string getWeaponAttackAction(const ItemInfo *restrict const - weapon) const - restrict2 A_WARN_UNUSED; - - std::string getAttackAction() const restrict2 A_WARN_UNUSED; - - std::string getAttackAction(const Attack *restrict const attack1) const - restrict2 A_WARN_UNUSED; - - /** - * Whether or not this player is a GM. - */ - bool isGM() const restrict2 noexcept2 A_WARN_UNUSED - { return mIsGM; } - - /** - * Triggers whether or not to show the name as a GM name. - */ - void setGM(const bool gm) restrict2; - - bool canTalk() const restrict2 noexcept2 A_WARN_UNUSED - { return mType == ActorType::Npc; } - - void talkTo() const restrict2; - - void draw(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 override final A_NONNULL(2); - - void drawPlayer(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawOther(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawMonster(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawPortal(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawBasic(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void setMoveTime() restrict2 noexcept2 - { mMoveTime = cur_time; } - - void setAttackTime() restrict2 noexcept2 - { mAttackTime = cur_time; } - - void setTalkTime() restrict2 noexcept2 - { mTalkTime = cur_time; } - - void setTestTime() restrict2 noexcept2 - { mTestTime = cur_time; } - - void setOtherTime() restrict2 noexcept2 - { mOtherTime = cur_time; } - - time_t getMoveTime() const restrict2 noexcept2 - { return mMoveTime; } - - time_t getAttackTime() const restrict2 noexcept2 - { return mAttackTime; } - - time_t getTalkTime() const restrict2 noexcept2 - { return mTalkTime; } - - time_t getTestTime() const restrict2 noexcept2 - { return mTestTime; } - - time_t getOtherTime() const restrict2 noexcept2 - { return mOtherTime; } - - void resetCounters() restrict2; - - void updateColors() restrict2; - - void setEnemy(const bool n) restrict2 noexcept2 - { mEnemy = n; } - - const std::string &getIp() const restrict2 noexcept2 A_WARN_UNUSED - { return mIp; } - - void setIp(const std::string &restrict ip) restrict2 noexcept2 - { mIp = ip; } - - unsigned int getPvpRank() const restrict2 noexcept2 A_WARN_UNUSED - { return mPvpRank; } - - void setPvpRank(const unsigned int rank) restrict2 noexcept2 - { mPvpRank = rank; } - - void setHP(const int hp) restrict2; - - void setMaxHP(const int hp) restrict2; - - int getHP() const restrict2 noexcept2 A_WARN_UNUSED - { return mHP; } - - int getMaxHP() const restrict2 noexcept2 A_WARN_UNUSED - { return mMaxHP; } - - uint8_t calcDirection(const int dstX, - const int dstY) const restrict2 A_WARN_UNUSED; - - uint8_t calcDirection() const restrict2 A_WARN_UNUSED; - - void setAttackDelay(const int n) restrict2 noexcept2 - { mAttackDelay = n; } - - int getAttackDelay() const restrict2 noexcept2 A_WARN_UNUSED - { return mAttackDelay; } - - int getMinHit() const restrict2 noexcept2 A_WARN_UNUSED - { return mMinHit; } - - void setMinHit(const int n) restrict2 noexcept2 - { mMinHit = n; } - - int getMaxHit() const restrict2 noexcept2 A_WARN_UNUSED - { return mMaxHit; } - - void setMaxHit(const int n) restrict2 noexcept2 - { mMaxHit = n; } - - int getCriticalHit() const restrict2 A_WARN_UNUSED - { return mCriticalHit; } - - void setCriticalHit(const int n) restrict2 noexcept2 - { mCriticalHit = n; } - - void updateHit(const int amount) restrict2; - - Equipment *getEquipment() restrict2 A_WARN_UNUSED; - - void undressItemById(const int id) restrict2; - - int getGoodStatus() const restrict2 noexcept2 A_WARN_UNUSED - { return mGoodStatus; } - - void setGoodStatus(const int n) restrict2 noexcept2 - { mGoodStatus = n; } - - std::string getGenderSign() const restrict2 A_WARN_UNUSED; - - std::string getGenderSignWithSpace() const restrict2 A_WARN_UNUSED; - - void updateComment() restrict2; - - const std::string getComment() const restrict2 noexcept2 A_WARN_UNUSED - { return mComment; } - - void setComment(const std::string &restrict n) restrict2 noexcept2 - { mComment = n; } - - static void clearCache(); - - static std::string loadComment(const std::string &restrict name, - const ActorTypeT &restrict type) - A_WARN_UNUSED; - - static void saveComment(const std::string &restrict name, - const std::string &restrict comment, - const ActorTypeT &restrict type); - - bool isAdvanced() const restrict2 noexcept2 A_WARN_UNUSED - { return mAdvanced; } - - void setAdvanced(const bool n) restrict2 - { mAdvanced = n; addToCache(); } - - bool isBuyShopEnabled() const restrict2 A_WARN_UNUSED; - - bool isSellShopEnabled() const restrict2 A_WARN_UNUSED; - - void enableShop(const bool b) restrict2; - - /** - * Sets the attack range. - */ - void setAttackRange(const int range) restrict2 noexcept2 - { mAttackRange = range; } - -/* - void attack(Being *restrict target = nullptr, - bool keep = false, - bool dontChangeEquipment = false) restrict2; - - void attack2(Being *restrict target = nullptr, - bool keep = false, - bool dontChangeEquipment = false) restrict2; -*/ - - void updatePercentHP() restrict2; - - void setRaceName(const std::string &restrict name) restrict2 noexcept2 - { mRaceName = name; } - - std::string getRaceName() const restrict2 noexcept2 A_WARN_UNUSED - { return mRaceName; } - - int getSpriteID(const int slot) const restrict2 A_WARN_UNUSED; - - const BeingSlot &getSpriteSlot(const int slot) const - restrict2 A_WARN_UNUSED; - - ItemColor getSpriteColor(const int slot) const restrict2 A_WARN_UNUSED; - - void setHairStyle(const unsigned int slot, - const int id) restrict2; - - void setHairColor(const unsigned int slot, - const ItemColor color) restrict2; - - void setHairColor(const ItemColor color) restrict2 noexcept2 - { mHairColor = color; } - - void setSpriteSlot(const unsigned int slot, - const BeingSlot &beingSlot); - - ItemColor getHairColor() const noexcept2 A_WARN_UNUSED - { return mHairColor; } - - void recalcSpritesOrder() restrict2; - - int getHitEffect(const Being *restrict const attacker, - const AttackTypeT type, - const int attackId, - const int level) const restrict2 A_WARN_UNUSED; - - CursorT getHoverCursor() const restrict2 A_WARN_UNUSED - { - return mInfo != nullptr ? - mInfo->getHoverCursor() : Cursor::CURSOR_POINTER; - } - - void addAfkEffect() restrict2; - - void removeAfkEffect() restrict2; - - void updateAwayEffect() restrict2; - - void addSpecialEffect(const int effect) restrict2; - - void removeSpecialEffect() restrict2; - - void addEffect(const std::string &restrict name) restrict2; - - void setOwner(Being *restrict const owner) restrict2 noexcept2 - { mOwner = owner; } - - Being *getOwner() const restrict2 noexcept2 - { return mOwner; } - - void playSfx(const SoundInfo &sound, - Being *const being, - const bool main, - const int x, const int y) const restrict2; - - uint16_t getLook() const restrict2 noexcept2 - { return mLook; } - - void setLook(const uint16_t look) restrict2; - - constexpr2 static uint8_t genderToInt(const GenderT sex) - A_CONST A_WARN_UNUSED - { - switch (sex) - { - case Gender::FEMALE: - case Gender::UNSPECIFIED: - default: - return 0; - case Gender::MALE: - return 1; - case Gender::OTHER: - return 3; - } - } - - constexpr2 static GenderT intToGender(const uint8_t sex) - A_CONST A_WARN_UNUSED - { - switch (sex) - { - case 0: - default: - return Gender::FEMALE; - case 1: - return Gender::MALE; - case 3: - return Gender::OTHER; - } - } - - NextSoundInfo mNextSound; - - /** - * Sets the new path for this being. - */ - void setPath(const Path &restrict path) restrict2; - - int getSortPixelY() const restrict2 override A_WARN_UNUSED - { return CAST_S32(mPos.y) - mYDiff - mSortOffsetY; } - - void setMap(Map *restrict const map) restrict2 override; - - void recreateItemParticles() restrict2; - - void incUsage() restrict2 noexcept2 - { mUsageCounter ++; } - - int decUsage() restrict2 noexcept2 - { return --mUsageCounter; } - - virtual int getLastAttackX() const restrict2 - { return mLastAttackX; } - - virtual int getLastAttackY() const restrict2 - { return mLastAttackY; } - - void drawHomunculus(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawMercenary(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void drawElemental(Graphics *restrict const graphics, - const int offsetX, - const int offsetY) const - restrict2 A_NONNULL(2); - - void setTrickDead(const bool b) restrict2 override final; - - void setChat(ChatObject *restrict const obj) restrict2; - - ChatObject *getChat() const restrict2 noexcept2 - { return mChat; } - - void setRiding(const bool b) restrict2 override final; - - void setHorse(const int horseId) restrict2; - - void removeHorse() restrict2; - - void setSellBoard(const std::string &restrict text) restrict2; - - std::string getSellBoard() const restrict2 noexcept2 A_WARN_UNUSED - { return mSellBoard; } - - void setBuyBoard(const std::string &restrict text) restrict2; - - std::string getBuyBoard() const restrict2 noexcept2 A_WARN_UNUSED - { return mBuyBoard; } - - void setSpiritBalls(const unsigned int balls) restrict2; - - unsigned int getSpiritBalls() const restrict2 noexcept2 A_WARN_UNUSED - { return mSpiritBalls; } - - void stopCast(const bool b) override final; - - void setCreatorId(const BeingId id) - { mCreatorId = id; } - - BeingId getCreatorId() const noexcept2 A_WARN_UNUSED - { return mCreatorId; } - - void setKarma(const int karma) restrict2 noexcept2 - { mKarma = karma; } - - int getKarma() const restrict2 noexcept2 A_WARN_UNUSED - { return mKarma; } - - void setManner(const int manner) restrict2 noexcept2 - { mManner = manner; } - - int getManner() const restrict2 noexcept2 A_WARN_UNUSED - { return mManner; } - - void disableBotAi() restrict2 noexcept2 - { mBotAi = false; } - - void enableBotAi() restrict2 noexcept2 - { mBotAi = true; } - - int getAreaSize() const restrict2 noexcept2 A_WARN_UNUSED - { return mAreaSize; } - - void setAreaSize(const int areaSize) restrict2 noexcept2 - { mAreaSize = areaSize; } - - void setTeamId(const uint16_t teamId) restrict2; - - void showTeamBadge(const bool show) restrict2; - - void showGuildBadge(const bool show) restrict2; - - void showGmBadge(const bool show) restrict2; - - void showPartyBadge(const bool show) restrict2; - - void showNameBadge(const bool show) restrict2; - - void showShopBadge(const bool show) restrict2; - - void showInactiveBadge(const bool show) restrict2; - - void showAwayBadge(const bool show) restrict2; - - void showBadges(const bool show) restrict2; - - void setLanguageId(const int lang) restrict2 noexcept2; - - int getLanguageId() restrict2 noexcept2 A_WARN_UNUSED - { return mLanguageId; } - - uint16_t getTeamId() const restrict2 noexcept2 A_WARN_UNUSED - { return mTeamId; } - - virtual void setGroupId(const int id) - { mGroupId = id; } - - int getGroupId() const noexcept2 A_WARN_UNUSED - { return mGroupId; } - - void serverRemove() restrict2 noexcept2; - - void addCast(const int dstX, - const int dstY, - const int skillId, - const int skillLevel, - const int range, - const int waitTimeTicks); - - void fixDirectionOffsets(int &offsetX, - int &offsetY) const; - - static Being *createBeing(const BeingId id, - const ActorTypeT type, - const BeingTypeId subtype, - Map *const map); - - protected: - void drawPlayerSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawOtherSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawPortalSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawMonsterSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawHomunculusSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawMercenarySpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawElementalSpriteAt(Graphics *restrict const graphics, - const int x, - const int y) const restrict2 A_NONNULL(2); - - void drawCompound(Graphics *const graphics, - const int posX, - const int posY) const A_NONNULL(2); - - /** - * Updates name's location. - */ - virtual void updateCoords() restrict2; - - void showName() restrict2; - - void addItemParticles(const int id, - const SpriteDisplay &restrict display) restrict2; - - void addItemParticlesCards(const int id, - const SpriteDisplay &restrict display, - const CardsList &restrict cards) restrict2; - - void removeAllItemsParticles() restrict2; - - void removeItemParticles(const int id) restrict2; - - void createSpeechBubble() restrict2; - - void setDefaultNameColor(const UserColorIdT defaultColor) restrict2; - - void updateBadgesCount() restrict2; - - static int getDefaultEffectId(const AttackTypeT &restrict type); - - BeingInfo *restrict mInfo; - AnimatedSprite *restrict mEmotionSprite; - AnimatedSprite *restrict mAnimationEffect; - CastingEffect *restrict mCastingEffect; - AnimatedSprite *restrict mBadges[BadgeIndex::BadgeIndexSize]; - - std::string mSpriteAction; - std::string mName; /**< Name of being */ - std::string mExtName; /**< Full name of being */ - std::string mRaceName; - std::string mPartyName; - std::string mGuildName; - std::string mSpeech; - - /** - * Holds a text object when the being displays it's name, 0 otherwise - */ - FlashText *restrict mDispName; - const Color *restrict mNameColor; - - /** Engine-related infos about weapon. */ - const ItemInfo *restrict mEquippedWeapon; - - Path mPath; - Text *restrict mText; - const Color *restrict mTextColor; - - Vector mDest; /**< destination coordinates. */ - - typedef std::map<int, ParticleInfo*> SpriteParticleInfo; - typedef SpriteParticleInfo::iterator SpriteParticleInfoIter; - - STD_VECTOR<BeingSlot> mSlots; - SpriteParticleInfo mSpriteParticles; - - // Character guild information - std::map<int, Guild*> mGuilds; - Party *mParty; - - int mActionTime; /**< Time spent in current action */ - int mEmotionTime; /**< Time until emotion disappears */ - - /** Time until the last speech sentence disappears */ - int mSpeechTime; - int mAttackSpeed; /**< Attack speed */ - - int mLevel; - int mGroupId; - int mAttackRange; - int mLastAttackX; - int mLastAttackY; - - int mPreStandTime; - - GenderT mGender; - BeingActionT mAction; - BeingTypeId mSubType; /**< Subtype (graphical view, basically) */ - uint8_t mDirection; /**< Facing direction */ - uint8_t mDirectionDelayed; /**< Facing direction */ - SpriteDirection::Type mSpriteDirection; /**< Facing direction */ - bool mShowName; - bool mIsGM; - - protected: - void postInit(const BeingTypeId subType, - Map *const map); - - void updateBadgesPosition(); - - /** - * Calculates the offset in the given directions. - * If walking in direction 'neg' the value is negated. - */ - template<signed char pos, signed char neg> - int getOffset() const restrict2 A_WARN_UNUSED; - - int searchSlotValue(const STD_VECTOR<int> &restrict slotRemap, - const int val) const restrict2 A_WARN_UNUSED; - - static void searchSlotValueItr(STD_VECTOR<int>::iterator &restrict it, - int &idx, - STD_VECTOR<int> &restrict slotRemap, - const int val); - - void addSpiritBalls(const unsigned int balls, - const int effectId) restrict2; - - void removeSpiritBalls(const unsigned int balls) restrict2; - - void dumpSprites() const restrict2; - - void drawBeingCursor(Graphics *const graphics, - const int offsetX, - const int offsetY) const A_NONNULL(2); - - void drawCasting(Graphics *const graphics, - const int offsetX, - const int offsetY) const A_NONNULL(2); - - void updateBotFollow(int dstX, - int dstY, - const int divX, - const int divY); - - void moveBotTo(int dstX, - int dstY); - - void updateBotDirection(const int dstX, - const int dstY); - - void botFixOffset(int &restrict dstX, - int &restrict dstY) const; - - const ActorTypeT mType; - - /** Speech Bubble components */ - SpeechBubble *restrict mSpeechBubble; - - /** - * Walk speed for x and y movement values. - * In pixels per second. - * @see MILLISECONDS_IN_A_TICK - */ - int mWalkSpeed; - int mSpeed; - std::string mIp; - int *restrict mSpriteRemap A_NONNULLPOINTER; - int *restrict mSpriteHide A_NONNULLPOINTER; - int *restrict mSpriteDraw A_NONNULLPOINTER; - std::string mComment; - std::string mBuyBoard; - std::string mSellBoard; - Being *restrict mOwner; - Particle *restrict mSpecialParticle; - ChatObject *restrict mChat; - HorseInfo *restrict mHorseInfo; - STD_VECTOR<AnimatedSprite*> mDownHorseSprites; - STD_VECTOR<AnimatedSprite*> mUpHorseSprites; - STD_VECTOR<Particle*> mSpiritParticles; - - int mX; // position in tiles - int mY; // position in tiles - int mCachedX; - int mCachedY; - int mSortOffsetY; // caculated offset in pixels based on mPixelOffsetY - int mPixelOffsetY; // tile height offset in pixels - // calculated between tiles - int mFixedOffsetY; // fixed tile height offset in pixels for tile - uint8_t mOldHeight; - - int mDamageTaken; - int mHP; - int mMaxHP; - int mDistance; - ReachableT mReachable; - int mGoodStatus; - - static time_t mUpdateConfigTime; - static unsigned int mConfLineLim; - static int mSpeechType; - static bool mHighlightMapPortals; - static bool mHighlightMonsterAttackRange; - static bool mLowTraffic; - static bool mDrawHotKeys; - static bool mShowBattleEvents; - static bool mShowMobHP; - static bool mShowOwnHP; - static bool mShowGender; - static bool mShowLevel; - static bool mShowPlayersStatus; - static bool mEnableReorderSprites; - static bool mHideErased; - static Move mMoveNames; - static bool mUseDiagonal; - static BadgeDrawType::Type mShowBadges; - static int mAwayEffect; - static VisibleNamePos::Type mVisibleNamePos; - - time_t mMoveTime; - time_t mAttackTime; - time_t mTalkTime; - time_t mOtherTime; - time_t mTestTime; - int mAttackDelay; - int mMinHit; - int mMaxHit; - int mCriticalHit; - unsigned int mPvpRank; - unsigned int mNumber; - unsigned int mSpiritBalls; - int mUsageCounter; - int mKarma; - int mManner; - int mAreaSize; - int mCastEndTime; - int mLanguageId; - int mBadgesX; - int mBadgesY; - BeingId mCreatorId; - uint16_t mTeamId; - uint16_t mLook; - uint16_t mBadgesCount; - ItemColor mHairColor; - bool mErased; - bool mEnemy; - bool mGotComment; - bool mAdvanced; - bool mShop; - bool mAway; - bool mInactive; - bool mNeedPosUpdate; - bool mBotAi; -}; - -extern std::list<BeingCacheEntry*> beingInfoCache; - -#endif // BEING_BEING_H diff --git a/src/being/beingcacheentry.h b/src/being/beingcacheentry.h deleted file mode 100644 index 4cfc6f64b..000000000 --- a/src/being/beingcacheentry.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_BEINGCACHEENTRY_H -#define BEING_BEINGCACHEENTRY_H - -#include "enums/simpletypes/beingid.h" - -#include "localconsts.h" - -#include <string> - -class BeingCacheEntry final -{ - public: - explicit BeingCacheEntry(const BeingId id) : - mName(), - mPartyName(), - mGuildName(), - mIp(), - mId(id), - mLevel(0), - mPvpRank(0), - mTime(0), - mFlags(0), - mTeamId(0U), - mIsAdvanced(false) - { - } - - A_DELETE_COPY(BeingCacheEntry) - - BeingId getId() const - { return mId; } - - /** - * Returns the name of the being. - */ - const std::string &getName() const - { return mName; } - - /** - * Sets the name for the being. - * - * @param name The name that should appear. - */ - void setName(const std::string &name) - { mName = name; } - - /** - * Following are set from the server (mainly for players) - */ - void setPartyName(const std::string &name) - { mPartyName = name; } - - void setGuildName(const std::string &name) - { mGuildName = name; } - - const std::string &getPartyName() const - { return mPartyName; } - - const std::string &getGuildName() const - { return mGuildName; } - - void setLevel(const int n) - { mLevel = n; } - - int getLevel() const - { return mLevel; } - - void setTime(const time_t n) - { mTime = n; } - - time_t getTime() const - { return mTime; } - - unsigned getPvpRank() const - { return mPvpRank; } - - void setPvpRank(const int r) - { mPvpRank = r; } - - std::string getIp() const - { return mIp; } - - void setIp(const std::string &ip) - { mIp = ip; } - - bool isAdvanced() const - { return mIsAdvanced; } - - void setAdvanced(const bool a) - { mIsAdvanced = a; } - - int getFlags() const - { return mFlags; } - - void setFlags(const int flags) - { mFlags = flags; } - - uint16_t getTeamId() const - { return mTeamId; } - - void setTeamId(const uint16_t teamId) - { mTeamId = teamId; } - - protected: - std::string mName; /**< Name of character */ - std::string mPartyName; - std::string mGuildName; - std::string mIp; - BeingId mId; /**< Unique sprite id */ - int mLevel; - unsigned int mPvpRank; - time_t mTime; - int mFlags; - uint16_t mTeamId; - bool mIsAdvanced; -}; - -#endif // BEING_BEINGCACHEENTRY_H diff --git a/src/being/beingflag.h b/src/being/beingflag.h deleted file mode 100644 index 0669f78bf..000000000 --- a/src/being/beingflag.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_BEINGFLAG_H -#define BEING_BEINGFLAG_H - -namespace BeingFlag -{ - enum - { - SHOP = 1, - AWAY = 2, - INACTIVE = 4, - GENDER_OTHER = 32, - GM = 64, - GENDER_MALE = 128, - SPECIAL = 128 + 64 - }; -} // namespace BeingFlag -#endif // BEING_BEINGFLAG_H diff --git a/src/being/beingspeech.h b/src/being/beingspeech.h deleted file mode 100644 index 869d1b665..000000000 --- a/src/being/beingspeech.h +++ /dev/null @@ -1,37 +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/>. - */ - -#ifndef BEING_BEINGSPEECH_H -#define BEING_BEINGSPEECH_H - -namespace BeingSpeech -{ - enum - { - NO_SPEECH = 0, - TEXT_OVERHEAD, - NO_NAME_IN_BUBBLE, - NAME_IN_BUBBLE - }; -} // namespace BeingSpeech - -#endif // BEING_BEINGSPEECH_H diff --git a/src/being/castingeffect.cpp b/src/being/castingeffect.cpp deleted file mode 100644 index 872743f82..000000000 --- a/src/being/castingeffect.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * The ManaPlus Client - * 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/castingeffect.h" - -#include "configuration.h" - -#include "const/resources/map/map.h" - -#include "gui/userpalette.h" - -#include "render/graphics.h" - -#include "resources/sprite/animatedsprite.h" - -#include "utils/checkutils.h" -#include "utils/delete2.h" - -#include "debug.h" - -CastingEffect::CastingEffect(const int skillId, - const int skillLevel, - const std::string &animation, - const int x, - const int y, - const int range) : - Actor(), - mSprite(animation.empty() ? nullptr : - AnimatedSprite::load(paths.getStringValue("sprites") + animation)), - mRectX((x - range) * mapTileSize), - mRectY((y - range) * mapTileSize), - mRectSize(range * mapTileSize * 2 + mapTileSize), - mAnimationX(mRectX + (mRectSize - (mSprite != nullptr ? - mSprite->getWidth() : 0)) / 2), - mAnimationY(mRectY + (mRectSize - (mSprite != nullptr ? - mSprite->getHeight() : 0)) / 2) -{ - mPixelX = x * mapTileSize; - mPixelY = y * mapTileSize; - mYDiff = range * mapTileSize + 31; - if (mSprite == nullptr) - { - reportAlways("Skill %d/%d casting animation '%s' load failed", - skillId, - skillLevel, - animation.c_str()); - } -} - -CastingEffect::~CastingEffect() -{ - delete2(mSprite); -} - -void CastingEffect::draw(Graphics *const graphics, - const int offsetX, - const int offsetY) const -{ - graphics->setColor(userPalette->getColorWithAlpha( - UserColorId::ATTACK_RANGE_BORDER)); - - graphics->drawRectangle(Rect( - mRectX + offsetX, - mRectY + offsetY, - mRectSize, - mRectSize)); - if (mSprite != nullptr) - { - mSprite->drawRescaled(graphics, - mRectX + offsetX, - mRectY + offsetY, - mRectSize, - mRectSize); - } -} - -void CastingEffect::update(const int time) -{ - if (mSprite != nullptr) - mSprite->update(time); -} - -bool CastingEffect::isTerminated() const -{ - if (mSprite != nullptr) - return mSprite->isTerminated(); - return false; -} diff --git a/src/being/castingeffect.h b/src/being/castingeffect.h deleted file mode 100644 index 3a1d1a6b7..000000000 --- a/src/being/castingeffect.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_CASTINGEFFECT_H -#define BEING_CASTINGEFFECT_H - -#include "being/actor.h" - -#include "enums/being/actortype.h" - -#include "localconsts.h" - -class AnimatedSprite; - -class CastingEffect final : public Actor -{ - public: - CastingEffect(const int skillId, - const int skillLevel, - const std::string &animation, - const int x, - const int y, - const int range); - - A_DELETE_COPY(CastingEffect) - - virtual ~CastingEffect(); - - virtual ActorTypeT getType() const noexcept2 A_WARN_UNUSED - { return ActorType::Unknown; } - - void draw(Graphics *const graphics, - const int offsetX, - const int offsetY) const override final A_NONNULL(2); - - int getSortPixelY() const restrict2 override A_WARN_UNUSED - { return mPixelY - mYDiff; } - - void update(const int time); - - bool isTerminated() const; - - float getAlpha() const override final A_WARN_UNUSED - { return 1.0f; } - - void setAlpha(const float alpha A_UNUSED) override final - { } - - protected: - AnimatedSprite *mSprite; - int mRectX; - int mRectY; - int mRectSize; - int mAnimationX; - int mAnimationY; -}; - -#endif // BEING_CASTINGEFFECT_H diff --git a/src/being/compounditem.h b/src/being/compounditem.h deleted file mode 100644 index 541623ceb..000000000 --- a/src/being/compounditem.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_COMPOUNDITEM_H -#define BEING_COMPOUNDITEM_H - -#include <list> - -#include "localconsts.h" - -class Image; - -typedef std::list <const void*> VectorPointers; - -class CompoundItem final -{ - public: - CompoundItem(); - - A_DELETE_COPY(CompoundItem) - - ~CompoundItem(); - - VectorPointers data; - Image *image; - Image *alphaImage; -}; - -#endif // BEING_COMPOUNDITEM_H diff --git a/src/being/compoundsprite.cpp b/src/being/compoundsprite.cpp deleted file mode 100644 index a32b7db1b..000000000 --- a/src/being/compoundsprite.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/compoundsprite.h" - -#include "configuration.h" - -#include "sdlshared.h" - -#include "being/compounditem.h" - -#include "render/surfacegraphics.h" - -#if defined(USE_OPENGL) || !defined(USE_SDL2) -#include "resources/imagehelper.h" -#endif // USE_OPENGL -#include "resources/image/image.h" - -#include "utils/delete2.h" -#include "utils/dtor.h" -#include "utils/foreach.h" -#include "utils/likely.h" -#include "utils/sdlcheckutils.h" - -#ifndef USE_SDL2 -#include "game.h" - -#include "const/resources/map/map.h" - -#include "resources/map/map.h" - -#include "utils/timer.h" - -PRAGMA48(GCC diagnostic push) -PRAGMA48(GCC diagnostic ignored "-Wshadow") -#ifndef SDL_BIG_ENDIAN -#include <SDL_endian.h> -#endif // SDL_BYTEORDER -PRAGMA48(GCC diagnostic pop) -#endif // USE_SDL2 - -#include "debug.h" - -#ifndef USE_SDL2 -static const int BUFFER_WIDTH = 100; -static const int BUFFER_HEIGHT = 100; -static const unsigned cache_max_size = 10; -static const unsigned cache_clean_part = 3; -#endif // USE_SDL2 - -bool CompoundSprite::mEnableDelay = true; - -CompoundSprite::CompoundSprite() : - Sprite(), - mSprites(), - imagesCache(), - mCacheItem(nullptr), - mImage(nullptr), - mAlphaImage(nullptr), - mOffsetX(0), - mOffsetY(0), - mStartTime(0), - mLastTime(0), -#ifndef USE_SDL2 - mNextRedrawTime(0), -#endif // USE_SDL2 - mNeedsRedraw(false), - mEnableAlphaFix(config.getBoolValue("enableAlphaFix")), - mDisableAdvBeingCaching(config.getBoolValue("disableAdvBeingCaching")), - mDisableBeingCaching(config.getBoolValue("disableBeingCaching")) -{ - mAlpha = 1.0F; -} - -CompoundSprite::~CompoundSprite() -{ - clear(); - mImage = nullptr; - mAlphaImage = nullptr; -} - -bool CompoundSprite::reset() -{ - bool ret = false; - FOR_EACH (SpriteIterator, it, mSprites) - { - if (*it != nullptr) - ret |= (*it)->reset(); - } - if (ret) - mLastTime = 0; - mNeedsRedraw |= ret; - return ret; -} - -bool CompoundSprite::play(const std::string &action) -{ - bool ret = false; - bool ret2 = true; - FOR_EACH (SpriteIterator, it, mSprites) - { - if (*it != nullptr) - { - const bool tmpVal = (*it)->play(action); - ret |= tmpVal; - ret2 &= tmpVal; - } - } - mNeedsRedraw |= ret; - if (ret2) - mLastTime = 0; - return ret; -} - -bool CompoundSprite::update(const int time) -{ - bool ret = false; - if (A_UNLIKELY(mLastTime == 0)) - mStartTime = time; - mLastTime = time; - FOR_EACH (SpriteIterator, it, mSprites) - { - if (*it != nullptr) - ret |= (*it)->update(time); - } - mNeedsRedraw |= ret; - return ret; -} - -void CompoundSprite::drawSimple(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 - { - CompoundSprite::drawSprites(graphics, posX, posY); - } -} - -void CompoundSprite::drawSprites(Graphics *const graphics, - const int posX, - const int posY) const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - { - (*it)->setAlpha(mAlpha); - (*it)->draw(graphics, posX, posY); - } - } -} - -void CompoundSprite::drawSpritesSDL(Graphics *const graphics, - const int posX, - const int posY) const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - (*it)->draw(graphics, posX, posY); - } -} - -int CompoundSprite::getWidth() const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - const Sprite *const base = *it; - if (base != nullptr) - return base->getWidth(); - } - - return 0; -} - -int CompoundSprite::getHeight() const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - const Sprite *const base = *it; - if (base != nullptr) - return base->getHeight(); - } - - return 0; -} - -const Image *CompoundSprite::getImage() const -{ - return mImage; -} - -bool CompoundSprite::setSpriteDirection(const SpriteDirection::Type direction) -{ - bool ret = false; - FOR_EACH (SpriteIterator, it, mSprites) - { - if (*it != nullptr) - ret |= (*it)->setSpriteDirection(direction); - } - if (ret) - mLastTime = 0; - mNeedsRedraw |= ret; - return ret; -} - -int CompoundSprite::getNumberOfLayers() const -{ - if ((mImage != nullptr) || (mAlphaImage != nullptr)) - return 1; - return CAST_S32(mSprites.size()); -} - -unsigned int CompoundSprite::getCurrentFrame() const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - return (*it)->getCurrentFrame(); - } - return 0; -} - -unsigned int CompoundSprite::getFrameCount() const -{ - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - return (*it)->getFrameCount(); - } - return 0; -} - -void CompoundSprite::addSprite(Sprite *const sprite) -{ - mSprites.push_back(sprite); - mNeedsRedraw = true; -} - -void CompoundSprite::setSprite(const size_t layer, Sprite *const sprite) -{ - // Skip if it won't change anything - if (mSprites[layer] == sprite) - return; - - delete mSprites[layer]; - mSprites[layer] = sprite; - mNeedsRedraw = true; -} - -void CompoundSprite::removeSprite(const int layer) -{ - // Skip if it won't change anything - if (mSprites[layer] == nullptr) - return; - - delete2(mSprites[layer]); - mNeedsRedraw = true; -} - -void CompoundSprite::clear() -{ - // Skip if it won't change anything - if (!mSprites.empty()) - { - delete_all(mSprites); - mSprites.clear(); - } - mNeedsRedraw = true; - delete_all(imagesCache); - imagesCache.clear(); - delete2(mCacheItem); - mLastTime = 0; -} - -void CompoundSprite::ensureSize(const size_t layerCount) -{ - // Skip if it won't change anything - if (mSprites.size() >= layerCount) - return; - -// resize(layerCount, nullptr); - mSprites.resize(layerCount); -} - -void CompoundSprite::redraw() const -{ -#ifndef USE_SDL2 - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - const int rmask = 0xff000000; - const int gmask = 0x00ff0000; - const int bmask = 0x0000ff00; - const int amask = 0x000000ff; -#else // SDL_BYTEORDER == SDL_BIG_ENDIAN - const int rmask = 0x000000ff; - const int gmask = 0x0000ff00; - const int bmask = 0x00ff0000; - const int amask = 0xff000000; -#endif // SDL_BYTEORDER == SDL_BIG_ENDIAN - - SDL_Surface *const surface = MSDL_CreateRGBSurface(SDL_HWSURFACE, - BUFFER_WIDTH, BUFFER_HEIGHT, 32, rmask, gmask, bmask, amask); - - if (surface == nullptr) - return; - - SurfaceGraphics *graphics = new SurfaceGraphics; - graphics->setBlitMode(BlitMode::BLIT_GFX); - graphics->setTarget(surface); - graphics->beginDraw(); - - int tileX = mapTileSize / 2; - int tileY = mapTileSize; - - const Game *const game = Game::instance(); - if (game != nullptr) - { - const Map *const map = game->getCurrentMap(); - if (map != nullptr) - { - tileX = map->getTileWidth() / 2; - tileY = map->getTileWidth(); - } - } - - const int posX = BUFFER_WIDTH / 2 - tileX; - const int posY = BUFFER_HEIGHT - tileY; - - mOffsetX = tileX - BUFFER_WIDTH / 2; - mOffsetY = tileY - BUFFER_HEIGHT; - - drawSpritesSDL(graphics, posX, posY); - - delete2(graphics); - - SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE); - - delete mAlphaImage; - - if (ImageHelper::mEnableAlpha) - { - SDL_Surface *const surfaceA = MSDL_CreateRGBSurface(SDL_HWSURFACE, - BUFFER_WIDTH, BUFFER_HEIGHT, 32, rmask, gmask, bmask, amask); - SDL_BlitSurface(surface, nullptr, surfaceA, nullptr); - mAlphaImage = imageHelper->loadSurface(surfaceA); - MSDL_FreeSurface(surfaceA); - } - else - { - mAlphaImage = nullptr; - } - - delete mImage; - mImage = imageHelper->loadSurface(surface); - MSDL_FreeSurface(surface); -#endif // USE_SDL2 -} - -void CompoundSprite::setAlpha(float alpha) -{ - if (alpha != mAlpha) - { - if (mEnableAlphaFix && -#ifdef USE_OPENGL - imageHelper->useOpenGL() == RENDER_SOFTWARE && -#endif // USE_OPENGL - mSprites.size() > 3U) - { - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - (*it)->setAlpha(alpha); - } - } - mAlpha = alpha; - } -} - -void CompoundSprite::updateImages() const -{ -#ifndef USE_SDL2 -#ifdef USE_OPENGL - if (imageHelper->useOpenGL() != RENDER_SOFTWARE) - return; -#endif // USE_OPENGL - - if (mEnableDelay) - { - if (get_elapsed_time1(mNextRedrawTime) < 10) - return; - mNextRedrawTime = tick_time; - } - mNeedsRedraw = false; - - if (!mDisableBeingCaching) - { - if (mSprites.size() <= 3U) - return; - - if (!mDisableAdvBeingCaching) - { - if (updateFromCache()) - return; - - redraw(); - - if (mImage != nullptr) - initCurrentCacheItem(); - } - else - { - redraw(); - } - } -#endif // USE_SDL2 -} - -bool CompoundSprite::updateFromCache() const -{ -#ifndef USE_SDL2 -// static int hits = 0; -// static int miss = 0; - - if ((mCacheItem != nullptr) && (mCacheItem->image != nullptr)) - { - imagesCache.push_front(mCacheItem); - mCacheItem = nullptr; - if (imagesCache.size() > cache_max_size) - { - for (unsigned f = 0; f < cache_clean_part; f ++) - { - CompoundItem *item = imagesCache.back(); - imagesCache.pop_back(); - delete item; - } - } - } - -// logger->log("cache size: %d, hit %d, miss %d", -// (int)imagesCache.size(), hits, miss); - - const size_t sz = mSprites.size(); - FOR_EACH (ImagesCache::iterator, it, imagesCache) - { - CompoundItem *const ic = *it; - if ((ic != nullptr) && ic->data.size() == sz) - { - bool fail(false); - VectorPointers::const_iterator it2 = ic->data.begin(); - const VectorPointers::const_iterator it2_end = ic->data.end(); - - for (SpriteConstIterator it1 = mSprites.begin(), - it1_end = mSprites.end(); - it1 != it1_end && it2 != it2_end; - ++ it1, ++ it2) - { - const void *ptr1 = nullptr; - const void *ptr2 = nullptr; - if (*it1 != nullptr) - ptr1 = (*it1)->getHash(); - if (*it2 != nullptr) - ptr2 = *it2; - if (ptr1 != ptr2) - { - fail = true; - break; - } - } - if (!fail) - { -// hits ++; - mImage = (*it)->image; - mAlphaImage = (*it)->alphaImage; - imagesCache.erase(it); - mCacheItem = ic; - return true; - } - } - } - mImage = nullptr; - mAlphaImage = nullptr; -// miss++; -#endif // USE_SDL2 - return false; -} - -void CompoundSprite::initCurrentCacheItem() const -{ - delete mCacheItem; - mCacheItem = new CompoundItem; - mCacheItem->image = mImage; - mCacheItem->alphaImage = mAlphaImage; -// mCacheItem->alpha = mAlpha; - - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - mCacheItem->data.push_back((*it)->getHash()); - else - mCacheItem->data.push_back(nullptr); - } -} - -bool CompoundSprite::updateNumber(const unsigned num) -{ - bool res(false); - FOR_EACH (SpriteConstIterator, it, mSprites) - { - if (*it != nullptr) - { - if ((*it)->updateNumber(num)) - res = true; - } - } - return res; -} - -CompoundItem::CompoundItem() : - data(), - image(nullptr), - alphaImage(nullptr) -{ -} - -CompoundItem::~CompoundItem() -{ - delete image; - delete alphaImage; -} diff --git a/src/being/compoundsprite.h b/src/being/compoundsprite.h deleted file mode 100644 index bf6679963..000000000 --- a/src/being/compoundsprite.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/>. - */ - -#ifndef BEING_COMPOUNDSPRITE_H -#define BEING_COMPOUNDSPRITE_H - -#include "resources/sprite/sprite.h" - -#include "utils/vector.h" - -#include <list> - -#include "localconsts.h" - -class CompoundItem; -class Image; - -class CompoundSprite notfinal : public Sprite -{ - public: - typedef STD_VECTOR<Sprite*>::iterator SpriteIterator; - typedef STD_VECTOR<Sprite*>::const_iterator SpriteConstIterator; - - CompoundSprite(); - - A_DELETE_COPY(CompoundSprite) - - virtual ~CompoundSprite(); - - bool reset() override final; - - bool play(const std::string &action) override final; - - bool update(const int time) override final; - - void drawSimple(Graphics *const graphics, - const int posX, - const int posY) const A_NONNULL(2); - - /** - * Gets the width in pixels of the first sprite in the list. - */ - int getWidth() const override A_WARN_UNUSED; - - /** - * Gets the height in pixels of the first sprite in the list. - */ - int getHeight() const override A_WARN_UNUSED; - - const Image *getImage() const override final A_WARN_UNUSED; - - bool setSpriteDirection(const SpriteDirection::Type direction) - override final; - - int getNumberOfLayers() const A_WARN_UNUSED; - - unsigned int getCurrentFrame() const override final A_WARN_UNUSED; - - unsigned int getFrameCount() const override final A_WARN_UNUSED; - - void addSprite(Sprite *const sprite); - - void setSprite(const size_t layer, Sprite *const sprite); - - void removeSprite(const int layer); - - void clear(); - - void ensureSize(const size_t layerCount); - - void drawSprites(Graphics *const graphics, - const int posX, - const int posY) const; - - virtual void drawSpritesSDL(Graphics *const graphics, - const int posX, - const int posY) const; - - void setAlpha(float alpha) override; - - bool updateNumber(const unsigned num) override final; - - constexpr2 static void setEnableDelay(bool b) noexcept2 - { mEnableDelay = b; } - - int getLastTime() const noexcept2 A_WARN_UNUSED - { return mLastTime; } - - int getStartTime() const noexcept2 A_WARN_UNUSED - { return mStartTime; } - - STD_VECTOR<Sprite*> mSprites; - - protected: - void redraw() const; - - void updateImages() const; - - bool updateFromCache() const; - - void initCurrentCacheItem() const; - - typedef std::list<CompoundItem*> ImagesCache; - mutable ImagesCache imagesCache; - mutable CompoundItem *mCacheItem; - - mutable Image *mImage; - mutable Image *mAlphaImage; - - mutable int mOffsetX; - mutable int mOffsetY; - int mStartTime; - int mLastTime; -#ifndef USE_SDL2 - mutable int mNextRedrawTime; -#endif // USE_SDL2 - - static bool mEnableDelay; - mutable bool mNeedsRedraw; - bool mEnableAlphaFix; - bool mDisableAdvBeingCaching; - bool mDisableBeingCaching; -}; - -#endif // BEING_COMPOUNDSPRITE_H diff --git a/src/being/crazymoves.cpp b/src/being/crazymoves.cpp deleted file mode 100644 index 5fb093d9d..000000000 --- a/src/being/crazymoves.cpp +++ /dev/null @@ -1,824 +0,0 @@ -/* - * The ManaPlus Client - * 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/crazymoves.h" - -#include "configuration.h" -#include "settings.h" - -#include "being/localplayer.h" - -#include "enums/being/beingdirection.h" - -#include "gui/shortcut/dropshortcut.h" - -#include "gui/windows/outfitwindow.h" - -#include "net/packetlimiter.h" -#include "net/pethandler.h" -#include "net/playerhandler.h" - -#include "resources/db/emotedb.h" - -#include "resources/map/map.h" - -#include "utils/timer.h" - -#include "debug.h" - -CrazyMoves *crazyMoves = nullptr; - -CrazyMoves::CrazyMoves() : - mMoveProgram(), - mDisableCrazyMove(false) -{ -} - -void CrazyMoves::crazyMove() -{ - const bool oldDisableCrazyMove = mDisableCrazyMove; - mDisableCrazyMove = true; - switch (settings.crazyMoveType) - { - case 1: - crazyMove1(); - break; - case 2: - crazyMove2(); - break; - case 3: - crazyMove3(); - break; - case 4: - crazyMove4(); - break; - case 5: - crazyMove5(); - break; - case 6: - crazyMove6(); - break; - case 7: - crazyMove7(); - break; - case 8: - crazyMove8(); - break; - case 9: - crazyMove9(); - break; - case 10: - crazyMoveA(); - break; - default: - break; - } - mDisableCrazyMove = oldDisableCrazyMove; -} - -void CrazyMoves::crazyMove1() -{ - if ((localPlayer == nullptr) || - (playerHandler == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - -// if (!PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) -// return; - - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - localPlayer->setWalkingDir(BeingDirection::UP); - localPlayer->setDirection(BeingDirection::LEFT); - playerHandler->setDirection(BeingDirection::LEFT); - break; - case BeingDirection::LEFT: - localPlayer->setWalkingDir(BeingDirection::LEFT); - localPlayer->setDirection(BeingDirection::DOWN); - playerHandler->setDirection(BeingDirection::DOWN); - break; - case BeingDirection::DOWN: - localPlayer->setWalkingDir(BeingDirection::DOWN); - localPlayer->setDirection(BeingDirection::RIGHT); - playerHandler->setDirection(BeingDirection::RIGHT); - break; - case BeingDirection::RIGHT: - localPlayer->setWalkingDir(BeingDirection::RIGHT); - localPlayer->setDirection(BeingDirection::UP); - playerHandler->setDirection(BeingDirection::UP); - break; - default: - break; - } -} - -void CrazyMoves::crazyMove2() -{ - if ((localPlayer == nullptr) || - (playerHandler == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - -// if (!PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) -// return; - - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - localPlayer->setWalkingDir(BeingDirection::UP | - BeingDirection::LEFT); - localPlayer->setDirection(BeingDirection::RIGHT); - playerHandler->setDirection( - BeingDirection::DOWN | BeingDirection::RIGHT); - break; - - case BeingDirection::RIGHT: - localPlayer->setWalkingDir(BeingDirection::UP | - BeingDirection::RIGHT); - localPlayer->setDirection(BeingDirection::DOWN); - playerHandler->setDirection( - BeingDirection::DOWN | BeingDirection::LEFT); - break; - - case BeingDirection::DOWN: - localPlayer->setWalkingDir(BeingDirection::DOWN | - BeingDirection::RIGHT); - localPlayer->setDirection(BeingDirection::LEFT); - playerHandler->setDirection( - BeingDirection::UP | BeingDirection::LEFT); - break; - - case BeingDirection::LEFT: - localPlayer->setWalkingDir(BeingDirection::DOWN | - BeingDirection::LEFT); - localPlayer->setDirection(BeingDirection::UP); - playerHandler->setDirection( - BeingDirection::UP | BeingDirection::RIGHT); - break; - - default: - break; - } -} - -void CrazyMoves::crazyMove3() -{ - if ((localPlayer == nullptr) || - (playerHandler == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - localPlayer->move(1, 1); - settings.crazyMoveState = 1; - break; - case 1: - localPlayer->move(1, -1); - settings.crazyMoveState = 2; - break; - case 2: - localPlayer->move(-1, -1); - settings.crazyMoveState = 3; - break; - case 3: - localPlayer->move(-1, 1); - settings.crazyMoveState = 0; - break; - default: - break; - } - -// if (!PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) -// return; - - localPlayer->setDirection(BeingDirection::DOWN); - playerHandler->setDirection(BeingDirection::DOWN); -} - -void CrazyMoves::crazyMove4() -{ - if ((localPlayer == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - localPlayer->move(7, 0); - settings.crazyMoveState = 1; - break; - case 1: - localPlayer->move(-7, 0); - settings.crazyMoveState = 0; - break; - default: - break; - } -} - -void CrazyMoves::crazyMove5() -{ - if ((localPlayer == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - localPlayer->move(0, 7); - settings.crazyMoveState = 1; - break; - case 1: - localPlayer->move(0, -7); - settings.crazyMoveState = 0; - break; - default: - break; - } -} - -void CrazyMoves::crazyMove6() -{ - if ((localPlayer == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - localPlayer->move(3, 0); - settings.crazyMoveState = 1; - break; - case 1: - localPlayer->move(2, -2); - settings.crazyMoveState = 2; - break; - case 2: - localPlayer->move(0, -3); - settings.crazyMoveState = 3; - break; - case 3: - localPlayer->move(-2, -2); - settings.crazyMoveState = 4; - break; - case 4: - localPlayer->move(-3, 0); - settings.crazyMoveState = 5; - break; - case 5: - localPlayer->move(-2, 2); - settings.crazyMoveState = 6; - break; - case 6: - localPlayer->move(0, 3); - settings.crazyMoveState = 7; - break; - case 7: - localPlayer->move(2, 2); - settings.crazyMoveState = 0; - break; - default: - break; - } -} - -void CrazyMoves::crazyMove7() -{ - if ((localPlayer == nullptr) || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - localPlayer->move(1, 1); - settings.crazyMoveState = 1; - break; - case 1: - localPlayer->move(-1, 1); - settings.crazyMoveState = 2; - break; - case 2: - localPlayer->move(-1, -1); - settings.crazyMoveState = 3; - break; - case 3: - localPlayer->move(1, -1); - settings.crazyMoveState = 0; - break; - default: - break; - } -} - -void CrazyMoves::crazyMove8() -{ - if (localPlayer == nullptr || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - const Map *const map = localPlayer->getMap(); - if (map == nullptr) - return; - const int x = localPlayer->getTileX(); - const int y = localPlayer->getTileY(); - int idx = 0; - const int dist = 1; - -// look -// up, ri,do,le - static const int movesX[][4] = - { - {-1, 0, 1, 0}, // move left - { 0, 1, 0, -1}, // move up - { 1, 0, -1, 0}, // move right - { 0, -1, 0, 1} // move down - }; - -// look -// up, ri,do,le - static const int movesY[][4] = - { - { 0, -1, 0, 1}, // move left - {-1, 0, 1, 0}, // move up - { 0, 1, 0, -1}, // move right - { 1, 0, -1, 0} // move down - }; - - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - idx = 0; - break; - - case BeingDirection::RIGHT: - idx = 1; - break; - - case BeingDirection::DOWN: - idx = 2; - break; - - case BeingDirection::LEFT: - idx = 3; - break; - - default: - break; - } - - int mult = 1; - const unsigned char blockWalkMask = localPlayer->getBlockWalkMask(); - if (map->getWalk(x + movesX[idx][0], - y + movesY[idx][0], blockWalkMask)) - { - while (map->getWalk(x + movesX[idx][0] * mult, - y + movesY[idx][0] * mult, - blockWalkMask) && mult <= dist) - { - mult ++; - } - localPlayer->move(movesX[idx][0] * (mult - 1), - movesY[idx][0] * (mult - 1)); - } - else if (map->getWalk(x + movesX[idx][1], - y + movesY[idx][1], blockWalkMask)) - { - while (map->getWalk(x + movesX[idx][1] * mult, - y + movesY[idx][1] * mult, - blockWalkMask) && mult <= dist) - { - mult ++; - } - localPlayer->move(movesX[idx][1] * (mult - 1), - movesY[idx][1] * (mult - 1)); - } - else if (map->getWalk(x + movesX[idx][2], - y + movesY[idx][2], blockWalkMask)) - { - while (map->getWalk(x + movesX[idx][2] * mult, - y + movesY[idx][2] * mult, - blockWalkMask) && mult <= dist) - { - mult ++; - } - localPlayer->move(movesX[idx][2] * (mult - 1), - movesY[idx][2] * (mult - 1)); - } - else if (map->getWalk(x + movesX[idx][3], - y + movesY[idx][3], blockWalkMask)) - { - while (map->getWalk(x + movesX[idx][3] * mult, - y + movesY[idx][3] * mult, - blockWalkMask) && mult <= dist) - { - mult ++; - } - localPlayer->move(movesX[idx][3] * (mult - 1), - movesY[idx][3] * (mult - 1)); - } -} - -void CrazyMoves::crazyMove9() -{ - int dx = 0; - int dy = 0; - - if (localPlayer == nullptr || - localPlayer->getCurrentAction() == BeingAction::MOVE) - { - return; - } - - switch (settings.crazyMoveState) - { - case 0: - switch (localPlayer->getDirection()) - { - case BeingDirection::UP : dy = -1; break; - case BeingDirection::DOWN : dy = 1; break; - case BeingDirection::LEFT : dx = -1; break; - case BeingDirection::RIGHT: dx = 1; break; - default: break; - } - localPlayer->move(dx, dy); - settings.crazyMoveState = 1; - break; - case 1: - settings.crazyMoveState = 2; - if (!localPlayer->allowAction()) - return; - if (playerHandler != nullptr) - playerHandler->changeAction(BeingAction::SIT); - break; - case 2: - settings.crazyMoveState = 3; - break; - case 3: - settings.crazyMoveState = 0; - break; - default: - break; - } -} - -void CrazyMoves::crazyMoveAm() const -{ - if (localPlayer == nullptr) - return; - - settings.crazyMoveState ++; - if (settings.crazyMoveState < mMoveProgram.length()) - { - int dx = 0; - int dy = 0; - - signed char param = mMoveProgram[settings.crazyMoveState++]; - if (param == '?') - { - const char cmd[] = {'l', 'r', 'u', 'd', 'L', 'R', 'U', 'D'}; - srand(tick_time); - param = cmd[rand() % 8]; - } - switch (param) - { - case 'd': - localPlayer->move(0, 1); - break; - case 'u': - localPlayer->move(0, -1); - break; - case 'l': - localPlayer->move(-1, 0); - break; - case 'r': - localPlayer->move(1, 0); - break; - case 'D': - localPlayer->move(1, 1); - break; - case 'U': - localPlayer->move(-1, -1); - break; - case 'L': - localPlayer->move(-1, 1); - break; - case 'R': - localPlayer->move(1, -1); - break; - case 'f': - { - const uint8_t dir = localPlayer->getDirection(); - if ((dir & BeingDirection::UP) != 0) - dy = -1; - else if ((dir & BeingDirection::DOWN) != 0) - dy = 1; - if ((dir & BeingDirection::LEFT) != 0) - dx = -1; - else if ((dir & BeingDirection::RIGHT) != 0) - dx = 1; - localPlayer->move(dx, dy); - break; - } - case 'b': - { - const uint8_t dir = localPlayer->getDirection(); - if ((dir & BeingDirection::UP) != 0) - dy = 1; - else if ((dir & BeingDirection::DOWN) != 0) - dy = -1; - if ((dir & BeingDirection::LEFT) != 0) - dx = 1; - else if ((dir & BeingDirection::RIGHT) != 0) - dx = -1; - localPlayer->move(dx, dy); - break; - } - default: - break; - } - } -} - -void CrazyMoves::crazyMoveAd() const -{ - settings.crazyMoveState ++; - - if (settings.crazyMoveState < mMoveProgram.length()) - { - signed char param = mMoveProgram[settings.crazyMoveState++]; - if (param == '?') - { - const char cmd[] = {'l', 'r', 'u', 'd'}; - srand(tick_time); - param = cmd[rand() % 4]; - } - switch (param) - { - case 'd': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::DOWN); - playerHandler->setDirection( - BeingDirection::DOWN); - } - break; - case 'u': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::UP); - playerHandler->setDirection( - BeingDirection::UP); - } - break; - case 'l': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::LEFT); - playerHandler->setDirection( - BeingDirection::LEFT); - } - break; - case 'r': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - localPlayer->setDirection(BeingDirection::RIGHT); - playerHandler->setDirection( - BeingDirection::RIGHT); - } - break; - case 'L': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - uint8_t dir = 0; - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - dir = BeingDirection::LEFT; - break; - case BeingDirection::DOWN: - dir = BeingDirection::RIGHT; - break; - case BeingDirection::LEFT: - dir = BeingDirection::DOWN; - break; - case BeingDirection::RIGHT: - dir = BeingDirection::UP; - break; - default: - break; - } - localPlayer->setDirection(dir); - playerHandler->setDirection(dir); - } - break; - case 'R': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - uint8_t dir = 0; - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - dir = BeingDirection::RIGHT; - break; - case BeingDirection::DOWN: - dir = BeingDirection::LEFT; - break; - case BeingDirection::LEFT: - dir = BeingDirection::UP; - break; - case BeingDirection::RIGHT: - dir = BeingDirection::DOWN; - break; - default: - break; - } - localPlayer->setDirection(dir); - playerHandler->setDirection(dir); - } - break; - case 'b': -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - uint8_t dir = 0; - switch (localPlayer->getDirection()) - { - case BeingDirection::UP: - dir = BeingDirection::DOWN; - break; - case BeingDirection::DOWN: - dir = BeingDirection::UP; - break; - case BeingDirection::LEFT: - dir = BeingDirection::RIGHT; - break; - case BeingDirection::RIGHT: - dir = BeingDirection::LEFT; - break; - default: - break; - } - localPlayer->setDirection(dir); - playerHandler->setDirection(dir); - } - break; - case '0': - dropShortcut->dropFirst(); - break; - case 'a': - dropShortcut->dropItems(); - break; - default: - break; - } - } -} - -void CrazyMoves::crazyMoveAs() -{ - settings.crazyMoveState ++; - if (localPlayer->toggleSit()) - settings.crazyMoveState ++; -} - -void CrazyMoves::crazyMoveAo() const -{ - settings.crazyMoveState ++; - if (settings.crazyMoveState < mMoveProgram.length()) - { - // wear next outfit - if (mMoveProgram[settings.crazyMoveState] == 'n') - { - settings.crazyMoveState ++; - outfitWindow->wearNextOutfit(); - } - // wear previous outfit - else if (mMoveProgram[settings.crazyMoveState] == 'p') - { - settings.crazyMoveState ++; - outfitWindow->wearPreviousOutfit(); - } - } -} - -void CrazyMoves::crazyMoveAe() const -{ - settings.crazyMoveState ++; - const signed char emo = mMoveProgram[settings.crazyMoveState]; - unsigned char emoteId = 0; - if (emo == '?') - { - srand(tick_time); - emoteId = CAST_U8( - 1 + (rand() % EmoteDB::size())); - } - else - { - if (emo >= '0' && emo <= '9') - emoteId = CAST_U8(emo - '0' + 1); - else if (emo >= 'a' && emo <= 'z') - emoteId = CAST_U8(emo - 'a' + 11); - else if (emo >= 'A' && emo <= 'Z') - emoteId = CAST_U8(emo - 'A' + 37); - } - if (mMoveProgram[settings.crazyMoveState - 1] == 'e') - LocalPlayer::emote(emoteId); - else if (PacketLimiter::limitPackets(PacketType::PACKET_CHAT)) - petHandler->emote(emoteId); - - settings.crazyMoveState ++; -} - -void CrazyMoves::crazyMoveA() -{ - mMoveProgram = config.getStringValue("crazyMoveProgram"); - - if (localPlayer->getCurrentAction() == BeingAction::MOVE) - return; - - if (mMoveProgram.empty()) - return; - - if (settings.crazyMoveState >= mMoveProgram.length()) - settings.crazyMoveState = 0; - - // move command - if (mMoveProgram[settings.crazyMoveState] == 'm') - { - crazyMoveAm(); - } - // direction command - else if (mMoveProgram[settings.crazyMoveState] == 'd') - { - crazyMoveAd(); - } - // sit command - else if (mMoveProgram[settings.crazyMoveState] == 's') - { - crazyMoveAs(); - } - // wear outfits - else if (mMoveProgram[settings.crazyMoveState] == 'o') - { - crazyMoveAo(); - } - // pause - else if (mMoveProgram[settings.crazyMoveState] == 'w') - { - settings.crazyMoveState ++; - } - // pick up - else if (mMoveProgram[settings.crazyMoveState] == 'p') - { - settings.crazyMoveState ++; - localPlayer->pickUpItems(); - } - // emote - else if (mMoveProgram[settings.crazyMoveState] == 'e' - || mMoveProgram[settings.crazyMoveState] == 'E') - { - crazyMoveAe(); - } - else - { - settings.crazyMoveState ++; - } - - if (settings.crazyMoveState >= mMoveProgram.length()) - settings.crazyMoveState = 0; -} diff --git a/src/being/crazymoves.h b/src/being/crazymoves.h deleted file mode 100644 index 4c812c5f0..000000000 --- a/src/being/crazymoves.h +++ /dev/null @@ -1,62 +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/>. - */ - -#ifndef BEING_CRAZYMOVES_H -#define BEING_CRAZYMOVES_H - -#include <string> - -#include "localconsts.h" - -class CrazyMoves final -{ - public: - CrazyMoves(); - A_DELETE_COPY(CrazyMoves) - void crazyMove(); - - protected: - static void crazyMove1(); - static void crazyMove2(); - static void crazyMove3(); - static void crazyMove4(); - static void crazyMove5(); - static void crazyMove6(); - static void crazyMove7(); - static void crazyMove8(); - static void crazyMove9(); - void crazyMoveA(); - void crazyMoveAd() const; - void crazyMoveAe() const; - void crazyMoveAm() const; - void crazyMoveAo() const; - static void crazyMoveAs(); - - std::string mMoveProgram; - - // temporary disable crazy moves in moves - bool mDisableCrazyMove; -}; - -extern CrazyMoves *crazyMoves; - -#endif // BEING_CRAZYMOVES_H diff --git a/src/being/flooritem.cpp b/src/being/flooritem.cpp deleted file mode 100644 index 041531e86..000000000 --- a/src/being/flooritem.cpp +++ /dev/null @@ -1,225 +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/flooritem.h" - -#include "configuration.h" - -#include "render/graphics.h" - -#include "gui/gui.h" -#include "gui/userpalette.h" - -#include "gui/fonts/font.h" - -#include "resources/iteminfo.h" - -#include "resources/db/itemdb.h" - -#include "resources/map/map.h" - -#ifdef TMWA_SUPPORT -#include "net/net.h" -#endif // TMWA_SUPPORT -#include "net/serverfeatures.h" - -#include "debug.h" - -extern volatile time_t cur_time; - -FloorItem::FloorItem(const BeingId id, - const int itemId, - const int x, const int y, - const ItemTypeT itemType, - const int amount, - const int refine, - const ItemColor color, - const Identified identified, - const Damaged damaged, - const int *const cards) : - ActorSprite(id), - mCards(), - mItemId(itemId), - mX(x), - mY(y), - mDropTime(cur_time), - mAmount(amount), - mRefine(refine), - mHeightPosDiff(0), - mItemType(itemType), - mPickupCount(0), - mCursor(Cursor::CURSOR_PICKUP), - mColor(color), - mIdentified(identified), - mDamaged(damaged), - mShowMsg(true), - mHighlight(config.getBoolValue("floorItemsHighlight")) -{ - setCards(cards, maxCards); -} - -void FloorItem::postInit(Map *const map, int subX, int subY) -{ - setMap(map); - const ItemInfo &info = ItemDB::get(mItemId); - if (map != nullptr) - { - const int maxX = info.getMaxFloorOffsetX(); - const int maxY = info.getMaxFloorOffsetY(); - - if (!serverFeatures->haveExtendedDropsPosition()) - { - if (subX > maxX) - subX = maxX; - else if (subX < -maxX) - subX = -maxX; - if (subY > maxY) - subY = maxY; - else if (subY < -maxY) - subY = -maxY; - - subX -= 8; - subY -= 8; - } - - mHeightPosDiff = map->getHeightOffset(mX, mY) * 16; - mPixelX = mX * map->getTileWidth() - + subX + mapTileSize / 2; - mPixelY = mY * map->getTileHeight() - + subY + mapTileSize - mHeightPosDiff; - mPos.x = static_cast<float>(mPixelX); - mPos.y = static_cast<float>(mPixelY); - mYDiff = 31 - mHeightPosDiff; - } - else - { - mPixelX = 0; - mPixelY = 0; - mPos.x = 0; - mPos.y = 0; - mYDiff = 31; - } - - mCursor = info.getPickupCursor(); - setupSpriteDisplay(info.getDisplay(), - ForceDisplay_true, - DisplayType::Floor, - info.getDyeIconColorsString(mColor)); -} - -void FloorItem::setCards(const int *const cards, - int sz) -{ - if (sz < 0 || cards == nullptr) - return; - if (sz > maxCards) - sz = maxCards; - for (int f = 0; f < sz; f ++) - mCards[f] = cards[f]; -} - -const ItemInfo &FloorItem::getInfo() const -{ - return ItemDB::get(mItemId); -} - -std::string FloorItem::getName() const -{ - const ItemInfo &info = ItemDB::get(mItemId); -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() == ServerType::TMWATHENA) - { - return info.getName(); - } -#endif // TMWA_SUPPORT - - return info.getName(mColor); -} - -void FloorItem::draw(Graphics *const graphics, - const int offsetX, const int offsetY) const -{ - if (mMap == nullptr) - return; - - BLOCK_START("FloorItem::draw") - const int x = mX * mMap->getTileWidth() + offsetX; - const int y = mY * mMap->getTileHeight() + offsetY - mHeightPosDiff; - Font *font = nullptr; - - if (mHighlight) - { - const time_t curTime = cur_time; - font = gui->getFont(); - if (mDropTime < curTime) - { - const int dx = mapTileSize; - const int dy = mapTileSize; - - if (curTime > mDropTime + 28 && curTime < mDropTime + 50) - { - graphics->setColor(Color(80, 200, 20, 200)); - graphics->fillRectangle(Rect( - x, y, dx, dy)); - } - else if (curTime > mDropTime + 19 - && curTime < mDropTime + 28) - { - graphics->setColor(Color(200, 80, 20, - 80 + 10 * CAST_S32(curTime - mDropTime - 18))); - graphics->fillRectangle(Rect( - x, y, dx, dy)); - } - else if (curTime > mDropTime && curTime < mDropTime + 20) - { - graphics->setColor(Color(20, 20, 255, - 7 * CAST_S32(curTime - mDropTime))); - graphics->fillRectangle(Rect(x, y, dx, dy)); - } - } - } - - const int px = getActorX() + offsetX; - const int py = getActorY() + offsetY; - CompoundSprite::drawSimple(graphics, px, py); - - if (mHighlight) - { - if (font != nullptr && mAmount > 1) - { - const Color &color = userPalette->getColor( - UserColorId::FLOOR_ITEM_TEXT); - font->drawString(graphics, - color, color, - toString(mAmount), - x, y); - } - } - BLOCK_END("FloorItem::draw") -} - -int FloorItem::getCard(const int index) const -{ - if (index < 0 || index >= maxCards) - return 0; - return mCards[index]; -} diff --git a/src/being/flooritem.h b/src/being/flooritem.h deleted file mode 100644 index 700ce7d15..000000000 --- a/src/being/flooritem.h +++ /dev/null @@ -1,153 +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/>. - */ - -#ifndef BEING_FLOORITEM_H -#define BEING_FLOORITEM_H - -#include "const/resources/item/cards.h" - -#include "enums/resources/cursor.h" - -#include "enums/resources/item/itemtype.h" - -#include "enums/simpletypes/damaged.h" -#include "enums/simpletypes/identified.h" -#include "enums/simpletypes/itemcolor.h" - -#include "being/actorsprite.h" - -class ItemInfo; - -/** - * An item lying on the floor. - */ -class FloorItem final : public ActorSprite -{ - public: - /** - * Constructor. - * - * @param id the unique ID of this item instance - * @param itemId the item ID - * @param x the x position in tiles - * @param y the y position in tiles - * @param amount the item amount - * @param color the item color - */ - FloorItem(const BeingId id, - const int itemId, - const int x, const int y, - const ItemTypeT itemType, - const int amount, - const int refine, - const ItemColor color, - const Identified identified, - const Damaged damaged, - const int *const cards); - - A_DELETE_COPY(FloorItem) - - void postInit(Map *const map, int subX, int subY); - - ActorTypeT getType() const noexcept2 override final A_WARN_UNUSED - { return ActorType::FloorItem; } - - void draw(Graphics *const graphics, - const int offsetX, const int offsetY) - const override final A_NONNULL(2); - - /** - * Returns the item ID. - */ - int getItemId() const noexcept2 A_WARN_UNUSED - { return mItemId; } - - /** - * Returns the item info for this floor item. Useful for adding an item - * link for the floor item to chat. - */ - const ItemInfo &getInfo() const A_WARN_UNUSED; - - std::string getName() const A_WARN_UNUSED; - - int getTileX() const override final A_WARN_UNUSED - { return mX; } - - int getTileY() const override final A_WARN_UNUSED - { return mY; } - - void incrementPickup() noexcept2 - { mPickupCount ++; } - - unsigned getPickupCount() const noexcept2 A_WARN_UNUSED - { return mPickupCount; } - - ItemColor getColor() const noexcept2 A_WARN_UNUSED - { return mColor; } - - bool getShowMsg() const noexcept2 A_WARN_UNUSED - { return mShowMsg; } - - void setShowMsg(const bool n) noexcept2 - { mShowMsg = n; } - - void disableHightlight() noexcept2 - { mHighlight = false; } - - CursorT getHoverCursor() const noexcept2 A_WARN_UNUSED - { return mCursor; } - - void setCards(const int *const cards, int sz); - - int getCard(const int index) const; - - int getRefine() const noexcept2 A_WARN_UNUSED - { return mRefine; } - - ItemTypeT getItemType() const noexcept2 A_WARN_UNUSED - { return mItemType; } - - Identified getIdentified() const noexcept2 A_WARN_UNUSED - { return mIdentified; } - - Damaged getDamaged() const noexcept2 A_WARN_UNUSED - { return mDamaged; } - - private: - int mCards[maxCards]; - int mItemId; - int mX, mY; - time_t mDropTime; - int mAmount; - int mRefine; - int mHeightPosDiff; - ItemTypeT mItemType; - unsigned int mPickupCount; - CursorT mCursor; - ItemColor mColor; - Identified mIdentified; - Damaged mDamaged; - bool mShowMsg; - bool mHighlight; -}; - -#endif // BEING_FLOORITEM_H diff --git a/src/being/homunculusinfo.h b/src/being/homunculusinfo.h deleted file mode 100644 index 1488af9e8..000000000 --- a/src/being/homunculusinfo.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_HOMUNCULUSINFO_H -#define BEING_HOMUNCULUSINFO_H - -#include "enums/simpletypes/beingid.h" - -#include <string> - -#include "localconsts.h" - -struct HomunculusInfo final -{ - HomunculusInfo() : - name(), - id(BeingId_zero), - level(0), - range(0), - hungry(0), - intimacy(0), - equip(0) - { } - - A_DELETE_COPY(HomunculusInfo) - - std::string name; - BeingId id; - int level; - int range; - int hungry; - int intimacy; - int equip; -}; - -#endif // BEING_HOMUNCULUSINFO_H diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp deleted file mode 100644 index 1a12a3808..000000000 --- a/src/being/localplayer.cpp +++ /dev/null @@ -1,2816 +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/localplayer.h" - -#include "actormanager.h" -#include "configuration.h" -#include "gamemodifiers.h" -#include "guild.h" -#include "party.h" -#include "settings.h" -#include "soundmanager.h" -#include "statuseffect.h" - -#include "being/beingflag.h" -#include "being/crazymoves.h" -#include "being/playerinfo.h" -#include "being/playerrelations.h" - -#include "const/sound.h" - -#include "enums/equipslot.h" - -#include "enums/being/beingdirection.h" - -#include "enums/resources/map/blockmask.h" -#include "enums/resources/map/mapitemtype.h" - -#include "particle/particleengine.h" - -#include "input/keyboardconfig.h" - -#include "gui/gui.h" -#include "gui/userpalette.h" -#include "gui/popupmanager.h" - -#include "gui/windows/chatwindow.h" -#include "gui/windows/ministatuswindow.h" -#include "gui/windows/okdialog.h" -#include "gui/windows/outfitwindow.h" -#include "gui/windows/shopwindow.h" -#include "gui/windows/socialwindow.h" -#include "gui/windows/statuswindow.h" -#include "gui/windows/updaterwindow.h" - -#include "gui/widgets/tabs/chat/whispertab.h" - -#include "listeners/awaylistener.h" - -#include "net/beinghandler.h" -#include "net/chathandler.h" -#include "net/inventoryhandler.h" -#include "net/net.h" -#include "net/packetlimiter.h" -#include "net/playerhandler.h" -#include "net/serverfeatures.h" - -#include "resources/iteminfo.h" - -#include "resources/db/weaponsdb.h" - -#include "resources/item/item.h" - -#include "resources/map/map.h" -#include "resources/map/mapitem.h" -#include "resources/map/speciallayer.h" -#include "resources/map/walklayer.h" - -#include "resources/sprite/animatedsprite.h" - -#include "utils/delete2.h" -#include "utils/foreach.h" -#include "utils/gettext.h" -#include "utils/timer.h" - -#ifdef USE_MUMBLE -#include "mumblemanager.h" -#endif // USE_MUMBLE - -#include <climits> - -#include "debug.h" - -static const int16_t awayLimitTimer = 60; -static const int MAX_TICK_VALUE = INT_MAX / 2; - -typedef std::map<int, Guild*>::const_iterator GuildMapCIter; - -LocalPlayer *localPlayer = nullptr; - -extern OkDialog *weightNotice; -extern time_t weightNoticeTime; - -LocalPlayer::LocalPlayer(const BeingId id, - const BeingTypeId subType) : - Being(id, ActorType::Player), - ActorSpriteListener(), - AttributeListener(), - PlayerDeathListener(), - mMoveState(0), - mLastTargetX(0), - mLastTargetY(0), - mHomes(), - mTarget(nullptr), - mPlayerFollowed(), - mPlayerImitated(), - mNextDestX(0), - mNextDestY(0), - mPickUpTarget(nullptr), - mLastAction(-1), - mStatusEffectIcons(), - mMessages(), - mMessageTime(0), - mAwayListener(new AwayListener), - mAwayDialog(nullptr), - mPingSendTick(0), - mPingTime(0), - mAfkTime(0), - mActivityTime(0), - mNavigateX(0), - mNavigateY(0), - mNavigateId(BeingId_zero), - mCrossX(0), - mCrossY(0), - mOldX(0), - mOldY(0), - mOldTileX(0), - mOldTileY(0), - mNavigatePath(), - mLastHitFrom(), - mWaitFor(), - mAdvertTime(0), - mTestParticle(nullptr), - mTestParticleName(), - mTestParticleTime(0), - mTestParticleHash(0L), - mSyncPlayerMoveDistance(config.getIntValue("syncPlayerMoveDistance")), - mUnfreezeTime(0), - mWalkingDir(0), - mUpdateName(true), - mBlockAdvert(false), - mTargetDeadPlayers(config.getBoolValue("targetDeadPlayers")), - mServerAttack(fromBool(config.getBoolValue("serverAttack"), Keep)), - mVisibleNames(static_cast<VisibleName::Type>( - config.getIntValue("visiblenames"))), - mEnableAdvert(config.getBoolValue("enableAdvert")), - mTradebot(config.getBoolValue("tradebot")), - mTargetOnlyReachable(config.getBoolValue("targetOnlyReachable")), - mIsServerBuggy(serverConfig.getValueBool("enableBuggyServers", true)), - mSyncPlayerMove(config.getBoolValue("syncPlayerMove")), - mDrawPath(config.getBoolValue("drawPath")), - mAttackMoving(config.getBoolValue("attackMoving")), - mAttackNext(config.getBoolValue("attackNext")), - mShowJobExp(config.getBoolValue("showJobExp")), - mShowServerPos(config.getBoolValue("showserverpos")), - mNextStep(false), - mGoingToTarget(false), - mKeepAttacking(false), - mPathSetByMouse(false), - mWaitPing(false), - mShowNavigePath(false), - mAllowRename(false), - mFreezed(false) -{ - logger->log1("LocalPlayer::LocalPlayer"); - - postInit(subType, nullptr); - mAttackRange = 0; - mLevel = 1; - mAdvanced = true; - mTextColor = &theme->getColor(ThemeColorId::PLAYER, 255); - if (userPalette != nullptr) - mNameColor = &userPalette->getColor(UserColorId::SELF); - else - mNameColor = nullptr; - - PlayerInfo::setStatBase(Attributes::PLAYER_WALK_SPEED, - getWalkSpeed()); - PlayerInfo::setStatMod(Attributes::PLAYER_WALK_SPEED, 0); - - loadHomes(); - - config.addListener("showownname", this); - config.addListener("targetDeadPlayers", this); - serverConfig.addListener("enableBuggyServers", this); - config.addListener("syncPlayerMove", this); - config.addListener("syncPlayerMoveDistance", this); - config.addListener("drawPath", this); - config.addListener("serverAttack", this); - config.addListener("attackMoving", this); - config.addListener("attackNext", this); - config.addListener("showJobExp", this); - config.addListener("enableAdvert", this); - config.addListener("tradebot", this); - config.addListener("targetOnlyReachable", this); - config.addListener("showserverpos", this); - config.addListener("visiblenames", this); - setShowName(config.getBoolValue("showownname")); -} - -LocalPlayer::~LocalPlayer() -{ - logger->log1("LocalPlayer::~LocalPlayer"); - - config.removeListeners(this); - serverConfig.removeListener("enableBuggyServers", this); - - navigateClean(); - mCrossX = 0; - mCrossY = 0; - - updateNavigateList(); - - if (mAwayDialog != nullptr) - { - soundManager.volumeRestore(); - delete2(mAwayDialog) - } - delete2(mAwayListener); -} - -void LocalPlayer::logic() -{ - BLOCK_START("LocalPlayer::logic") -#ifdef USE_MUMBLE - if (mumbleManager) - mumbleManager->setPos(mX, mY, mDirection); -#endif // USE_MUMBLE - - // Actions are allowed once per second - if (get_elapsed_time(mLastAction) >= 1000) - mLastAction = -1; - - if (mActivityTime == 0 || mLastAction != -1) - mActivityTime = cur_time; - - if (mUnfreezeTime > 0 && - mUnfreezeTime <= tick_time) - { - mUnfreezeTime = 0; - mFreezed = false; - } - - if ((mAction != BeingAction::MOVE || mNextStep) && !mNavigatePath.empty()) - { - mNextStep = false; - int dist = 5; - if (!mSyncPlayerMove) - dist = 20; - - if (((mNavigateX != 0) || (mNavigateY != 0)) && - ((mCrossX + dist >= mX && mCrossX <= mX + dist - && mCrossY + dist >= mY && mCrossY <= mY + dist) - || ((mCrossX == 0) && (mCrossY == 0)))) - { - const Path::const_iterator i = mNavigatePath.begin(); - if ((*i).x == mX && (*i).y == mY) - mNavigatePath.pop_front(); - else - setDestination((*i).x, (*i).y); - } - } - - // Show XP messages - if (!mMessages.empty()) - { - if (mMessageTime == 0) - { - const MessagePair info = mMessages.front(); - - if ((particleEngine != nullptr) && (gui != nullptr)) - { - particleEngine->addTextRiseFadeOutEffect( - info.first, - mPixelX, - mPixelY - 48, - &userPalette->getColor(info.second), - gui->getInfoParticleFont(), - true); - } - - mMessages.pop_front(); - mMessageTime = 30; - } - mMessageTime--; - } - - if (mTarget != nullptr) - { - if (mTarget->getType() == ActorType::Npc) - { - // NPCs are always in range - mTarget->setTargetType(TargetCursorType::IN_RANGE); - } - else - { - // Find whether target is in range - const int rangeX = CAST_S32( - abs(mTarget->mX - mX)); - const int rangeY = CAST_S32( - abs(mTarget->mY - mY)); - const int attackRange = getAttackRange(); - const TargetCursorTypeT targetType - = rangeX > attackRange || rangeY > attackRange - ? TargetCursorType::NORMAL : TargetCursorType::IN_RANGE; - mTarget->setTargetType(targetType); - - if (!mTarget->isAlive() && (!mTargetDeadPlayers - || mTarget->getType() != ActorType::Player)) - { - stopAttack(true); - } - - if (mKeepAttacking && (mTarget != nullptr)) - attack(mTarget, true); - } - } - - Being::logic(); - BLOCK_END("LocalPlayer::logic") -} - -void LocalPlayer::slowLogic() -{ - BLOCK_START("LocalPlayer::slowLogic") - const time_t time = cur_time; - if ((weightNotice != nullptr) && weightNoticeTime < time) - { - weightNotice->scheduleDelete(); - weightNotice = nullptr; - weightNoticeTime = 0; - } - - if ((serverFeatures != nullptr) && - !serverFeatures->havePlayerStatusUpdate() && - mEnableAdvert && - !mBlockAdvert && - mAdvertTime < cur_time) - { - uint8_t smile = BeingFlag::SPECIAL; - if (mTradebot && - shopWindow != nullptr && - !shopWindow->isShopEmpty()) - { - smile |= BeingFlag::SHOP; - } - - if (settings.awayMode || settings.pseudoAwayMode) - smile |= BeingFlag::AWAY; - - if (mInactive) - smile |= BeingFlag::INACTIVE; - - if (emote(smile)) - mAdvertTime = time + 60; - else - mAdvertTime = time + 30; - } - - if (mTestParticleTime != time && !mTestParticleName.empty()) - { - const unsigned long hash = UpdaterWindow::getFileHash( - mTestParticleName); - if (hash != mTestParticleHash) - { - setTestParticle(mTestParticleName, false); - mTestParticleHash = hash; - } - mTestParticleTime = time; - } - - BLOCK_END("LocalPlayer::slowLogic") -} - -void LocalPlayer::setAction(const BeingActionT &action, - const int attackId) -{ - if (action == BeingAction::DEAD) - { - if (!mLastHitFrom.empty() && - !serverFeatures->haveKillerId()) - { - // TRANSLATORS: chat message after death - debugMsg(strprintf(_("You were killed by %s."), - mLastHitFrom.c_str())); - mLastHitFrom.clear(); - } - setTarget(nullptr); - } - - Being::setAction(action, - attackId); -#ifdef USE_MUMBLE - if (mumbleManager) - mumbleManager->setAction(CAST_S32(action)); -#endif // USE_MUMBLE -} - -void LocalPlayer::setGroupId(const int id) -{ - Being::setGroupId(id); - - if (id > 0) - { - setGM(true); - if (chatWindow != nullptr) - { - chatWindow->loadGMCommands(); - chatWindow->showGMTab(); - } - } - else - { - setGM(false); - } - if (statusWindow != nullptr) - statusWindow->updateLevelLabel(); -} - -void LocalPlayer::nextTile(unsigned char dir A_UNUSED = 0) -{ - const Party *const party = Party::getParty(1); - if (party != nullptr) - { - PartyMember *const pm = party->getMember(mName); - if (pm != nullptr) - { - pm->setX(mX); - pm->setY(mY); - } - } - - if (mPath.empty()) - { - if (mPickUpTarget != nullptr) - pickUp(mPickUpTarget); - - if (mWalkingDir != 0u) - startWalking(mWalkingDir); - } - else if (mPath.size() == 1) - { - if (mPickUpTarget != nullptr) - pickUp(mPickUpTarget); - } - - if (mGoingToTarget && (mTarget != nullptr) && withinAttackRange(mTarget)) - { - mAction = BeingAction::STAND; - attack(mTarget, true); - mGoingToTarget = false; - mPath.clear(); - return; - } - else if (mGoingToTarget && (mTarget == nullptr)) - { - mGoingToTarget = false; - mPath.clear(); - } - - if (mPath.empty()) - { - if (mNavigatePath.empty() || mAction != BeingAction::MOVE) - setAction(BeingAction::STAND, 0); - else - mNextStep = true; - } - else - { - Being::nextTile(); - } -} - -bool LocalPlayer::pickUp(FloorItem *const item) -{ - if (item == nullptr) - return false; - - if (!PacketLimiter::limitPackets(PacketType::PACKET_PICKUP)) - return false; - - const int dx = item->getTileX() - mX; - const int dy = item->getTileY() - mY; - int dist = 6; - - const unsigned int pickUpType = settings.pickUpType; - if (pickUpType >= 4 && pickUpType <= 6) - dist = 4; - - if (dx * dx + dy * dy < dist) - { - if ((actorManager != nullptr) && actorManager->checkForPickup(item)) - { - PlayerInfo::pickUpItem(item, Sfx_true); - mPickUpTarget = nullptr; - } - } - else if (pickUpType >= 4 && pickUpType <= 6) - { - const Path debugPath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - item->getTileX(), - item->getTileY(), - getBlockWalkMask(), - 0); - if (!debugPath.empty()) - navigateTo(item->getTileX(), item->getTileY()); - else - setDestination(item->getTileX(), item->getTileY()); - - mPickUpTarget = item; - mPickUpTarget->addActorSpriteListener(this); - } - return true; -} - -void LocalPlayer::actorSpriteDestroyed(const ActorSprite &actorSprite) -{ - if (mPickUpTarget == &actorSprite) - mPickUpTarget = nullptr; -} - -Being *LocalPlayer::getTarget() const -{ - return mTarget; -} - -void LocalPlayer::setTarget(Being *const target) -{ - if (target == this && (target != nullptr)) - return; - - if (target == mTarget) - return; - - Being *oldTarget = nullptr; - if (mTarget != nullptr) - { - mTarget->untarget(); - oldTarget = mTarget; - } - - if (mTarget != nullptr) - { - if (mTarget->getType() == ActorType::Monster) - mTarget->setShowName(false); - } - - mTarget = target; - - if (oldTarget != nullptr) - oldTarget->updateName(); - - if (target != nullptr) - { - mLastTargetX = target->mX; - mLastTargetY = target->mY; - target->updateName(); - if (mVisibleNames == VisibleName::ShowOnSelection) - target->setShowName(true); - } - if (oldTarget != nullptr && mVisibleNames == VisibleName::ShowOnSelection) - oldTarget->setShowName(false); - if (target != nullptr && target->getType() == ActorType::Monster) - target->setShowName(true); -} - -Being *LocalPlayer::setNewTarget(const ActorTypeT type, - const AllowSort allowSort) -{ - if (actorManager != nullptr) - { - Being *const target = actorManager->findNearestLivingBeing( - localPlayer, 20, type, allowSort); - - if ((target != nullptr) && target != mTarget) - setTarget(target); - - return target; - } - return nullptr; -} - -void LocalPlayer::setDestination(const int x, const int y) -{ - mActivityTime = cur_time; - - if (settings.attackType == 0 || !mAttackMoving) - mKeepAttacking = false; - - // Only send a new message to the server when destination changes - if (x != mDest.x || y != mDest.y) - { - if (settings.moveType != 1) - { - playerHandler->setDestination(x, y, mDirection); - Being::setDestination(x, y); - } - else - { - uint8_t newDir = 0; - if ((mDirection & BeingDirection::UP) != 0) - newDir |= BeingDirection::DOWN; - if ((mDirection & BeingDirection::LEFT) != 0) - newDir |= BeingDirection::RIGHT; - if ((mDirection & BeingDirection::DOWN) != 0) - newDir |= BeingDirection::UP; - if ((mDirection & BeingDirection::RIGHT) != 0) - newDir |= BeingDirection::LEFT; - - playerHandler->setDestination(x, y, newDir); - -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - setDirection(newDir); - playerHandler->setDirection(newDir); - } - - Being::setDestination(x, y); - playerHandler->setDestination(x, y, mDirection); - } - } -} - -void LocalPlayer::setWalkingDir(const unsigned char dir) -{ - // This function is called by Game::handleInput() - mWalkingDir = dir; - - // If we're not already walking, start walking. - if (mAction != BeingAction::MOVE && (dir != 0u)) - startWalking(dir); -} - -void LocalPlayer::startWalking(const unsigned char dir) -{ - // This function is called by setWalkingDir(), - // but also by nextTile() for TMW-Athena... - if ((mMap == nullptr) || (dir == 0u)) - return; - - mPickUpTarget = nullptr; - if (mAction == BeingAction::MOVE && !mPath.empty()) - { - // Just finish the current action, otherwise we get out of sync - Being::setDestination(mX, mY); - return; - } - - int dx = 0, dy = 0; - if ((dir & BeingDirection::UP) != 0) - dy--; - if ((dir & BeingDirection::DOWN) != 0) - dy++; - if ((dir & BeingDirection::LEFT) != 0) - dx--; - if ((dir & BeingDirection::RIGHT) != 0) - dx++; - - const unsigned char blockWalkMask = getBlockWalkMask(); - // Prevent skipping corners over colliding tiles - if ((dx != 0) && !mMap->getWalk(mX + dx, mY, blockWalkMask)) - dx = 0; - if ((dy != 0) && !mMap->getWalk(mX, mY + dy, blockWalkMask)) - dy = 0; - - // Choose a straight direction when diagonal target is blocked - if (dx != 0 && dy != 0 && !mMap->getWalk(mX + dx, mY + dy, blockWalkMask)) - dx = 0; - - // Walk to where the player can actually go - if ((dx != 0 || dy != 0) && mMap->getWalk(mX + dx, mY + dy, blockWalkMask)) - { - setDestination(mX + dx, mY + dy); - } - else if (dir != mDirection) - { - // If the being can't move, just change direction - -// if (PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - { - playerHandler->setDirection(dir); - setDirection(dir); - } - } -} - -void LocalPlayer::stopWalking(const bool sendToServer) -{ - if (mAction == BeingAction::MOVE && (mWalkingDir != 0u)) - { - mWalkingDir = 0; - mPickUpTarget = nullptr; - setDestination(mPixelX, - mPixelY); - if (sendToServer) - { - playerHandler->setDestination( - mPixelX, - mPixelY, - -1); - } - setAction(BeingAction::STAND, 0); - } - - // No path set anymore, so we reset the path by mouse flag - mPathSetByMouse = false; - - clearPath(); - navigateClean(); -} - -bool LocalPlayer::toggleSit() const -{ - if (!PacketLimiter::limitPackets(PacketType::PACKET_SIT)) - return false; - - BeingActionT newAction; - switch (mAction) - { - case BeingAction::STAND: - case BeingAction::PRESTAND: - case BeingAction::SPAWN: - newAction = BeingAction::SIT; - break; - case BeingAction::SIT: - newAction = BeingAction::STAND; - break; - case BeingAction::MOVE: - case BeingAction::ATTACK: - case BeingAction::DEAD: - case BeingAction::HURT: - case BeingAction::CAST: - default: - return true; - } - - playerHandler->changeAction(newAction); - return true; -} - -bool LocalPlayer::updateSit() const -{ - if (!PacketLimiter::limitPackets(PacketType::PACKET_SIT)) - return false; - - playerHandler->changeAction(mAction); - return true; -} - -bool LocalPlayer::emote(const uint8_t emotion) -{ - if (!PacketLimiter::limitPackets(PacketType::PACKET_EMOTE)) - return false; - - playerHandler->emote(emotion); - return true; -} - -void LocalPlayer::attack(Being *const target, const bool keep, - const bool dontChangeEquipment) -{ - mKeepAttacking = keep; - - if ((target == nullptr) || target->getType() == ActorType::Npc) - return; - - if (mTarget != target) - setTarget(target); - - // Must be standing or sitting or casting to attack - if (mAction != BeingAction::STAND && - mAction != BeingAction::SIT && - mAction != BeingAction::CAST) - { - return; - } - -#ifdef TMWA_SUPPORT - const int dist_x = target->mX - mX; - const int dist_y = target->mY - mY; - - if (Net::getNetworkType() == ServerType::TMWATHENA) - { - if (abs(dist_y) >= abs(dist_x)) - { - if (dist_y > 0) - setDirection(BeingDirection::DOWN); - else - setDirection(BeingDirection::UP); - } - else - { - if (dist_x > 0) - setDirection(BeingDirection::RIGHT); - else - setDirection(BeingDirection::LEFT); - } - } -#endif // TMWA_SUPPORT - - mActionTime = tick_time; - - if (target->getType() != ActorType::Player - || checAttackPermissions(target)) - { - setAction(BeingAction::ATTACK, 0); - - if (!PacketLimiter::limitPackets(PacketType::PACKET_ATTACK)) - return; - - if (!dontChangeEquipment) - changeEquipmentBeforeAttack(target); - - const BeingId targetId = target->getId(); - playerHandler->attack(targetId, mServerAttack); - PlayerInfo::updateAttackAi(targetId, mServerAttack); - } - - if (!keep) - stopAttack(); -} - -void LocalPlayer::stopAttack(const bool keepAttack) -{ - if (!PacketLimiter::limitPackets(PacketType::PACKET_STOPATTACK)) - return; - - if (mServerAttack == Keep_true && mAction == BeingAction::ATTACK) - playerHandler->stopAttack(); - - untarget(); - if (!keepAttack || !mAttackNext) - mKeepAttacking = false; -} - -void LocalPlayer::untarget() -{ - if (mAction == BeingAction::ATTACK) - setAction(BeingAction::STAND, 0); - - if (mTarget != nullptr) - setTarget(nullptr); -} - -void LocalPlayer::pickedUp(const ItemInfo &itemInfo, - const int amount, - const ItemColor color, - const BeingId floorItemId, - const PickupT fail) -{ - if (fail != Pickup::OKAY) - { - if ((actorManager != nullptr) && floorItemId != BeingId_zero) - { - FloorItem *const item = actorManager->findItem(floorItemId); - if (item != nullptr) - { - if (!item->getShowMsg()) - return; - item->setShowMsg(false); - } - } - const char* msg = nullptr; - switch (fail) - { - case Pickup::BAD_ITEM: - // TRANSLATORS: pickup error message - msg = N_("Tried to pick up nonexistent item."); - break; - case Pickup::TOO_HEAVY: - // TRANSLATORS: pickup error message - msg = N_("Item is too heavy."); - break; - case Pickup::TOO_FAR: - // TRANSLATORS: pickup error message - msg = N_("Item is too far away."); - break; - case Pickup::INV_FULL: - // TRANSLATORS: pickup error message - msg = N_("Inventory is full."); - break; - case Pickup::STACK_FULL: - // TRANSLATORS: pickup error message - msg = N_("Stack is too big."); - break; - case Pickup::DROP_STEAL: - // TRANSLATORS: pickup error message - msg = N_("Item belongs to someone else."); - break; - case Pickup::MAX_AMOUNT: - // TRANSLATORS: pickup error message - msg = N_("You can't pickup this amount of items."); - break; - case Pickup::STACK_AMOUNT: - // TRANSLATORS: pickup error message - msg = N_("Your item stack has max amount."); - break; - case Pickup::OKAY: - break; - default: - case Pickup::UNKNOWN: - // TRANSLATORS: pickup error message - msg = N_("Unknown problem picking up item."); - break; - } - if ((localChatTab != nullptr) && config.getBoolValue("showpickupchat")) - localChatTab->chatLog(gettext(msg), ChatMsgType::BY_SERVER); - - if ((mMap != nullptr) && config.getBoolValue("showpickupparticle")) - { - // Show pickup notification - addMessageToQueue(gettext(msg), UserColorId::PICKUP_INFO); - } - } - else - { - std::string str; -#ifdef TMWA_SUPPORT - if (Net::getNetworkType() == ServerType::TMWATHENA) - { - str = itemInfo.getName(); - } - else -#endif // TMWA_SUPPORT - { - str = itemInfo.getName(color); - } - - if (config.getBoolValue("showpickupchat") && (localChatTab != nullptr)) - { - // TRANSLATORS: %d is number, - // [@@%d|%s@@] - here player can see link to item - localChatTab->chatLog(strprintf(ngettext("You picked up %d " - "[@@%d|%s@@].", "You picked up %d [@@%d|%s@@].", amount), - amount, itemInfo.getId(), str.c_str()), - ChatMsgType::BY_SERVER); - } - - if ((mMap != nullptr) && config.getBoolValue("showpickupparticle")) - { - // Show pickup notification - if (amount > 1) - { - addMessageToQueue(strprintf("%d x %s", amount, - str.c_str()), UserColorId::PICKUP_INFO); - } - else - { - addMessageToQueue(str, UserColorId::PICKUP_INFO); - } - } - } -} - -int LocalPlayer::getAttackRange() const -{ - if (mAttackRange > -1) - { - return mAttackRange; - } - - const Item *const weapon = PlayerInfo::getEquipment( - EquipSlot::FIGHT1_SLOT); - if (weapon != nullptr) - { - const ItemInfo &info = weapon->getInfo(); - return info.getAttackRange(); - } - return 48; // unarmed range -} - -bool LocalPlayer::withinAttackRange(const Being *const target, - const bool fixDistance, - const int addRange) const -{ - if (target == nullptr) - return false; - - int range = getAttackRange() + addRange; - int dx; - int dy; - - if (fixDistance && range == 1) - range = 2; - - dx = CAST_S32(abs(target->mX - mX)); - dy = CAST_S32(abs(target->mY - mY)); - return !(dx > range || dy > range); -} - -void LocalPlayer::setGotoTarget(Being *const target) -{ - if (target == nullptr) - return; - - mPickUpTarget = nullptr; - setTarget(target); - mGoingToTarget = true; - navigateTo(target->mX, - target->mY); -} - -void LocalPlayer::handleStatusEffect(const StatusEffect *const effect, - const int32_t effectId, - const Enable newStatus, - const IsStart start) -{ - Being::handleStatusEffect(effect, - effectId, - newStatus, - start); - - if (effect != nullptr) - { - effect->deliverMessage(); - effect->playSFX(); - - AnimatedSprite *const sprite = effect->getIcon(); - - if (sprite == nullptr) - { - // delete sprite, if necessary - for (size_t i = 0; i < mStatusEffectIcons.size(); ) - { - if (mStatusEffectIcons[i] == effectId) - { - mStatusEffectIcons.erase(mStatusEffectIcons.begin() + i); - if (miniStatusWindow != nullptr) - miniStatusWindow->eraseIcon(CAST_S32(i)); - } - else - { - i++; - } - } - } - else - { - // replace sprite or append - bool found = false; - const size_t sz = mStatusEffectIcons.size(); - for (size_t i = 0; i < sz; i++) - { - if (mStatusEffectIcons[i] == effectId) - { - if (miniStatusWindow != nullptr) - miniStatusWindow->setIcon(CAST_S32(i), sprite); - found = true; - break; - } - } - - if (!found) - { // add new - const int offset = CAST_S32(mStatusEffectIcons.size()); - if (miniStatusWindow != nullptr) - miniStatusWindow->setIcon(offset, sprite); - mStatusEffectIcons.push_back(effectId); - } - } - } -} - -void LocalPlayer::addMessageToQueue(const std::string &message, - const UserColorIdT color) -{ - if (mMessages.size() < 20) - mMessages.push_back(MessagePair(message, color)); -} - -void LocalPlayer::optionChanged(const std::string &value) -{ - if (value == "showownname") - { - setShowName(config.getBoolValue("showownname")); - } - else if (value == "targetDeadPlayers") - { - mTargetDeadPlayers = config.getBoolValue("targetDeadPlayers"); - } - else if (value == "enableBuggyServers") - { - mIsServerBuggy = serverConfig.getBoolValue("enableBuggyServers"); - } - else if (value == "syncPlayerMove") - { - mSyncPlayerMove = config.getBoolValue("syncPlayerMove"); - } - else if (value == "syncPlayerMoveDistance") - { - mSyncPlayerMoveDistance = config.getIntValue("syncPlayerMoveDistance"); - } - else if (value == "drawPath") - { - mDrawPath = config.getBoolValue("drawPath"); - } - else if (value == "serverAttack") - { - mServerAttack = fromBool(config.getBoolValue("serverAttack"), Keep); - } - else if (value == "attackMoving") - { - mAttackMoving = config.getBoolValue("attackMoving"); - } - else if (value == "attackNext") - { - mAttackNext = config.getBoolValue("attackNext"); - } - else if (value == "showJobExp") - { - mShowJobExp = config.getBoolValue("showJobExp"); - } - else if (value == "enableAdvert") - { - mEnableAdvert = config.getBoolValue("enableAdvert"); - } - else if (value == "tradebot") - { - mTradebot = config.getBoolValue("tradebot"); - } - else if (value == "targetOnlyReachable") - { - mTargetOnlyReachable = config.getBoolValue("targetOnlyReachable"); - } - else if (value == "showserverpos") - { - mShowServerPos = config.getBoolValue("showserverpos"); - } - else if (value == "visiblenames") - { - mVisibleNames = static_cast<VisibleName::Type>( - config.getIntValue("visiblenames")); - } -} - -void LocalPlayer::addJobMessage(const int change) -{ - if (change != 0 && mMessages.size() < 20) - { - if (!mMessages.empty()) - { - MessagePair pair = mMessages.back(); - // TRANSLATORS: this is normal experience - if (pair.first.find(strprintf(" %s", _("xp"))) == - // TRANSLATORS: this is normal experience - pair.first.size() - strlen(_("xp")) - 1) - { - mMessages.pop_back(); - // TRANSLATORS: this is job experience - pair.first.append(strprintf(", %d %s", change, _("job"))); - mMessages.push_back(pair); - } - else - { - // TRANSLATORS: this is job experience - addMessageToQueue(strprintf("%d %s", change, _("job"))); - } - } - else - { - // TRANSLATORS: this is job experience - addMessageToQueue(strprintf("%d %s", change, _("job"))); - } - } -} - -void LocalPlayer::addXpMessage(const int change) -{ - if (change != 0 && mMessages.size() < 20) - { - // TRANSLATORS: get xp message - addMessageToQueue(strprintf("%d %s", change, _("xp"))); - } -} - -void LocalPlayer::addHomunXpMessage(const int change) -{ - if (change != 0 && mMessages.size() < 20) - { - addMessageToQueue(strprintf("%s %d %s", - // TRANSLATORS: get homunculus xp message - _("Homun"), - change, - // TRANSLATORS: get xp message - _("xp"))); - } -} - -void LocalPlayer::addHpMessage(const int change) -{ - if (change != 0 && mMessages.size() < 20) - { - // TRANSLATORS: get hp message - addMessageToQueue(strprintf("%d %s", change, _("hp"))); - } -} - -void LocalPlayer::addSpMessage(const int change) -{ - if (change != 0 && mMessages.size() < 20) - { - // TRANSLATORS: get hp message - addMessageToQueue(strprintf("%d %s", change, _("mana"))); - } -} - -void LocalPlayer::attributeChanged(const AttributesT id, - const int64_t oldVal, - const int64_t newVal) -{ - PRAGMA45(GCC diagnostic push) - PRAGMA45(GCC diagnostic ignored "-Wswitch-enum") - switch (id) - { - case Attributes::PLAYER_EXP: - { - if (Net::getNetworkType() != ServerType::TMWATHENA) - break; - if (oldVal > newVal) - break; - - const int change = CAST_S32(newVal - oldVal); - addXpMessage(change); - break; - } - case Attributes::PLAYER_BASE_LEVEL: - mLevel = CAST_S32(newVal); - break; - case Attributes::PLAYER_HP: - if (oldVal != 0 && newVal == 0) - PlayerDeathListener::distributeEvent(); - break; - case Attributes::PLAYER_JOB_EXP: - { - if (!mShowJobExp || - Net::getNetworkType() != ServerType::TMWATHENA) - { - return; - } - if (oldVal > newVal || - PlayerInfo::getAttribute( - Attributes::PLAYER_JOB_EXP_NEEDED) == 0) - { - return; - } - const int32_t change = CAST_S32(newVal - oldVal); - addJobMessage(change); - break; - } - default: - break; - } - PRAGMA45(GCC diagnostic pop) -} - -void LocalPlayer::move(const int dX, const int dY) -{ - mPickUpTarget = nullptr; - setDestination(mX + dX, mY + dY); -} - -void LocalPlayer::moveToTarget(int dist) -{ - bool gotPos(false); - Path debugPath; - - size_t limit(0); - - if (dist == -1) - { - dist = settings.moveToTargetType; - if (dist != 0) - { - const bool broken = (Net::getNetworkType() == - ServerType::TMWATHENA); - switch (dist) - { - case 10: - dist = mAttackRange; - if (dist == 1 && broken) - dist = 2; - break; - case 11: - dist = mAttackRange - 1; - if (dist < 1) - dist = 1; - if (dist == 1 && broken) - dist = 2; - break; - default: - break; - } - } - } - - if (mTarget != nullptr) - { - if (mMap != nullptr) - { - debugPath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - mTarget->mX, - mTarget->mY, - getBlockWalkMask(), - 0); - } - - const size_t sz = debugPath.size(); - if (sz < CAST_SIZE(dist)) - return; - limit = CAST_S32(sz) - dist; - gotPos = true; - } - else if ((mNavigateX != 0) || (mNavigateY != 0)) - { - debugPath = mNavigatePath; - limit = dist; - gotPos = true; - } - - if (gotPos) - { - if (dist == 0) - { - if (mTarget != nullptr) - navigateTo(mTarget->mX, mTarget->mY); - } - else - { - Position pos(0, 0); - size_t f = 0; - - for (Path::const_iterator i = debugPath.begin(), - i_fend = debugPath.end(); - i != i_fend && f < limit; ++i, f++) - { - pos = (*i); - } - navigateTo(pos.x, pos.y); - } - } - else if ((mLastTargetX != 0) || (mLastTargetY != 0)) - { - navigateTo(mLastTargetX, mLastTargetY); - } -} - -void LocalPlayer::moveToHome() -{ - mPickUpTarget = nullptr; - if ((mX != mCrossX || mY != mCrossY) && (mCrossX != 0) && (mCrossY != 0)) - { - setDestination(mCrossX, mCrossY); - } - else if (mMap != nullptr) - { - const std::map<std::string, Vector>::const_iterator iter = - mHomes.find(mMap->getProperty("_realfilename")); - - if (iter != mHomes.end()) - { - const Vector pos = mHomes[(*iter).first]; - if (mX == pos.x && mY == pos.y) - { - playerHandler->setDestination( - CAST_S32(pos.x), - CAST_S32(pos.y), - CAST_S32(mDirection)); - } - else - { - navigateTo(CAST_S32(pos.x), CAST_S32(pos.y)); - } - } - } -} - -void LocalPlayer::changeEquipmentBeforeAttack(const Being *const target) const -{ - if (settings.attackWeaponType == 1 - || (target == nullptr) - || (PlayerInfo::getInventory() == nullptr)) - { - return; - } - - bool allowSword = false; - const int dx = target->mX - mX; - const int dy = target->mY - mY; - const Item *item = nullptr; - - if (dx * dx + dy * dy > 80) - return; - - if (dx * dx + dy * dy < 8) - allowSword = true; - - const Inventory *const inv = PlayerInfo::getInventory(); - if (inv == nullptr) - return; - - // if attack distance for sword - if (allowSword) - { - // searching swords - const WeaponsInfos &swords = WeaponsDB::getSwords(); - FOR_EACH (WeaponsInfosIter, it, swords) - { - item = inv->findItem(*it, ItemColor_zero); - if (item != nullptr) - break; - } - - // no swords - if (item == nullptr) - return; - - // if sword not equiped - if (item->isEquipped() == Equipped_false) - PlayerInfo::equipItem(item, Sfx_true); - - // if need equip shield too - if (settings.attackWeaponType == 3) - { - // searching shield - const WeaponsInfos &shields = WeaponsDB::getShields(); - FOR_EACH (WeaponsInfosIter, it, shields) - { - item = inv->findItem(*it, ItemColor_zero); - if (item != nullptr) - break; - } - if ((item != nullptr) && item->isEquipped() == Equipped_false) - PlayerInfo::equipItem(item, Sfx_true); - } - } - // big distance. allowed only bow - else - { - // searching bow - const WeaponsInfos &bows = WeaponsDB::getBows(); - FOR_EACH (WeaponsInfosIter, it, bows) - { - item = inv->findItem(*it, ItemColor_zero); - if (item != nullptr) - break; - } - - // no bow - if (item == nullptr) - return; - - if (item->isEquipped() == Equipped_false) - PlayerInfo::equipItem(item, Sfx_true); - } -} - -bool LocalPlayer::isReachable(Being *const being, - const int maxCost) -{ - if ((being == nullptr) || (mMap == nullptr)) - return false; - - if (being->getReachable() == Reachable::REACH_NO) - return false; - - if (being->mX == mX && - being->mY == mY) - { - being->setDistance(0); - being->setReachable(Reachable::REACH_YES); - return true; - } - else if (being->mX - 1 <= mX && - being->mX + 1 >= mX && - being->mY - 1 <= mY && - being->mY + 1 >= mY) - { - being->setDistance(1); - being->setReachable(Reachable::REACH_YES); - return true; - } - - const Path debugPath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - being->mX, - being->mY, - getBlockWalkMask(), - maxCost); - - being->setDistance(CAST_S32(debugPath.size())); - if (!debugPath.empty()) - { - being->setReachable(Reachable::REACH_YES); - return true; - } - being->setReachable(Reachable::REACH_NO); - return false; -} - -bool LocalPlayer::isReachable(const int x, const int y, - const bool allowCollision) const -{ - const WalkLayer *const walk = mMap->getWalkLayer(); - if (walk == nullptr) - return false; - int num = walk->getDataAt(x, y); - if (allowCollision && num < 0) - num = -num; - - return walk->getDataAt(mX, mY) == num; -} - -bool LocalPlayer::pickUpItems(int pickUpType) -{ - if (actorManager == nullptr) - return false; - - bool status = false; - int x = mX; - int y = mY; - - // first pick up item on player position - FloorItem *item = - actorManager->findItem(x, y); - if (item != nullptr) - status = pickUp(item); - - if (pickUpType == 0) - pickUpType = settings.pickUpType; - - if (pickUpType == 0) - return status; - - int x1, y1, x2, y2; - switch (pickUpType) - { - case 1: - switch (mDirection) - { - case BeingDirection::UP : --y; break; - case BeingDirection::DOWN : ++y; break; - case BeingDirection::LEFT : --x; break; - case BeingDirection::RIGHT: ++x; break; - default: break; - } - item = actorManager->findItem(x, y); - if (item != nullptr) - status = pickUp(item); - break; - case 2: - switch (mDirection) - { - case BeingDirection::UP: - x1 = x - 1; y1 = y - 1; x2 = x + 1; y2 = y; break; - case BeingDirection::DOWN: - x1 = x - 1; y1 = y; x2 = x + 1; y2 = y + 1; break; - case BeingDirection::LEFT: - x1 = x - 1; y1 = y - 1; x2 = x; y2 = y + 1; break; - case BeingDirection::RIGHT: - x1 = x; y1 = y - 1; x2 = x + 1; y2 = y + 1; break; - default: - x1 = x; x2 = x; y1 = y; y2 = y; break; - } - if (actorManager->pickUpAll(x1, y1, x2, y2)) - status = true; - break; - case 3: - if (actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1)) - status = true; - break; - - case 4: - if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1)) - { - if (actorManager->pickUpNearest(x, y, 4)) - status = true; - } - else - { - status = true; - } - break; - - case 5: - if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1)) - { - if (actorManager->pickUpNearest(x, y, 8)) - status = true; - } - else - { - status = true; - } - break; - - case 6: - if (!actorManager->pickUpAll(x - 1, y - 1, x + 1, y + 1)) - { - if (actorManager->pickUpNearest(x, y, 90)) - status = true; - } - else - { - status = true; - } - break; - - default: - break; - } - return status; -} - - -void LocalPlayer::moveByDirection(const unsigned char dir) -{ - int dx = 0, dy = 0; - if ((dir & BeingDirection::UP) != 0) - dy--; - if ((dir & BeingDirection::DOWN) != 0) - dy++; - if ((dir & BeingDirection::LEFT) != 0) - dx--; - if ((dir & BeingDirection::RIGHT) != 0) - dx++; - move(dx, dy); -} - -void LocalPlayer::specialMove(const unsigned char direction) -{ - if ((direction != 0u) && ((mNavigateX != 0) || (mNavigateY != 0))) - navigateClean(); - - if ((direction != 0u) && (settings.moveType >= 2 - && settings.moveType <= 4)) - { - if (mAction == BeingAction::MOVE) - return; - - unsigned int max; - - if (settings.moveType == 2) - max = 5; - else if (settings.moveType == 4) - max = 1; - else - max = 3; - - if (getMoveState() < max) - { - moveByDirection(direction); - mMoveState ++; - } - else - { - mMoveState = 0; - crazyMoves->crazyMove(); - } - } - else - { - setWalkingDir(direction); - } -} - -#ifdef TMWA_SUPPORT -void LocalPlayer::magicAttack() const -{ - if (Net::getNetworkType() != ServerType::TMWATHENA) - return; - if (chatWindow == nullptr || - !isAlive() || - !playerHandler->canUseMagic()) - { - return; - } - - switch (settings.magicAttackType) - { - // flar W00 - case 0: - tryMagic("#flar", 1, 0, 10); - break; - // chiza W01 - case 1: - tryMagic("#chiza", 1, 0, 9); - break; - // ingrav W10 - case 2: - tryMagic("#ingrav", 2, 2, 20); - break; - // frillyar W11 - case 3: - tryMagic("#frillyar", 2, 2, 25); - break; - // upmarmu W12 - case 4: - tryMagic("#upmarmu", 2, 2, 20); - break; - default: - break; - } -} - -void LocalPlayer::tryMagic(const std::string &spell, const int baseMagic, - const int schoolMagic, const int mana) -{ - if (chatWindow == nullptr) - return; - - if (PlayerInfo::getSkillLevel(340) >= baseMagic - && PlayerInfo::getSkillLevel(342) >= schoolMagic) - { - if (PlayerInfo::getAttribute(Attributes::PLAYER_MP) >= mana) - { - if (!PacketLimiter::limitPackets(PacketType::PACKET_CHAT)) - return; - - chatWindow->localChatInput(spell); - } - } -} -#endif // TMWA_SUPPORT - -void LocalPlayer::loadHomes() -{ - std::string buf; - std::stringstream ss(serverConfig.getValue("playerHomes", "")); - - while (ss >> buf) - { - Vector pos; - ss >> pos.x; - ss >> pos.y; - mHomes[buf] = pos; - } -} - -void LocalPlayer::setMap(Map *const map) -{ - BLOCK_START("LocalPlayer::setMap") - if (map != nullptr) - { - if (socialWindow != nullptr) - socialWindow->updateActiveList(); - } - navigateClean(); - mCrossX = 0; - mCrossY = 0; - - Being::setMap(map); - updateNavigateList(); - BLOCK_END("LocalPlayer::setMap") -} - -void LocalPlayer::setHome() -{ - if ((mMap == nullptr) || (socialWindow == nullptr)) - return; - - SpecialLayer *const specialLayer = mMap->getSpecialLayer(); - - if (specialLayer == nullptr) - return; - - const std::string key = mMap->getProperty("_realfilename"); - Vector pos = mHomes[key]; - - if (mAction == BeingAction::SIT) - { - const std::map<std::string, Vector>::const_iterator - iter = mHomes.find(key); - - if (iter != mHomes.end()) - { - socialWindow->removePortal(CAST_S32(pos.x), - CAST_S32(pos.y)); - } - - if (iter != mHomes.end() && mX == CAST_S32(pos.x) - && mY == CAST_S32(pos.y)) - { - mMap->updatePortalTile("", MapItemType::EMPTY, - CAST_S32(pos.x), CAST_S32(pos.y)); - - mHomes.erase(key); - socialWindow->removePortal(CAST_S32(pos.x), - CAST_S32(pos.y)); - } - else - { - if (iter != mHomes.end()) - { - specialLayer->setTile(CAST_S32(pos.x), - CAST_S32(pos.y), MapItemType::EMPTY); - specialLayer->updateCache(); - } - - pos.x = static_cast<float>(mX); - pos.y = static_cast<float>(mY); - mHomes[key] = pos; - mMap->updatePortalTile("home", MapItemType::HOME, - mX, mY); - socialWindow->addPortal(mX, mY); - } - MapItem *const mapItem = specialLayer->getTile(mX, mY); - if (mapItem != nullptr) - { - const int idx = socialWindow->getPortalIndex(mX, mY); - mapItem->setName(KeyboardConfig::getKeyShortString( - OutfitWindow::keyName(idx))); - } - saveHomes(); - } - else - { - MapItem *mapItem = specialLayer->getTile(mX, mY); - int type = 0; - - const std::map<std::string, Vector>::iterator iter = mHomes.find(key); - if (iter != mHomes.end() && mX == pos.x && mY == pos.y) - { - mHomes.erase(key); - saveHomes(); - } - - if ((mapItem == nullptr) || mapItem->getType() == MapItemType::EMPTY) - { - if ((mDirection & BeingDirection::UP) != 0) - type = MapItemType::ARROW_UP; - else if ((mDirection & BeingDirection::LEFT) != 0) - type = MapItemType::ARROW_LEFT; - else if ((mDirection & BeingDirection::DOWN) != 0) - type = MapItemType::ARROW_DOWN; - else if ((mDirection & BeingDirection::RIGHT) != 0) - type = MapItemType::ARROW_RIGHT; - } - else - { - type = MapItemType::EMPTY; - } - mMap->updatePortalTile("", type, mX, mY); - - if (type != MapItemType::EMPTY) - { - socialWindow->addPortal(mX, mY); - mapItem = specialLayer->getTile(mX, mY); - if (mapItem != nullptr) - { - const int idx = socialWindow->getPortalIndex(mX, mY); - mapItem->setName(KeyboardConfig::getKeyShortString( - OutfitWindow::keyName(idx))); - } - } - else - { - specialLayer->setTile(mX, mY, MapItemType::EMPTY); - specialLayer->updateCache(); - socialWindow->removePortal(mX, mY); - } - } -} - -void LocalPlayer::saveHomes() -{ - std::stringstream ss; - - for (std::map<std::string, Vector>::const_iterator iter = mHomes.begin(), - iter_fend = mHomes.end(); - iter != iter_fend; - ++iter) - { - const Vector &pos = (*iter).second; - - if (iter != mHomes.begin()) - ss << " "; - ss << (*iter).first << " " << pos.x << " " << pos.y; - } - - serverConfig.setValue("playerHomes", ss.str()); -} - -void LocalPlayer::pingRequest() -{ - const int time = tick_time; - if (mWaitPing == true && mPingSendTick != 0) - { - if (time >= mPingSendTick && (time - mPingSendTick) > 1000) - return; - } - - mPingSendTick = time; - mWaitPing = true; - beingHandler->requestNameById(getId()); -} - -std::string LocalPlayer::getPingTime() const -{ - std::string str; - if (!mWaitPing) - { - if (mPingTime == 0) - str = "?"; - else - str = toString(CAST_S32(mPingTime)); - } - else - { - time_t time = tick_time; - if (time > mPingSendTick) - time -= mPingSendTick; - else - time += MAX_TICK_VALUE - mPingSendTick; - if (time <= mPingTime) - time = mPingTime; - if (mPingTime != time) - str = strprintf("%d (%d)", CAST_S32(mPingTime), CAST_S32(time)); - else - str = toString(CAST_S32(time)); - } - return str; -} - -void LocalPlayer::pingResponse() -{ - if (mWaitPing == true && mPingSendTick > 0) - { - mWaitPing = false; - const int time = tick_time; - if (time < mPingSendTick) - { - mPingSendTick = 0; - mPingTime = 0; - } - else - { - mPingTime = (time - mPingSendTick) * 10; - } - } -} - -void LocalPlayer::tryPingRequest() -{ - if (mPingSendTick == 0 || tick_time < mPingSendTick - || (tick_time - mPingSendTick) > 200) - { - pingRequest(); - } -} - - -void LocalPlayer::setAway(const std::string &message) const -{ - setAfkMessage(message); - GameModifiers::changeAwayMode(true); - updateStatus(); -} - -void LocalPlayer::setAfkMessage(std::string message) -{ - if (!message.empty()) - { - if (message.size() > 4 && message.substr(0, 4) == "/me ") - { - message = message.substr(4); - config.setValue("afkFormat", 1); - } - else - { - config.setValue("afkFormat", 0); - } - serverConfig.setValue("afkMessage", message); - } -} - -void LocalPlayer::setPseudoAway(const std::string &message) -{ - setAfkMessage(message); - settings.pseudoAwayMode = !settings.pseudoAwayMode; -} - -void LocalPlayer::afkRespond(ChatTab *const tab, const std::string &nick) -{ - if (settings.awayMode) - { - const time_t time = cur_time; - if (mAfkTime == 0 || time < mAfkTime - || time - mAfkTime > awayLimitTimer) - { - std::string str(serverConfig.getValue("afkMessage", - "I am away from keyboard.")); - if (str.find("'NAME'") != std::string::npos) - replaceAll(str, "'NAME'", nick); - - std::string msg("*AFK*: " + str); - - if (config.getIntValue("afkFormat") == 1) - msg = "*" + msg + "*"; - - if (tab == nullptr) - { - chatHandler->privateMessage(nick, msg); - if (localChatTab != nullptr) - { - localChatTab->chatLog(std::string(mName).append( - " : ").append(msg), - ChatMsgType::ACT_WHISPER, - IgnoreRecord_false); - } - } - else - { - if (tab->getNoAway()) - return; - chatHandler->privateMessage(nick, msg); - tab->chatLog(mName, msg); - } - mAfkTime = time; - } - } -} - -bool LocalPlayer::navigateTo(const int x, const int y) -{ - if (mMap == nullptr) - return false; - - SpecialLayer *const tmpLayer = mMap->getTempLayer(); - if (tmpLayer == nullptr) - return false; - - mShowNavigePath = true; - mOldX = mPixelX; - mOldY = mPixelY; - mOldTileX = mX; - mOldTileY = mY; - mNavigateX = x; - mNavigateY = y; - mNavigateId = BeingId_zero; - - mNavigatePath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - x, - y, - getBlockWalkMask(), - 0); - - if (mDrawPath) - tmpLayer->addRoad(mNavigatePath); - return !mNavigatePath.empty(); -} - -void LocalPlayer::navigateClean() -{ - if (mMap == nullptr) - return; - - mShowNavigePath = false; - mOldX = 0; - mOldY = 0; - mOldTileX = 0; - mOldTileY = 0; - mNavigateX = 0; - mNavigateY = 0; - mNavigateId = BeingId_zero; - - mNavigatePath.clear(); - - SpecialLayer *const tmpLayer = mMap->getTempLayer(); - if (tmpLayer == nullptr) - return; - - tmpLayer->clean(); -} - -void LocalPlayer::updateMusic() const -{ - if (mMap != nullptr) - { - std::string str = mMap->getObjectData(mX, mY, MapItemType::MUSIC); - if (str.empty()) - str = mMap->getMusicFile(); - if (str != soundManager.getCurrentMusicFile()) - { - if (str.empty()) - soundManager.fadeOutMusic(); - else - soundManager.fadeOutAndPlayMusic(str); - } - } -} - -void LocalPlayer::updateCoords() -{ - Being::updateCoords(); - - // probably map not loaded. - if ((mPixelX == 0) || (mPixelY == 0)) - return; - - if (mX != mOldTileX || mY != mOldTileY) - { - if (socialWindow != nullptr) - socialWindow->updatePortals(); - PopupManager::hideBeingPopup(); - updateMusic(); - } - - if ((mMap != nullptr) && (mX != mOldTileX || mY != mOldTileY)) - { - SpecialLayer *const tmpLayer = mMap->getTempLayer(); - if (tmpLayer == nullptr) - return; - - const int x = (mPixelX - mapTileSize / 2) / mapTileSize; - const int y = (mPixelY - mapTileSize) / mapTileSize; - if (mNavigateId != BeingId_zero) - { - if (actorManager == nullptr) - { - navigateClean(); - return; - } - - const Being *const being = actorManager - ->findBeing(mNavigateId); - if (being == nullptr) - { - navigateClean(); - return; - } - mNavigateX = being->mX; - mNavigateY = being->mY; - } - - if (mNavigateX == x && mNavigateY == y) - { - navigateClean(); - return; - } - for (Path::const_iterator i = mNavigatePath.begin(), - i_fend = mNavigatePath.end(); - i != i_fend; - ++i) - { - if ((*i).x == mX && (*i).y == mY) - { - mNavigatePath.pop_front(); - fixPos(); - break; - } - } - if (mDrawPath && mShowNavigePath) - { - tmpLayer->clean(); - tmpLayer->addRoad(mNavigatePath); - } - } - mOldX = mPixelX; - mOldY = mPixelY; - mOldTileX = mX; - mOldTileY = mY; -} - -void LocalPlayer::targetMoved() const -{ -/* - if (mKeepAttacking) - { - if (mTarget && mServerAttack == Keep_true) - { - logger->log("LocalPlayer::targetMoved0"); - if (!PacketLimiter::limitPackets(PacketType::PACKET_ATTACK)) - return; - logger->log("LocalPlayer::targetMoved"); - playerHandler->attack(mTarget->getId(), mServerAttack); - } - } -*/ -} - -int LocalPlayer::getPathLength(const Being *const being) const -{ - if ((mMap == nullptr) || (being == nullptr)) - return 0; - - if (being->mX == mX && being->mY == mY) - return 0; - - if (being->mX - 1 <= mX && - being->mX + 1 >= mX && - being->mY - 1 <= mY && - being->mY + 1 >= mY) - { - return 1; - } - - if (mTargetOnlyReachable) - { - const Path debugPath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - being->mX, - being->mY, - getBlockWalkMask(), - 0); - return CAST_S32(debugPath.size()); - } - - const int dx = CAST_S32(abs(being->mX - mX)); - const int dy = CAST_S32(abs(being->mY - mY)); - if (dx > dy) - return dx; - return dy; -} - -int LocalPlayer::getAttackRange2() const -{ - int range = getAttackRange(); - if (range == 1) - range = 2; - return range; -} - -void LocalPlayer::attack2(Being *const target, const bool keep, - const bool dontChangeEquipment) -{ - if (!dontChangeEquipment && (target != nullptr)) - changeEquipmentBeforeAttack(target); - - const bool broken = (Net::getNetworkType() == ServerType::TMWATHENA); - - // probably need cache getPathLength(target) - if ((target == nullptr || - settings.attackType == 0 || - settings.attackType == 3) || - (withinAttackRange(target, broken, broken ? 1 : 0) && - getPathLength(target) <= getAttackRange2())) - { - attack(target, keep); - if (settings.attackType == 2) - { - if (target == nullptr) - { - if (pickUpItems()) - return; - } - else - { - pickUpItems(3); - } - } - } - else if (mPickUpTarget == nullptr) - { - if (settings.attackType == 2) - { - if (pickUpItems()) - return; - } - setTarget(target); - if (target->getType() != ActorType::Npc) - { - mKeepAttacking = true; - moveToTarget(); - } - } -} - -void LocalPlayer::setFollow(const std::string &player) -{ - mPlayerFollowed = player; - if (!mPlayerFollowed.empty()) - { - // TRANSLATORS: follow command message - std::string msg = strprintf(_("Follow: %s"), player.c_str()); - debugMsg(msg); - } - else - { - // TRANSLATORS: follow command message - debugMsg(_("Follow canceled")); - } -} - -void LocalPlayer::setImitate(const std::string &player) -{ - mPlayerImitated = player; - if (!mPlayerImitated.empty()) - { - // TRANSLATORS: imitate command message - std::string msg = strprintf(_("Imitation: %s"), player.c_str()); - debugMsg(msg); - } - else - { - // TRANSLATORS: imitate command message - debugMsg(_("Imitation canceled")); - } -} - -void LocalPlayer::cancelFollow() -{ - if (!mPlayerFollowed.empty()) - { - // TRANSLATORS: cancel follow message - debugMsg(_("Follow canceled")); - } - if (!mPlayerImitated.empty()) - { - // TRANSLATORS: cancel follow message - debugMsg(_("Imitation canceled")); - } - mPlayerFollowed.clear(); - mPlayerImitated.clear(); -} - -void LocalPlayer::imitateEmote(const Being *const being, - const unsigned char action) const -{ - if (being == nullptr) - return; - - std::string player_imitated = getImitate(); - if (!player_imitated.empty() && being->mName == player_imitated) - emote(action); -} - -void LocalPlayer::imitateAction(const Being *const being, - const BeingActionT &action) -{ - if (being == nullptr) - return; - - if (!mPlayerImitated.empty() && being->mName == mPlayerImitated) - { - setAction(action, 0); - playerHandler->changeAction(action); - } -} - -void LocalPlayer::imitateDirection(const Being *const being, - const unsigned char dir) -{ - if (being == nullptr) - return; - - if (!mPlayerImitated.empty() && being->mName == mPlayerImitated) - { - if (!PacketLimiter::limitPackets(PacketType::PACKET_DIRECTION)) - return; - - if (settings.followMode == 2) - { - uint8_t dir2 = 0; - if ((dir & BeingDirection::LEFT) != 0) - dir2 |= BeingDirection::RIGHT; - else if ((dir & BeingDirection::RIGHT) != 0) - dir2 |= BeingDirection::LEFT; - if ((dir & BeingDirection::UP) != 0) - dir2 |= BeingDirection::DOWN; - else if ((dir & BeingDirection::DOWN) != 0) - dir2 |= BeingDirection::UP; - - setDirection(dir2); - playerHandler->setDirection(dir2); - } - else - { - setDirection(dir); - playerHandler->setDirection(dir); - } - } -} - -void LocalPlayer::imitateOutfit(const Being *const player, - const int sprite) const -{ - if (player == nullptr) - return; - - if (settings.imitationMode == 1 && - !mPlayerImitated.empty() && - player->mName == mPlayerImitated) - { - if (sprite < 0 || sprite >= player->getNumberOfLayers()) - return; - - const AnimatedSprite *const equipmentSprite - = dynamic_cast<const AnimatedSprite *>( - player->mSprites[sprite]); - - if (equipmentSprite != nullptr) - { -// logger->log("have equipmentSprite"); - const Inventory *const inv = PlayerInfo::getInventory(); - if (inv == nullptr) - return; - - const std::string &path = equipmentSprite->getIdPath(); - if (path.empty()) - return; - -// logger->log("idPath: " + path); - const Item *const item = inv->findItemBySprite(path, - player->getGender(), player->getSubType()); - if ((item != nullptr) && item->isEquipped() == Equipped_false) - PlayerInfo::equipItem(item, Sfx_false); - } - else - { -// logger->log("have unequip %d", sprite); - const int equipmentSlot = inventoryHandler - ->convertFromServerSlot(sprite); -// logger->log("equipmentSlot: " + toString(equipmentSlot)); - if (equipmentSlot == inventoryHandler->getProjectileSlot()) - return; - - const Item *const item = PlayerInfo::getEquipment(equipmentSlot); - if (item != nullptr) - { -// logger->log("unequiping"); - PlayerInfo::unequipItem(item, Sfx_false); - } - } - } -} - -void LocalPlayer::followMoveTo(const Being *const being, - const int x, const int y) -{ - if ((being != nullptr) && - !mPlayerFollowed.empty() && - being->mName == mPlayerFollowed) - { - mPickUpTarget = nullptr; - navigateTo(x, y); - } -} - -void LocalPlayer::followMoveTo(const Being *const being, - const int x1, const int y1, - const int x2, const int y2) -{ - if (being == nullptr) - return; - - mPickUpTarget = nullptr; - if (!mPlayerFollowed.empty() && - being->mName == mPlayerFollowed) - { - switch (settings.followMode) - { - case 0: - navigateTo(x1, y1); - setNextDest(x2, y2); - break; - case 1: - if (x1 != x2 || y1 != y2) - { - navigateTo(mX + x2 - x1, mY + y2 - y1); - setNextDest(mX + x2 - x1, mY + y2 - y1); - } - break; - case 2: - if (x1 != x2 || y1 != y2) - { - navigateTo(mX + x1 - x2, mY + y1 - y2); - setNextDest(mX + x1 - x2, mY + y1 - y2); - } - break; - case 3: - if (mTarget == nullptr || - mTarget->mName != mPlayerFollowed) - { - if (actorManager != nullptr) - { - Being *const b = actorManager->findBeingByName( - mPlayerFollowed, ActorType::Player); - setTarget(b); - } - } - moveToTarget(); - setNextDest(x2, y2); - break; - default: - break; - } - } -} - -void LocalPlayer::setNextDest(const int x, const int y) -{ - mNextDestX = x; - mNextDestY = y; -} - -bool LocalPlayer::allowAction() -{ - if (mIsServerBuggy) - { - if (mLastAction != -1) - return false; - mLastAction = tick_time; - } - return true; -} - -void LocalPlayer::fixPos() -{ - if ((mCrossX == 0) && (mCrossY == 0)) - return; - - const int dx = abs(mX - mCrossX); - const int dy = abs(mY - mCrossY); - const int dist = dx > dy ? dx : dy; - const time_t time = cur_time; - const int maxDist = mSyncPlayerMove ? mSyncPlayerMoveDistance : 7; - - if (dist > maxDist) - { - mActivityTime = time; - setTileCoords(mCrossX, mCrossY); -// alternative way to fix, move to real position -// setDestination(mCrossX, mCrossY); - } -} - -void LocalPlayer::setRealPos(const int x, const int y) -{ - if (mMap == nullptr) - return; - - SpecialLayer *const layer = mMap->getTempLayer(); - if (layer != nullptr) - { - bool cacheUpdated(false); - if (((mCrossX != 0) || (mCrossY != 0)) && - (layer->getTile(mCrossX, mCrossY) != nullptr) && - layer->getTile(mCrossX, mCrossY)->getType() == MapItemType::CROSS) - { - layer->setTile(mCrossX, mCrossY, MapItemType::EMPTY); - layer->updateCache(); - cacheUpdated = true; - } - - if (mShowServerPos) - { - const MapItem *const mapItem = layer->getTile(x, y); - - if (mapItem == nullptr || - mapItem->getType() == MapItemType::EMPTY) - { - if (mX != x && mY != y) - { - layer->setTile(x, y, MapItemType::CROSS); - if (cacheUpdated == false) - layer->updateCache(); - } - } - } - - if (mCrossX != x || mCrossY != y) - { - mCrossX = x; - mCrossY = y; - } - } - if (mMap->isCustom()) - mMap->setWalk(x, y); -} -void LocalPlayer::fixAttackTarget() -{ - if ((mMap == nullptr) || (mTarget == nullptr)) - return; - - if (settings.moveToTargetType == 11 || (settings.attackType == 0u) - || !config.getBoolValue("autofixPos")) - { - return; - } - - const Path debugPath = mMap->findPath( - (mPixelX - mapTileSize / 2) / mapTileSize, - (mPixelY - mapTileSize) / mapTileSize, - mTarget->mX, - mTarget->mY, - getBlockWalkMask(), - 0); - - if (!debugPath.empty()) - { - const Path::const_iterator i = debugPath.begin(); - setDestination((*i).x, (*i).y); - } -} - -void LocalPlayer::respawn() -{ - navigateClean(); -} - -int LocalPlayer::getLevel() const -{ - return PlayerInfo::getAttribute(Attributes::PLAYER_BASE_LEVEL); -} - -void LocalPlayer::updateNavigateList() -{ - if (mMap != nullptr) - { - const std::map<std::string, Vector>::const_iterator iter = - mHomes.find(mMap->getProperty("_realfilename")); - - if (iter != mHomes.end()) - { - const Vector &pos = mHomes[(*iter).first]; - if ((pos.x != 0.0f) && (pos.y != 0.0f)) - { - mMap->addPortalTile("home", MapItemType::HOME, - CAST_S32(pos.x), CAST_S32(pos.y)); - } - } - } -} - -void LocalPlayer::failMove(const int x A_UNUSED, - const int y A_UNUSED) -{ -} - -void LocalPlayer::waitFor(const std::string &nick) -{ - mWaitFor = nick; -} - -void LocalPlayer::checkNewName(Being *const being) -{ - if (being == nullptr) - return; - - const std::string &nick = being->mName; - if (being->getType() == ActorType::Player) - { - const Guild *const guild = getGuild(); - if (guild != nullptr) - { - const GuildMember *const gm = guild->getMember(nick); - if (gm != nullptr) - { - const int level = gm->getLevel(); - if (level > 1 && being->getLevel() != level) - { - being->setLevel(level); - being->updateName(); - } - } - } - if (chatWindow != nullptr) - { - WhisperTab *const tab = chatWindow->getWhisperTab(nick); - if (tab != nullptr) - tab->setWhisperTabColors(); - } - } - - if (!mWaitFor.empty() && mWaitFor == nick) - { - // TRANSLATORS: wait player/monster message - debugMsg(strprintf(_("You see %s"), mWaitFor.c_str())); - soundManager.playGuiSound(SOUND_INFO); - mWaitFor.clear(); - } -} - -unsigned char LocalPlayer::getBlockWalkMask() const -{ - // for now blocking all types of collisions - return BlockMask::WALL | - BlockMask::AIR | - BlockMask::WATER | - BlockMask::PLAYERWALL; -} - -void LocalPlayer::removeHome() -{ - if (mMap == nullptr) - return; - - const std::string key = mMap->getProperty("_realfilename"); - const std::map<std::string, Vector>::iterator iter = mHomes.find(key); - - if (iter != mHomes.end()) - mHomes.erase(key); -} - -void LocalPlayer::stopAdvert() -{ - mBlockAdvert = true; -} - -bool LocalPlayer::checAttackPermissions(const Being *const target) -{ - if (target == nullptr) - return false; - - switch (settings.pvpAttackType) - { - case 0: - return true; - case 1: - return !(playerRelations.getRelation(target->mName) - == Relation::FRIEND); - case 2: - return playerRelations.checkBadRelation(target->mName); - default: - case 3: - return false; - } -} - -void LocalPlayer::updateStatus() const -{ - if (serverFeatures->havePlayerStatusUpdate() && mEnableAdvert) - { - uint8_t status = 0; - if (Net::getNetworkType() == ServerType::TMWATHENA) - { - if (mTradebot && - shopWindow != nullptr && - !shopWindow->isShopEmpty()) - { - status |= BeingFlag::SHOP; - } - } - if (settings.awayMode || settings.pseudoAwayMode) - status |= BeingFlag::AWAY; - - if (mInactive) - status |= BeingFlag::INACTIVE; - - playerHandler->updateStatus(status); - } -} - -void LocalPlayer::setTestParticle(const std::string &fileName, - const bool updateHash) -{ - mTestParticleName = fileName; - mTestParticleTime = cur_time; - if (mTestParticle != nullptr) - { - mChildParticleEffects.removeLocally(mTestParticle); - mTestParticle = nullptr; - } - if (!fileName.empty()) - { - mTestParticle = particleEngine->addEffect(fileName, 0, 0, 0); - controlCustomParticle(mTestParticle); - if (updateHash) - mTestParticleHash = UpdaterWindow::getFileHash(mTestParticleName); - } -} - -void LocalPlayer::playerDeath() -{ - if (mAction != BeingAction::DEAD) - { - setAction(BeingAction::DEAD, 0); - recalcSpritesOrder(); - } -} - -bool LocalPlayer::canMove() const -{ - return !mFreezed && - mAction != BeingAction::DEAD && - (serverFeatures->haveMoveWhileSit() || - mAction != BeingAction::SIT); -} - -void LocalPlayer::freezeMoving(const int timeWaitTicks) -{ - if (timeWaitTicks <= 0) - return; - const int nextTime = tick_time + timeWaitTicks; - if (mUnfreezeTime < nextTime) - mUnfreezeTime = nextTime; - if (mUnfreezeTime > 0) - mFreezed = true; -} diff --git a/src/being/localplayer.h b/src/being/localplayer.h deleted file mode 100644 index 897e4dc00..000000000 --- a/src/being/localplayer.h +++ /dev/null @@ -1,533 +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/>. - */ - -#ifndef BEING_LOCALPLAYER_H -#define BEING_LOCALPLAYER_H - -#include "being/being.h" - -#include "enums/being/pickup.h" -#include "enums/being/visiblename.h" - -#include "enums/simpletypes/allowsort.h" -#include "enums/simpletypes/keep.h" - -#include "listeners/actorspritelistener.h" -#include "listeners/attributelistener.h" -#include "listeners/playerdeathlistener.h" - -#include "localconsts.h" - -class AwayListener; -class ChatTab; -class FloorItem; -class Map; -class OkDialog; - -/** - * The local player character. - */ -class LocalPlayer final : public Being, - public ActorSpriteListener, - public AttributeListener, - public PlayerDeathListener -{ - public: - /** - * Constructor. - */ - explicit LocalPlayer(const BeingId id, - const BeingTypeId subType = BeingTypeId_zero); - - A_DELETE_COPY(LocalPlayer) - - /** - * Destructor. - */ - ~LocalPlayer(); - - void logic() override final; - - void slowLogic(); - - void setAction(const BeingActionT &action, - const int attackId) override final; - - /** - * Compute the next pathnode location when walking using keyboard. - * used by nextTile(). - */ - Position getNextWalkPosition(const unsigned char dir) - const A_WARN_UNUSED; - - /** - * Adds a new tile to the path when walking. - * @note Eathena - * Also, when specified, it picks up an item at the end of a path - * or attack target. - */ - void nextTile() override final - { nextTile(0); } - - void nextTile(unsigned char dir); - - bool pickUp(FloorItem *const item); - - /** - * Called when an ActorSprite has been destroyed. - * @param actorSprite the ActorSprite being destroyed. - */ - void actorSpriteDestroyed(const ActorSprite &actorSprite) - override final; - - /** - * Gets the attack range. - */ - int getAttackRange() const A_WARN_UNUSED; - - int getAttackRange2() const A_WARN_UNUSED; - - void attack(Being *const target = nullptr, const bool keep = false, - const bool dontChangeEquipment = false); - - void attack2(Being *const target = nullptr, const bool keep = false, - const bool dontChangeEquipment = false); - - void setGroupId(const int id) override final; - - void stopAttack(const bool keepAttack = false); - - void untarget(); - - /** - * Returns the current target of the player. Returns 0 if no being is - * currently targeted. - */ - Being *getTarget() const A_WARN_UNUSED; - - /** - * Sets the target being of the player. - */ - void setTarget(Being *const target); - - Being *setNewTarget(const ActorTypeT type, - const AllowSort allowSort); - - /** - * Sets a new destination for this being to walk to. - */ - void setDestination(const int x, const int y); - - /** - * Sets a new direction to keep walking in. - */ - void setWalkingDir(const unsigned char dir); - - /** - * Gets the walking direction - */ - unsigned char getWalkingDir() const noexcept2 A_WARN_UNUSED - { return mWalkingDir; } - - /** - * Sets going to being to attack - */ - void setGotoTarget(Being *const target); - - /** - * Returns whether the target is in range to attack - */ - bool withinAttackRange(const Being *const target, - const bool fixDistance = false, - const int addRange = 0) const A_WARN_UNUSED; - - /** - * Stops the player dead in his tracks - */ - void stopWalking(const bool sendToServer = true); - - bool toggleSit() const; - - bool updateSit() const; - - static bool emote(const uint8_t emotion); - - /** - * Shows item pickup notifications. - */ - void pickedUp(const ItemInfo &itemInfo, - const int amount, - const ItemColor color, - const BeingId floorItemId, - const PickupT fail); - - int getLevel() const override final A_WARN_UNUSED; - - /** Tells that the path has been set by mouse. */ - void pathSetByMouse() - { mPathSetByMouse = true; } - - /** Tells if the path has been set by mouse. */ - bool isPathSetByMouse() const noexcept2 A_WARN_UNUSED - { return mPathSetByMouse; } - - unsigned int getMoveState() const noexcept2 A_WARN_UNUSED - { return mMoveState; } - - void setMoveState(const unsigned int n) noexcept2 - { mMoveState = n; } - - std::string getPingTime() const A_WARN_UNUSED; - - void tryPingRequest(); - -#ifdef TMWA_SUPPORT - void magicAttack() const; -#endif // TMWA_SUPPORT - - void specialMove(const unsigned char direction); - - void moveByDirection(const unsigned char dir); - - bool pickUpItems(int pickUpType = 0); - - void move(const int dX, const int dY); - - void moveToTarget(int dist = -1); - - void moveToHome(); - - bool isReachable(Being *const being, - const int maxCost = 0) A_WARN_UNUSED; - - bool isReachable(const int x, const int y, - const bool allowCollision) const A_WARN_UNUSED; - - void setHome(); - - void pingRequest(); - - void pingResponse(); - - void setAway(const std::string &message) const; - - static void setPseudoAway(const std::string &message); - - void setHalfAway(const bool n) - { mInactive = n; } - - bool getHalfAway() const noexcept2 A_WARN_UNUSED - { return mInactive; } - - void afkRespond(ChatTab *const tab, const std::string &nick); - - static void setAfkMessage(std::string message); - - bool navigateTo(const int x, const int y); - - void navigateClean(); - - void imitateEmote(const Being *const being, - const unsigned char action) const; - - void imitateAction(const Being *const being, - const BeingActionT &action); - - void imitateDirection(const Being *const being, - const unsigned char dir); - - void imitateOutfit(const Being *const player, - const int sprite = -1) const; - - void followMoveTo(const Being *const being, const int x, const int y); - - void followMoveTo(const Being *const being, const int x1, const int y1, - const int x2, const int y2); - - bool allowAction() A_WARN_UNUSED; - - void setRealPos(const int x, const int y); - - bool isServerBuggy() const noexcept2 A_WARN_UNUSED - { return mIsServerBuggy; } - - void fixPos(); - - /** - * Sets the map the being is on - */ - void setMap(Map *const map) override final; - - void addMessageToQueue(const std::string &message, - const UserColorIdT color - = UserColorId::EXP_INFO); - - /** - * Called when a option (set with config.addListener()) is changed - */ - void optionChanged(const std::string &value) override final; - - void playerDeath() override final; - - /** - * set a following player. - */ - void setFollow(const std::string &player); - - /** - * set an imitation player. - */ - void setImitate(const std::string &player); - - /** - * setting the next destination of the following, in case of warp - */ - void setNextDest(const int x, const int y); - - int getNextDestX() const noexcept2 A_WARN_UNUSED - { return mNextDestX; } - - int getNextDestY() const noexcept2 A_WARN_UNUSED - { return mNextDestY; } - - void respawn(); - - const FloorItem *getPickUpTarget() const noexcept2 A_WARN_UNUSED - { return mPickUpTarget; } - - void unSetPickUpTarget() - { mPickUpTarget = nullptr; } - - /** - * Stop following a player. - */ - void cancelFollow(); - - /** - * Get the playername followed by the current player. - */ - const std::string &getFollow() const noexcept2 A_WARN_UNUSED - { return mPlayerFollowed; } - - /** - * Get the playername imitated by the current player. - */ - const std::string &getImitate() const noexcept2 A_WARN_UNUSED - { return mPlayerImitated; } - - /** - * Tells the engine whether to check - * if the Player Name is to be displayed. - */ - void setCheckNameSetting(const bool checked) - { mUpdateName = checked; } - - /** - * Gets if the engine has to check - * if the Player Name is to be displayed. - */ - bool getCheckNameSetting() const noexcept2 A_WARN_UNUSED - { return mUpdateName; } - - void fixAttackTarget(); - - void updateNavigateList(); - - int getPathLength(const Being *const being) const A_WARN_UNUSED; - - void targetMoved() const A_CONST; - - void setLastHitFrom(const std::string &n) - { mLastHitFrom = n; } - - void waitFor(const std::string &nick); - - void checkNewName(Being *const being); - - unsigned char getBlockWalkMask() const override final - A_CONST A_WARN_UNUSED; - - void saveHomes(); - - void removeHome(); - - void stopAdvert(); - - void addXpMessage(const int change); - - void addHomunXpMessage(const int change); - - void addJobMessage(const int change); - - void addHpMessage(const int change); - - void addSpMessage(const int change); - - static bool checAttackPermissions(const Being *const target) - A_WARN_UNUSED; - - void updateStatus() const; - - void setTestParticle(const std::string &fileName, - const bool updateHash = true); - - int getLastAttackX() const override final - { return mTarget != nullptr ? mTarget->mX : mLastAttackX; } - - int getLastAttackY() const override final - { return mTarget != nullptr ? mTarget->mY : mLastAttackY; } - - void attributeChanged(const AttributesT id, - const int64_t oldVal, - const int64_t newVal) override final; - - void updateMusic() const; - - void setAfkTime(const int v) noexcept2 - { mAfkTime = v; } - - void setAwayDialog(OkDialog *const dialog) - { mAwayDialog = dialog; } - - AwayListener *getAwayListener() const noexcept2 A_WARN_UNUSED - { return mAwayListener; } - - void setRename(const bool r) noexcept2 - { mAllowRename = r; } - - bool getRename() const noexcept2 - { return mAllowRename; } - - bool canMove() const; - - void freezeMoving(const int timeWaitTicks); - - void failMove(const int x, - const int y); - - protected: - void updateCoords() override final; - - void handleStatusEffect(const StatusEffect *const effect, - const int32_t effectId, - const Enable newStatus, - const IsStart start) override final; - - void startWalking(const unsigned char dir); - - void changeEquipmentBeforeAttack(const Being *const target) const; - -#ifdef TMWA_SUPPORT - static void tryMagic(const std::string &spell, - const int baseMagic, - const int schoolMagic, - const int mana); -#endif // TMWA_SUPPORT - - void loadHomes(); - - // move state. used if mMoveType == 2 - unsigned int mMoveState; - - int mLastTargetX; - int mLastTargetY; - - std::map<std::string, Vector> mHomes; - - Being *mTarget; - - /** Follow system **/ - std::string mPlayerFollowed; - std::string mPlayerImitated; - int mNextDestX; - int mNextDestY; - - FloorItem *mPickUpTarget; - - int mLastAction; // Time stamp of the last action, -1 if none. - - STD_VECTOR<int32_t> mStatusEffectIcons; - - typedef std::pair<std::string, UserColorIdT> MessagePair; - /** Queued messages*/ - std::list<MessagePair> mMessages; - int mMessageTime; - AwayListener *mAwayListener; - OkDialog *mAwayDialog; - - int mPingSendTick; - time_t mPingTime; - time_t mAfkTime; - time_t mActivityTime; - int mNavigateX; - int mNavigateY; - BeingId mNavigateId; - int mCrossX; - int mCrossY; - int mOldX; - int mOldY; - int mOldTileX; - int mOldTileY; - Path mNavigatePath; - - std::string mLastHitFrom; - std::string mWaitFor; - time_t mAdvertTime; - Particle *mTestParticle; - std::string mTestParticleName; - time_t mTestParticleTime; - unsigned long mTestParticleHash; - int mSyncPlayerMoveDistance; - int mUnfreezeTime; - unsigned char mWalkingDir; // The direction the player is walking in. - /** Whether or not the name settings have changed */ - bool mUpdateName; - bool mBlockAdvert; - bool mTargetDeadPlayers; - Keep mServerAttack; - VisibleName::Type mVisibleNames; - bool mEnableAdvert; - bool mTradebot; - bool mTargetOnlyReachable; - bool mIsServerBuggy; - bool mSyncPlayerMove; - bool mDrawPath; - bool mAttackMoving; - bool mAttackNext; - bool mShowJobExp; - bool mShowServerPos; - bool mNextStep; - // temporary disable crazy moves in moves - bool mGoingToTarget; - // Whether or not to continue to attack - bool mKeepAttacking; - // Tells if the path was set using mouse - bool mPathSetByMouse; - bool mWaitPing; - bool mShowNavigePath; - bool mAllowRename; - bool mFreezed; -}; - -extern LocalPlayer *localPlayer; - -#endif // BEING_LOCALPLAYER_H diff --git a/src/being/mercenaryinfo.h b/src/being/mercenaryinfo.h deleted file mode 100644 index c25eeef49..000000000 --- a/src/being/mercenaryinfo.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_MERCENARYINFO_H -#define BEING_MERCENARYINFO_H - -#include "enums/simpletypes/beingid.h" -#include <string> - -#include "localconsts.h" - -struct MercenaryInfo final -{ - MercenaryInfo() : - name(), - id(BeingId_zero), - level(0), - range(0) - { } - - A_DELETE_COPY(MercenaryInfo) - - std::string name; - BeingId id; - int level; - int range; -}; - -#endif // BEING_MERCENARYINFO_H diff --git a/src/being/petinfo.h b/src/being/petinfo.h deleted file mode 100644 index 5ede2cfb2..000000000 --- a/src/being/petinfo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The ManaPlus Client - * 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/>. - */ - -#ifndef BEING_PETINFO_H -#define BEING_PETINFO_H - -#include "enums/simpletypes/beingid.h" - -#include <string> - -#include "localconsts.h" - -struct PetInfo final -{ - PetInfo() : - name(), - id(BeingId_zero), - level(0), - hungry(0), - intimacy(0), - race(0), - performance(0), - hairStyle(0), - equip(0) - { } - - A_DELETE_COPY(PetInfo) - - std::string name; - BeingId id; - int level; - int hungry; - int intimacy; - int race; - int performance; - int hairStyle; - int equip; -}; - -#endif // BEING_PETINFO_H diff --git a/src/being/playerignorestrategy.h b/src/being/playerignorestrategy.h deleted file mode 100644 index fb5dd5ebb..000000000 --- a/src/being/playerignorestrategy.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2008-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/>. - */ - -#ifndef BEING_PLAYERIGNORESTRATEGY_H -#define BEING_PLAYERIGNORESTRATEGY_H - -#include <string> - -#include "localconsts.h" - -class Being; - -/** - * Ignore strategy: describes how we should handle ignores. - */ -class PlayerIgnoreStrategy notfinal -{ - public: - std::string mDescription; - std::string mShortName; - - A_DELETE_COPY(PlayerIgnoreStrategy) - - virtual ~PlayerIgnoreStrategy() - { } - - /** - * Handle the ignoring of the indicated action by the indicated player. - */ - virtual void ignore(Being *const being, - const unsigned int flags) const = 0; - protected: - PlayerIgnoreStrategy() : - mDescription(), - mShortName() - { - } -}; -#endif // BEING_PLAYERIGNORESTRATEGY_H diff --git a/src/being/playerinfo.cpp b/src/being/playerinfo.cpp deleted file mode 100644 index 0a89bd7e1..000000000 --- a/src/being/playerinfo.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/playerinfo.h" - -#include "configuration.h" -#include "itemsoundmanager.h" - -#include "being/localplayer.h" - -#include "being/homunculusinfo.h" -#include "being/mercenaryinfo.h" -#include "being/petinfo.h" - -#include "gui/windows/inventorywindow.h" -#include "gui/windows/npcdialog.h" - -#include "listeners/statlistener.h" - -#include "net/homunculushandler.h" -#include "net/inventoryhandler.h" -#include "net/mercenaryhandler.h" -#include "net/playerhandler.h" - -#include "resources/item/item.h" - -#include "utils/delete2.h" - -#include "utils/translation/translationmanager.h" - -#include "debug.h" - -namespace PlayerInfo -{ - -PlayerInfoBackend mData; -int mCharId = 0; - -Inventory *mInventory = nullptr; -Inventory *mCartInventory = nullptr; -MercenaryInfo *mMercenary = nullptr; -HomunculusInfo *mHomunculus = nullptr; -PetInfo *mPet = nullptr; -std::string mRoomName; -Equipment *mEquipment = nullptr; -BeingId mPetBeingId = BeingId_zero; -GuildPositionFlags::Type mGuildPositionFlags = GuildPositionFlags::None; -BeingId mElementalId = BeingId_zero; - -Trading mTrading = Trading_false; -bool mVending = false; -int mLevelProgress = 0; -int mServerLanguage = -1; -std::set<int> mProtectedItems; - -// --- Triggers --------------------------------------------------------------- - -void triggerAttr(const AttributesT id, - const int64_t old) -{ - AttributeListener::distributeEvent(id, old, - mData.mAttributes.find(id)->second); -} - -void triggerStat(const AttributesT id, - const int old1, - const int old2) -{ - StatListener::distributeEvent(id, old1, old2); -} - -// --- Attributes ------------------------------------------------------------- - -int64_t getAttribute64(const AttributesT id) -{ - const AtrIntMap::const_iterator it = mData.mAttributes.find(id); - if (it != mData.mAttributes.end()) - return it->second; - return 0; -} - -int32_t getAttribute(const AttributesT id) -{ - const AtrIntMap::const_iterator it = mData.mAttributes.find(id); - if (it != mData.mAttributes.end()) - return CAST_S32(it->second); - return 0; -} - -void setAttribute(const AttributesT id, - const int64_t value, - const Notify notify) -{ - const int64_t old = mData.mAttributes[id]; - mData.mAttributes[id] = value; - if (notify == Notify_true) - triggerAttr(id, old); -} - -int getSkillLevel(const int id) -{ - const IntMap::const_iterator it = mData.mSkills.find(id); - if (it != mData.mSkills.end()) - return it->second; - return 0; -} - -void setSkillLevel(const int id, const int value) -{ - mData.mSkills[id] = value; -} - -// --- Stats ------------------------------------------------------------------ - -int getStatBase(const AttributesT id) -{ - const StatMap::const_iterator it = mData.mStats.find(id); - if (it != mData.mStats.end()) - return it->second.base; - return 0; -} - -void setStatBase(const AttributesT id, const int value, const Notify notify) -{ - const int old = mData.mStats[id].base; - mData.mStats[id].base = value; - if (notify == Notify_true) - triggerStat(id, old, 0); -} - -int getStatMod(const AttributesT id) -{ - const StatMap::const_iterator it = mData.mStats.find(id); - if (it != mData.mStats.end()) - return it->second.mod; - return 0; -} - -void setStatMod(const AttributesT id, const int value, const Notify notify) -{ - const int old = mData.mStats[id].mod; - mData.mStats[id].mod = value; - if (notify == Notify_true) - triggerStat(id, old, 0); -} - -int getStatEffective(const AttributesT id) -{ - const StatMap::const_iterator it = mData.mStats.find(id); - if (it != mData.mStats.end()) - return it->second.base + it->second.mod; - return 0; -} - -const std::pair<int, int> getStatExperience(const AttributesT id) -{ - const StatMap::const_iterator it = mData.mStats.find(id); - int a, b; - if (it != mData.mStats.end()) - { - a = it->second.exp; - b = it->second.expNeed; - } - else - { - a = 0; - b = 0; - } - return std::pair<int, int>(a, b); -} - -void setStatExperience(const AttributesT id, - const int have, - const int need, - const Notify notify) -{ - Stat &stat = mData.mStats[id]; - - const int oldExp = stat.exp; - const int oldExpNeed = stat.expNeed; - stat.exp = have; - stat.expNeed = need; - if (notify == Notify_true) - triggerStat(id, oldExp, oldExpNeed); -} - -// --- Inventory / Equipment -------------------------------------------------- - -Inventory *getInventory() -{ - return mInventory; -} - -Inventory *getStorageInventory() -{ - if (inventoryHandler != nullptr) - return inventoryHandler->getStorage(); - return nullptr; -} - -Inventory *getCartInventory() -{ - return mCartInventory; -} - -void clearInventory() -{ - if (mEquipment != nullptr) - mEquipment->clear(); - if (mInventory != nullptr) - mInventory->clear(); -} - -Equipment *getEquipment() -{ - return mEquipment; -} - -const Item *getEquipment(const unsigned int slot) -{ - if (mEquipment != nullptr) - return mEquipment->getEquipment(slot); - return nullptr; -} - -void setEquipmentBackend(Equipment::Backend *const backend) -{ - if (mEquipment != nullptr) - mEquipment->setBackend(backend); -} - -void equipItem(const Item *const item, const Sfx sfx) -{ - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->equipItem(item); -} - -void unequipItem(const Item *const item, const Sfx sfx) -{ - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->unequipItem(item); -} - -void useItem(const Item *const item, const Sfx sfx) -{ - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::USE); - if (inventoryHandler != nullptr) - inventoryHandler->useItem(item); -} - -void useEquipItem(const Item *const item, - const int16_t useType, - const Sfx sfx) -{ - if (item != nullptr) - { - if (item->getType() == ItemType::Card) - { - if (mProtectedItems.find(item->getId()) == mProtectedItems.end()) - { - if (inventoryHandler != nullptr) - inventoryHandler->useCard(item); - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::USECARD); - } - } - else if (item->isEquipment() == Equipm_true) - { - if (item->isEquipped() == Equipped_true) - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->unequipItem(item); - } - else - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->equipItem(item); - } - } - else - { - if (mProtectedItems.find(item->getId()) == mProtectedItems.end()) - { - if (inventoryHandler != nullptr) - { - if (useType == 0) - inventoryHandler->useItem(item); - else - inventoryHandler->useItem(item, useType); - } - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::USE); - } - } - } -} - -void useEquipItem2(const Item *const item, - const int16_t useType, - const Sfx sfx) -{ - if (item != nullptr) - { - if (item->isEquipment() == Equipm_false) - { - if (item->isEquipped() == Equipped_true) - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->unequipItem(item); - } - else - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP); - if (inventoryHandler != nullptr) - inventoryHandler->equipItem(item); - } - } - else - { - if (mProtectedItems.find(item->getId()) == mProtectedItems.end()) - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::USE); - if (inventoryHandler != nullptr) - { - if (useType == 0) - inventoryHandler->useItem(item); - else - inventoryHandler->useItem(item, useType); - } - } - } - } -} - -void dropItem(const Item *const item, const int amount, const Sfx sfx) -{ - if (item != nullptr && - mProtectedItems.find(item->getId()) == mProtectedItems.end()) - { - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::DROP); - if (inventoryHandler != nullptr) - inventoryHandler->dropItem(item, amount); - } -} - -void pickUpItem(const FloorItem *const item, const Sfx sfx) -{ - if (sfx == Sfx_true) - ItemSoundManager::playSfx(item, ItemSoundEvent::PICKUP); - if (playerHandler != nullptr) - playerHandler->pickUp(item); -} - -// --- Misc ------------------------------------------------------------------- - -void setBackend(const PlayerInfoBackend &backend) -{ - mData = backend; -} - -void setCharId(const int charId) -{ - mCharId = charId; -} - -int getCharId() -{ - return mCharId; -} - -Trading isTrading() -{ - return mTrading; -} - -void setTrading(const Trading trading) -{ - mTrading = trading; -} - -#define updateAttackStat(atk, delay, speed) \ - attackDelay = getStatBase(delay); \ - if (attackDelay != 0) \ - { \ - setStatBase(speed, \ - getStatBase(atk) * 1000 / attackDelay, \ - Notify_false); \ - setStatMod(speed, \ - getStatMod(atk) * 1000 / attackDelay, \ - Notify_true); \ - } \ - else \ - { \ - setStatBase(speed, 0, \ - Notify_false); \ - setStatMod(speed, 0, \ - Notify_true); \ - } - -void updateAttrs() -{ - int attackDelay; - updateAttackStat(Attributes::PLAYER_ATK, - Attributes::PLAYER_ATTACK_DELAY, - Attributes::PLAYER_ATTACK_SPEED) - updateAttackStat(Attributes::HOMUN_ATK, - Attributes::HOMUN_ATTACK_DELAY, - Attributes::HOMUN_ATTACK_SPEED) - updateAttackStat(Attributes::MERC_ATK, - Attributes::MERC_ATTACK_DELAY, - Attributes::MERC_ATTACK_SPEED) -} - -void init() -{ -} - -void deinit() -{ - clearInventory(); - delete2(mMercenary); - mPetBeingId = BeingId_zero; -} - -void loadData() -{ - mProtectedItems.clear(); - splitToIntSet(mProtectedItems, - serverConfig.getStringValue("protectedItems"), ','); -} - -void clear() -{ - mData.mSkills.clear(); - mPetBeingId = BeingId_zero; -} - -bool isTalking() -{ - return NpcDialog::isActive() || InventoryWindow::isStorageActive(); -} - -void gameDestroyed() -{ - delete2(mInventory); - delete2(mEquipment); - delete2(mCartInventory); -} - -void stateChange(const StateT state) -{ - if (state == State::GAME) - { - if (mInventory == nullptr) - { - mInventory = new Inventory(InventoryType::Inventory); - mEquipment = new Equipment; - mCartInventory = new Inventory(InventoryType::Cart); - } - } -} - -static void saveProtectedItems() -{ - std::string str; - std::set<int>::const_iterator it = mProtectedItems.begin(); - std::set<int>::const_iterator it_end = mProtectedItems.end(); - if (it != it_end) - { - str.append(toString(*it)); - ++ it; - } - while (it != it_end) - { - str.append(",").append(toString(*it)); - ++ it; - } - serverConfig.setValue("protectedItems", str); - serverConfig.write(); -} - -void protectItem(const int id) -{ - mProtectedItems.insert(id); - saveProtectedItems(); -} - -void unprotectItem(const int id) -{ - mProtectedItems.erase(id); - saveProtectedItems(); -} - -bool isItemProtected(const int id) -{ - return mProtectedItems.find(id) != mProtectedItems.end(); -} - -void setMercenary(MercenaryInfo *const info) -{ - delete mMercenary; - mMercenary = info; -} - -void setMercenaryBeing(Being *const being) -{ - if (being == nullptr || - mMercenary == nullptr) - { - return; - } - being->setName(mMercenary->name); - being->setOwner(localPlayer); - being->setLevel(mMercenary->level); - being->setAttackRange(mMercenary->range); -} - -void setElemental(const BeingId id) -{ - mElementalId = id; -} - -BeingId getElementalId() -{ - return mElementalId; -} - -MercenaryInfo *getMercenary() -{ - return mMercenary; -} - -void setPet(PetInfo *const info) -{ - delete mPet; - mPet = info; -} - -void setPetBeing(Being *const being) -{ - if (being != nullptr) - mPetBeingId = being->getId(); - else - mPetBeingId = BeingId_zero; - if (being == nullptr || - mPet == nullptr) - { - return; - } - being->setName(mPet->name); - being->setOwner(localPlayer); - being->setLevel(mPet->level); -} - -PetInfo *getPet() -{ - return mPet; -} - -BeingId getPetBeingId() -{ - return mPetBeingId; -} - -void setHomunculus(HomunculusInfo *const info) -{ - delete mHomunculus; - mHomunculus = info; -} - -void setHomunculusBeing(Being *const being) -{ - if (being == nullptr || - mHomunculus == nullptr) - { - return; - } - being->setName(mHomunculus->name); - being->setOwner(localPlayer); -} - -HomunculusInfo *getHomunculus() -{ - return mHomunculus; -} - -BeingId getHomunculusId() -{ - return mHomunculus != nullptr ? mHomunculus->id : BeingId_zero; -} - -BeingId getMercenaryId() -{ - return mMercenary != nullptr ? mMercenary->id : BeingId_zero; -} - -void updateAttackAi(const BeingId targetId, - const Keep keep) -{ - if (mMercenary != nullptr && - mercenaryHandler != nullptr) - { - mercenaryHandler->attack(targetId, keep); - } - if (mHomunculus != nullptr && - homunculusHandler != nullptr) - { - homunculusHandler->attack(targetId, keep); - } -} - -std::string getRoomName() -{ - return mRoomName; -} - -void setRoomName(const std::string &name) -{ - mRoomName = name; -} - -bool isInRoom() -{ - return !mRoomName.empty(); -} - -void setGuildPositionFlags(const GuildPositionFlags::Type pos) -{ - mGuildPositionFlags = pos; -} - -GuildPositionFlags::Type getGuildPositionFlags() -{ - return mGuildPositionFlags; -} - -void enableVending(const bool b) -{ - mVending = b; -} - -bool isVending() -{ - return mVending; -} - -void setServerLanguage(const int lang) -{ - if (lang != mServerLanguage) - { - mServerLanguage = lang; - TranslationManager::loadDictionaryLang(); - } -} - -int getServerLanguage() -{ - return mServerLanguage; -} - -} // namespace PlayerInfo diff --git a/src/being/playerinfo.h b/src/being/playerinfo.h deleted file mode 100644 index 5528a1c3d..000000000 --- a/src/being/playerinfo.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 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/>. - */ - -#ifndef BEING_PLAYERINFO_H -#define BEING_PLAYERINFO_H - -#include "equipment.h" - -#include "enums/guildpositionflags.h" -#include "enums/state.h" - -#include "enums/being/attributes.h" - -#include "enums/simpletypes/beingid.h" -#include "enums/simpletypes/keep.h" -#include "enums/simpletypes/notify.h" -#include "enums/simpletypes/sfx.h" -#include "enums/simpletypes/trading.h" - -#include "utils/intmap.h" - -#include <string> - -/** - * Stat information storage structure. - */ -struct Stat final -{ - A_DEFAULT_COPY(Stat) - - int base; - int mod; - int exp; - int expNeed; -}; - -typedef std::map<AttributesT, int64_t> AtrIntMap; -typedef std::map<AttributesT, Stat> StatMap; - -/** - * Backend for core player information. - */ -struct PlayerInfoBackend final -{ - PlayerInfoBackend() : - mAttributes(), - mStats(), - mSkills() - { - } - - A_DEFAULT_COPY(PlayerInfoBackend) - - AtrIntMap mAttributes; - StatMap mStats; - IntMap mSkills; -}; - -class Being; -class FloorItem; -class Inventory; -class Item; - -struct HomunculusInfo; -struct MercenaryInfo; -struct PetInfo; - -/** - * A database like namespace which holds global info about the localplayer - * - */ -namespace PlayerInfo -{ -// --- Attributes ------------------------------------------------------------- - - /** - * Returns the value of the given attribute. - */ - int64_t getAttribute64(const AttributesT id) A_WARN_UNUSED; - - int32_t getAttribute(const AttributesT id) A_WARN_UNUSED; - - /** - * Changes the value of the given attribute. - */ - void setAttribute(const AttributesT id, - const int64_t value, - const Notify notify = Notify_true); - - int getSkillLevel(const int id) A_WARN_UNUSED; - - void setSkillLevel(const int id, const int value); - -// --- Stats ------------------------------------------------------------------ - - /** - * Returns the base value of the given stat. - */ - int getStatBase(const AttributesT id) A_WARN_UNUSED; - - /** - * Changes the base value of the given stat. - */ - void setStatBase(const AttributesT id, - const int value, - const Notify notify = Notify_true); - - /** - * Returns the modifier for the given stat. - */ - int getStatMod(const AttributesT id) A_WARN_UNUSED; - - /** - * Changes the modifier for the given stat. - */ - void setStatMod(const AttributesT id, - const int value, - const Notify notify = Notify_true); - - /** - * Returns the current effective value of the given stat. Effective is base - * + mod - */ - int getStatEffective(const AttributesT id) A_WARN_UNUSED; - - /** - * Changes the level of the given stat. - */ - void setStatLevel(AttributesT id, int value, Notify notify = Notify_true); - - /** - * Returns the experience of the given stat. - */ - const std::pair<int, int> getStatExperience(const AttributesT id) - A_WARN_UNUSED; - - /** - * Changes the experience of the given stat. - */ - void setStatExperience(const AttributesT id, - const int have, - const int need, - const Notify notify = Notify_true); - -// --- Inventory / Equipment -------------------------------------------------- - - /** - * Returns the player's inventory. - */ - Inventory *getInventory() A_WARN_UNUSED; - - Inventory *getStorageInventory() A_WARN_UNUSED; - - Inventory *getCartInventory() A_WARN_UNUSED; - - /** - * Clears the player's inventory and equipment. - */ - void clearInventory(); - - void clear(); - - /** - * Returns the player's equipment. - */ - Equipment *getEquipment() A_WARN_UNUSED; - - /** - * Returns the player's equipment at the given slot. - */ - const Item *getEquipment(const unsigned int slot) A_WARN_UNUSED; - -// --- Misc ------------------------------------------------------------------- - - /** - * Changes the internal PlayerInfoBackend reference; - */ - void setBackend(const PlayerInfoBackend &backend); - - void setCharId(const int charId); - - int getCharId(); - - /** - * Returns true if the player is involved in a trade at the moment, false - * otherwise. - */ - Trading isTrading(); - - /** - * Sets whether the player is currently involved in trade or not. - */ - void setTrading(const Trading trading); - - void updateAttrs(); - - /** - * Initializes some internals. - */ - void init() A_CONST; - - void deinit(); - - void loadData(); - - bool isTalking(); - - void gameDestroyed(); - - void stateChange(const StateT state); - - void triggerAttr(const AttributesT id, - const int64_t old); - - void triggerStat(const AttributesT id, - const int old1, - const int old2); - - void setEquipmentBackend(Equipment::Backend *const backend); - - void equipItem(const Item *const item, const Sfx sfx); - - void unequipItem(const Item *const item, const Sfx sfx); - - void useItem(const Item *const item, const Sfx sfx); - - void useEquipItem(const Item *const item, - const int16_t useType, - const Sfx sfx); - - void useEquipItem2(const Item *const item, - const int16_t useType, - const Sfx sfx); - - void dropItem(const Item *const item, const int amount, const Sfx sfx); - - void pickUpItem(const FloorItem *const item, const Sfx sfx); - - void protectItem(const int id); - - void unprotectItem(const int id); - - bool isItemProtected(const int id); - - MercenaryInfo *getMercenary(); - - void setMercenary(MercenaryInfo *const info); - - void setMercenaryBeing(Being *const being); - - PetInfo *getPet(); - - void setPet(PetInfo *const info); - - void setPetBeing(Being *const being); - - BeingId getPetBeingId(); - - HomunculusInfo *getHomunculus(); - - void setHomunculus(HomunculusInfo *const info); - - void setHomunculusBeing(Being *const being); - - void setElemental(const BeingId id); - - BeingId getHomunculusId(); - - BeingId getMercenaryId(); - - BeingId getElementalId(); - - void updateAttackAi(const BeingId targetId, - const Keep keep); - - std::string getRoomName(); - - void setRoomName(const std::string &name); - - bool isInRoom(); - - void setGuildPositionFlags(const GuildPositionFlags::Type pos); - - GuildPositionFlags::Type getGuildPositionFlags(); - - void enableVending(const bool b); - - bool isVending() A_WARN_UNUSED; - - void setServerLanguage(const int lang); - - int getServerLanguage() A_WARN_UNUSED; -} // namespace PlayerInfo - -#endif // BEING_PLAYERINFO_H diff --git a/src/being/playerrelation.cpp b/src/being/playerrelation.cpp deleted file mode 100644 index 0b4627089..000000000 --- a/src/being/playerrelation.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2008-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/playerrelation.h" - -#include "debug.h" - -PlayerRelation::PlayerRelation(const RelationT relation) : - mRelation(relation) -{ -} diff --git a/src/being/playerrelation.h b/src/being/playerrelation.h deleted file mode 100644 index bc96c9bcd..000000000 --- a/src/being/playerrelation.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2008-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/>. - */ - -#ifndef BEING_PLAYERRELATION_H -#define BEING_PLAYERRELATION_H - -#include "enums/being/relation.h" - -#include "localconsts.h" - -struct PlayerRelation final -{ - static const unsigned int EMOTE = (1U << 0); - static const unsigned int SPEECH_FLOAT = (1U << 1); - static const unsigned int SPEECH_LOG = (1U << 2); - static const unsigned int WHISPER = (1U << 3); - static const unsigned int TRADE = (1U << 4); - static const unsigned int INVISIBLE = (1U << 5); - static const unsigned int BLACKLIST = (1U << 6); - static const unsigned int ENEMY = (1U << 7); - - static const unsigned int RELATIONS_NR = 7; - static const unsigned int RELATION_PERMISSIONS[RELATIONS_NR]; - - static const unsigned int DEFAULT = EMOTE - | SPEECH_FLOAT - | SPEECH_LOG - | WHISPER - | TRADE; - - explicit PlayerRelation(const RelationT relation); - - A_DELETE_COPY(PlayerRelation) - - RelationT mRelation; // bitmask for all of the above -}; - -#endif // BEING_PLAYERRELATION_H diff --git a/src/being/playerrelations.cpp b/src/being/playerrelations.cpp deleted file mode 100644 index fe774432b..000000000 --- a/src/being/playerrelations.cpp +++ /dev/null @@ -1,661 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2008-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/playerrelations.h" - -#include "actormanager.h" -#include "configuration.h" -#include "logger.h" - -#include "being/localplayer.h" -#include "being/playerignorestrategy.h" -#include "being/playerrelation.h" - -#include "utils/dtor.h" -#include "utils/foreach.h" -#include "utils/gettext.h" - -#include "listeners/playerrelationslistener.h" - -#include "debug.h" - -static const unsigned int FIRST_IGNORE_EMOTE = 14; - -typedef std::map<std::string, PlayerRelation *> PlayerRelations; -typedef PlayerRelations::const_iterator PlayerRelationsCIter; -typedef std::list<PlayerRelationsListener *> PlayerRelationListeners; -typedef PlayerRelationListeners::const_iterator PlayerRelationListenersCIter; - -static const char *const PLAYER_IGNORE_STRATEGY_NOP = "nop"; -static const char *const PLAYER_IGNORE_STRATEGY_EMOTE0 = "emote0"; -static const char *const DEFAULT_IGNORE_STRATEGY = - PLAYER_IGNORE_STRATEGY_EMOTE0; - -static const char *const NAME = "name"; -static const char *const RELATION = "relation"; - -static const unsigned int IGNORE_EMOTE_TIME = 100; - -namespace -{ - class SortPlayersFunctor final - { - public: - SortPlayersFunctor() - { } - - A_DEFAULT_COPY(SortPlayersFunctor) - - bool operator() (const std::string &str1, - const std::string &str2) const - { - std::string s1 = str1; - std::string s2 = str2; - toLower(s1); - toLower(s2); - if (s1 == s2) - return str1 < str2; - return s1 < s2; - } - } playersRelSorter; - - // (De)serialisation class - class PlayerConfSerialiser final : - public ConfigurationListManager<std::pair<std::string, - PlayerRelation *>, std::map<std::string, PlayerRelation *> *> - { - public: - PlayerConfSerialiser() - { } - - A_DELETE_COPY(PlayerConfSerialiser) - - ConfigurationObject *writeConfigItem( - const std::pair<std::string, PlayerRelation *> &value, - ConfigurationObject *const cobj) const override final - { - if (cobj == nullptr || - value.second == nullptr) - { - return nullptr; - } - cobj->setValue(NAME, value.first); - cobj->setValue(RELATION, toString( - CAST_S32(value.second->mRelation))); - - return cobj; - } - - std::map<std::string, PlayerRelation *> * - readConfigItem(const ConfigurationObject *const cobj, - std::map<std::string, PlayerRelation *> - *const container) const override final - { - if (cobj == nullptr || - container == nullptr) - { - return container; - } - const std::string name = cobj->getValue(NAME, ""); - if (name.empty()) - return container; - - if ((*container)[name] == nullptr) - { - const int v = cobj->getValueInt(RELATION, - CAST_S32(Relation::NEUTRAL)); - - (*container)[name] = new PlayerRelation( - static_cast<RelationT>(v)); - } - // otherwise ignore the duplicate entry - - return container; - } - }; -} // namespace - -static PlayerConfSerialiser player_conf_serialiser; // stateless singleton - -const unsigned int PlayerRelation::RELATION_PERMISSIONS[RELATIONS_NR] = -{ - /* NEUTRAL */ 0, // we always fall back to the defaults anyway - /* FRIEND */ EMOTE | SPEECH_FLOAT | SPEECH_LOG | WHISPER | TRADE, - /* DISREGARDED*/ EMOTE | SPEECH_FLOAT, - /* IGNORED */ 0, - /* ERASED */ INVISIBLE, - /* BLACKLISTED */ SPEECH_LOG | WHISPER, - /* ENEMY2 */ EMOTE | SPEECH_FLOAT | SPEECH_LOG | WHISPER | TRADE -}; - -PlayerRelationsManager::PlayerRelationsManager() : - mPersistIgnores(false), - mDefaultPermissions(PlayerRelation::DEFAULT), - mIgnoreStrategy(nullptr), - mRelations(), - mListeners(), - mIgnoreStrategies() -{ -} - -PlayerRelationsManager::~PlayerRelationsManager() -{ - delete_all(mIgnoreStrategies); - - FOR_EACH (PlayerRelationsCIter, it, mRelations) - delete it->second; - mRelations.clear(); -} - -void PlayerRelationsManager::clear() -{ - StringVect *const names = getPlayers(); - FOR_EACHP (StringVectCIter, it, names) - removePlayer(*it); - delete names; -} - -static const char *const PERSIST_IGNORE_LIST = "persistent-player-list"; -static const char *const PLAYER_IGNORE_STRATEGY = "player-ignore-strategy"; -static const char *const DEFAULT_PERMISSIONS = "default-player-permissions"; - -int PlayerRelationsManager::getPlayerIgnoreStrategyIndex( - const std::string &name) -{ - const STD_VECTOR<PlayerIgnoreStrategy *> *const strategies - = getPlayerIgnoreStrategies(); - - if (strategies == nullptr) - return -1; - - const size_t sz = strategies->size(); - for (size_t i = 0; i < sz; i++) - { - if ((*strategies)[i]->mShortName == name) - return CAST_S32(i); - } - - return -1; -} - -void PlayerRelationsManager::load() -{ - Configuration *const cfg = &serverConfig; - clear(); - - mPersistIgnores = (cfg->getValue(PERSIST_IGNORE_LIST, 1) != 0); - mDefaultPermissions = CAST_S32(cfg->getValue(DEFAULT_PERMISSIONS, - mDefaultPermissions)); - - const std::string ignore_strategy_name = cfg->getValue( - PLAYER_IGNORE_STRATEGY, DEFAULT_IGNORE_STRATEGY); - const int ignore_strategy_index = getPlayerIgnoreStrategyIndex( - ignore_strategy_name); - - if (ignore_strategy_index >= 0) - { - setPlayerIgnoreStrategy((*getPlayerIgnoreStrategies()) - [ignore_strategy_index]); - } - - cfg->getList<std::pair<std::string, PlayerRelation *>, - std::map<std::string, PlayerRelation *> *> - ("player", &(mRelations), &player_conf_serialiser); -} - - -void PlayerRelationsManager::init() -{ - load(); - - if (!mPersistIgnores) - { - clear(); // Yes, we still keep them around in the config file - // until the next update. - } - - FOR_EACH (PlayerRelationListenersCIter, it, mListeners) - (*it)->updateAll(); -} - -void PlayerRelationsManager::store() const -{ - serverConfig.setList<std::map<std::string, - PlayerRelation *>::const_iterator, - std::pair<std::string, PlayerRelation *>, - std::map<std::string, PlayerRelation *> *> - ("player", mRelations.begin(), mRelations.end(), - &player_conf_serialiser); - - serverConfig.setValue(DEFAULT_PERMISSIONS, mDefaultPermissions); - serverConfig.setValue(PERSIST_IGNORE_LIST, mPersistIgnores); - serverConfig.setValue(PLAYER_IGNORE_STRATEGY, - mIgnoreStrategy != nullptr ? mIgnoreStrategy->mShortName : - DEFAULT_IGNORE_STRATEGY); - - serverConfig.write(); -} - -void PlayerRelationsManager::signalUpdate(const std::string &name) -{ - FOR_EACH (PlayerRelationListenersCIter, it, mListeners) - (*it)->updatedPlayer(name); - - if (actorManager != nullptr) - { - Being *const being = actorManager->findBeingByName( - name, ActorType::Player); - - if (being != nullptr && - being->getType() == ActorType::Player) - { - being->updateColors(); - } - } -} - -unsigned int PlayerRelationsManager::checkPermissionSilently( - const std::string &player_name, const unsigned int flags) const -{ - const std::map<std::string, PlayerRelation *>::const_iterator - it = mRelations.find(player_name); - if (it == mRelations.end()) - { - return mDefaultPermissions & flags; - } - - const PlayerRelation *const r = (*it).second; - unsigned int permissions = PlayerRelation::RELATION_PERMISSIONS[ - CAST_S32(r->mRelation)]; - - switch (r->mRelation) - { - case Relation::NEUTRAL: - permissions = mDefaultPermissions; - break; - - case Relation::FRIEND: - permissions |= mDefaultPermissions; // widen - break; - - case Relation::DISREGARDED: - case Relation::IGNORED: - case Relation::ERASED: - case Relation::BLACKLISTED: - case Relation::ENEMY2: - default: - permissions &= mDefaultPermissions; // narrow - break; - } - - return permissions & flags; -} - -bool PlayerRelationsManager::hasPermission(const Being *const being, - const unsigned int flags) const -{ - if (being == nullptr) - return false; - - if (being->getType() == ActorType::Player) - { - return static_cast<unsigned int>(hasPermission( - being->getName(), flags)) == flags; - } - return true; -} - -bool PlayerRelationsManager::hasPermission(const std::string &name, - const unsigned int flags) const -{ - if (actorManager == nullptr) - return false; - - const unsigned int rejections = flags - & ~checkPermissionSilently(name, flags); - const bool permitted = (rejections == 0); - - if (!permitted) - { - // execute `ignore' strategy, if possible - if (mIgnoreStrategy != nullptr) - { - Being *const b = actorManager->findBeingByName( - name, ActorType::Player); - - if ((b != nullptr) && b->getType() == ActorType::Player) - mIgnoreStrategy->ignore(b, rejections); - } - } - - return permitted; -} - -void PlayerRelationsManager::setRelation(const std::string &player_name, - const RelationT relation) -{ - if (localPlayer == nullptr || - (relation != Relation::NEUTRAL && - localPlayer->getName() == player_name)) - { - return; - } - - PlayerRelation *const r = mRelations[player_name]; - if (r == nullptr) - mRelations[player_name] = new PlayerRelation(relation); - else - r->mRelation = relation; - - signalUpdate(player_name); - store(); -} - -StringVect *PlayerRelationsManager::getPlayers() const -{ - StringVect *const retval = new StringVect; - - FOR_EACH (PlayerRelationsCIter, it, mRelations) - { - if (it->second != nullptr) - retval->push_back(it->first); - } - - std::sort(retval->begin(), retval->end(), playersRelSorter); - - return retval; -} - -StringVect *PlayerRelationsManager::getPlayersByRelation( - const RelationT rel) const -{ - StringVect *const retval = new StringVect; - - FOR_EACH (PlayerRelationsCIter, it, mRelations) - { - if ((it->second != nullptr) && - it->second->mRelation == rel) - { - retval->push_back(it->first); - } - } - - std::sort(retval->begin(), retval->end(), playersRelSorter); - - return retval; -} - -void PlayerRelationsManager::removePlayer(const std::string &name) -{ - delete mRelations[name]; - mRelations.erase(name); - signalUpdate(name); -} - - -RelationT PlayerRelationsManager::getRelation( - const std::string &name) const -{ - const std::map<std::string, PlayerRelation *>::const_iterator - it = mRelations.find(name); - if (it != mRelations.end()) - return (*it).second->mRelation; - - return Relation::NEUTRAL; -} - -//////////////////////////////////////// -// defaults - -unsigned int PlayerRelationsManager::getDefault() const -{ - return mDefaultPermissions; -} - -void PlayerRelationsManager::setDefault(const unsigned int permissions) -{ - mDefaultPermissions = permissions; - - store(); - signalUpdate(""); -} - -void PlayerRelationsManager::ignoreTrade(const std::string &name) const -{ - if (name.empty()) - return; - - const RelationT relation = getRelation(name); - - if (relation == Relation::IGNORED || - relation == Relation::DISREGARDED || - relation == Relation::BLACKLISTED || - relation == Relation::ERASED) - { - return; - } - playerRelations.setRelation(name, Relation::BLACKLISTED); -} - -bool PlayerRelationsManager::checkBadRelation(const std::string &name) const -{ - if (name.empty()) - return true; - - const RelationT relation = getRelation(name); - - if (relation == Relation::IGNORED || - relation == Relation::DISREGARDED || - relation == Relation::BLACKLISTED || - relation == Relation::ERASED || - relation == Relation::ENEMY2) - { - return true; - } - return false; -} - -//////////////////////////////////////// -// ignore strategies - - -class PIS_nothing final : public PlayerIgnoreStrategy -{ - public: - PIS_nothing() : - PlayerIgnoreStrategy() - { - // TRANSLATORS: ignore/unignore action - mDescription = _("Completely ignore"); - mShortName = PLAYER_IGNORE_STRATEGY_NOP; - } - - A_DELETE_COPY(PIS_nothing) - - void ignore(Being *const being A_UNUSED, - const unsigned int flags A_UNUSED) const override final - { - } -}; - -class PIS_dotdotdot final : public PlayerIgnoreStrategy -{ - public: - PIS_dotdotdot() : - PlayerIgnoreStrategy() - { - // TRANSLATORS: ignore/unignore action - mDescription = _("Print '...'"); - mShortName = "dotdotdot"; - } - - A_DELETE_COPY(PIS_dotdotdot) - - void ignore(Being *const being, - const unsigned int flags A_UNUSED) const override final - { - if (being == nullptr) - return; - - logger->log("ignoring: " + being->getName()); - being->setSpeech("..."); - } -}; - - -class PIS_blinkname final : public PlayerIgnoreStrategy -{ - public: - PIS_blinkname() : - PlayerIgnoreStrategy() - { - // TRANSLATORS: ignore/unignore action - mDescription = _("Blink name"); - mShortName = "blinkname"; - } - - A_DELETE_COPY(PIS_blinkname) - - void ignore(Being *const being, - const unsigned int flags A_UNUSED) const override final - { - if (being == nullptr) - return; - - logger->log("ignoring: " + being->getName()); - being->flashName(200); - } -}; - -class PIS_emote final : public PlayerIgnoreStrategy -{ - public: - PIS_emote(const uint8_t emote_nr, - const std::string &description, - const std::string &shortname) : - PlayerIgnoreStrategy(), - mEmotion(emote_nr) - { - mDescription = description; - mShortName = shortname; - } - - A_DELETE_COPY(PIS_emote) - - void ignore(Being *const being, - const unsigned int flags A_UNUSED) const override final - { - if (being == nullptr) - return; - - being->setEmote(mEmotion, IGNORE_EMOTE_TIME); - } - uint8_t mEmotion; -}; - -STD_VECTOR<PlayerIgnoreStrategy *> * -PlayerRelationsManager::getPlayerIgnoreStrategies() -{ - if (mIgnoreStrategies.empty()) - { - // not initialised yet? - mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE, - // TRANSLATORS: ignore strategi - _("Floating '...' bubble"), - PLAYER_IGNORE_STRATEGY_EMOTE0)); - mIgnoreStrategies.push_back(new PIS_emote(FIRST_IGNORE_EMOTE + 1, - // TRANSLATORS: ignore strategi - _("Floating bubble"), - "emote1")); - mIgnoreStrategies.push_back(new PIS_nothing); - mIgnoreStrategies.push_back(new PIS_dotdotdot); - mIgnoreStrategies.push_back(new PIS_blinkname); - } - return &mIgnoreStrategies; -} - -bool PlayerRelationsManager::isGoodName(const std::string &name) const -{ - const size_t size = name.size(); - - if (size < 3) - return true; - - const std::map<std::string, PlayerRelation *>::const_iterator - it = mRelations.find(name); - if (it != mRelations.end()) - return true; - - return checkName(name); -} - -bool PlayerRelationsManager::isGoodName(Being *const being) const -{ - if (being == nullptr) - return false; - if (being->getGoodStatus() != -1) - return being->getGoodStatus() == 1; - - const std::string &name = being->getName(); - const size_t size = name.size(); - - if (size < 3) - return true; - - const std::map<std::string, PlayerRelation *>::const_iterator - it = mRelations.find(name); - if (it != mRelations.end()) - return true; - - const bool status = checkName(name); - being->setGoodStatus(status ? 1 : 0); - return status; -} - -bool PlayerRelationsManager::checkName(const std::string &name) -{ - const size_t size = name.size(); - const std::string check = config.getStringValue("unsecureChars"); - const std::string lastChar = name.substr(size - 1, 1); - - if (name.substr(0, 1) == " " || - lastChar == " " || - lastChar == "." || - name.find(" ") != std::string::npos) - { - return false; - } - else if (check.empty()) - { - return true; - } - else if (name.find_first_of(check) != std::string::npos) - { - return false; - } - else - { - return true; - } -} - -PlayerRelationsManager playerRelations; diff --git a/src/being/playerrelations.h b/src/being/playerrelations.h deleted file mode 100644 index d1db4a003..000000000 --- a/src/being/playerrelations.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * The ManaPlus Client - * Copyright (C) 2008-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/>. - */ - -#ifndef BEING_PLAYERRELATIONS_H -#define BEING_PLAYERRELATIONS_H - -#include "utils/stringvector.h" - -#include "enums/being/relation.h" - -#include <list> -#include <map> - -#include "localconsts.h" - -class Being; -class PlayerIgnoreStrategy; -class PlayerRelationsListener; - -struct PlayerRelation; - -/** - * Player relations class, represents any particular relations and/or - * preferences the user of the local client has wrt other players (identified - * by std::string). - */ -class PlayerRelationsManager final -{ - public: - PlayerRelationsManager(); - - A_DELETE_COPY(PlayerRelationsManager) - - ~PlayerRelationsManager(); - - /** - * Initialise player relations manager (load config file etc.) - */ - void init(); - - /** - * Load configuration from our config file, or substitute defaults. - */ - void load(); - - /** - * Save configuration to our config file. - */ - void store() const; - - /** - * Determines whether the player in question is being ignored, filtered by - * the specified flags. - */ - unsigned int checkPermissionSilently(const std::string &player_name, - const unsigned int flags) - const A_WARN_UNUSED; - - /** - * Tests whether the player in question is being ignored for any of the - * actions in the specified flags. If so, trigger appropriate side effects - * if requested by the player. - */ - bool hasPermission(const Being *const being, - const unsigned int flags) const A_WARN_UNUSED; - - bool hasPermission(const std::string &being, - const unsigned int flags) const A_WARN_UNUSED; - - /** - * Updates the relationship with this player. - */ - void setRelation(const std::string &name, - const RelationT relation); - - /** - * Updates the relationship with this player. - */ - RelationT getRelation(const std::string &name) const A_WARN_UNUSED; - - /** - * Deletes the information recorded for a player. - */ - void removePlayer(const std::string &name); - - /** - * Retrieves the default permissions. - */ - unsigned int getDefault() const A_WARN_UNUSED; - - /** - * Sets the default permissions. - */ - void setDefault(const unsigned int permissions); - - /** - * Retrieves all known player ignore strategies. - * - * The player ignore strategies are allocated statically and must - * not be deleted. - */ - STD_VECTOR<PlayerIgnoreStrategy *> *getPlayerIgnoreStrategies() - A_WARN_UNUSED; - - /** - * Return the current player ignore strategy. - * - * \return A player ignore strategy, or nullptr - */ - const PlayerIgnoreStrategy *getPlayerIgnoreStrategy() const - noexcept2 - A_WARN_UNUSED - { return mIgnoreStrategy; } - - /** - * Sets the strategy to call when ignoring players. - */ - void setPlayerIgnoreStrategy(PlayerIgnoreStrategy *const strategy) - noexcept2 - { mIgnoreStrategy = strategy; } - - /** - * For a given ignore strategy short name, find the appropriate index - * in the ignore strategies vector. - * - * \param The short name of the ignore strategy to look up - * \return The appropriate index, or -1 - */ - int getPlayerIgnoreStrategyIndex(const std::string &shortname) - A_WARN_UNUSED; - - /** - * Retrieves a sorted vector of all players for which we have any - * relations recorded. - */ - StringVect *getPlayers() const RETURNS_NONNULL A_WARN_UNUSED; - - StringVect *getPlayersByRelation(const RelationT rel) - const A_WARN_UNUSED; - - /** - * Removes all recorded player info. - */ - void clear(); - - /** - * Do we persist our `ignore' setup? - */ - bool getPersistIgnores() const noexcept2 A_WARN_UNUSED - { return mPersistIgnores; } - - void ignoreTrade(const std::string &name) const; - - bool isGoodName(Being *const being) const A_WARN_UNUSED; - - bool isGoodName(const std::string &name) const A_WARN_UNUSED; - - /** - * Change the `ignore persist' flag. - * - * @param value Whether to persist ignores - */ - void setPersistIgnores(const bool value) noexcept2 - { mPersistIgnores = value; } - - void addListener(PlayerRelationsListener *const listener) - { mListeners.push_back(listener); } - - void removeListener(PlayerRelationsListener *const listener) - { mListeners.remove(listener); } - - bool checkBadRelation(const std::string &name) const A_WARN_UNUSED; - - private: - void signalUpdate(const std::string &name); - - bool mPersistIgnores; // If NOT set, we delete the - // ignored data upon reloading - unsigned int mDefaultPermissions; - - static bool checkName(const std::string &name) A_WARN_UNUSED; - - PlayerIgnoreStrategy *mIgnoreStrategy; - std::map<std::string, PlayerRelation *> mRelations; - std::list<PlayerRelationsListener *> mListeners; - STD_VECTOR<PlayerIgnoreStrategy *> mIgnoreStrategies; -}; - - -extern PlayerRelationsManager playerRelations; // singleton representation - // of player relations - - -#endif // BEING_PLAYERRELATIONS_H |