diff options
author | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-02-17 13:10:20 +0100 |
---|---|---|
committer | Thorbjørn Lindeijer <bjorn@lindeijer.nl> | 2025-02-21 15:47:08 +0100 |
commit | 0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24 (patch) | |
tree | b6d5761900fff24d10247ac8c333f90885f320e9 | |
parent | d43e93d4f10769d86d2c1a6e8fc62af83812d672 (diff) | |
download | mana-0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24.tar.gz mana-0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24.tar.bz2 mana-0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24.tar.xz mana-0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24.zip |
Moved stun and status effect handling from ActorSprite to Being
Since this stuff is only relevant for Being instances and not for
FloorItem instances.
Also removed the virtual getWidth/getHeight from Actor, since they were
not actually used.
-rw-r--r-- | src/actor.h | 14 | ||||
-rw-r--r-- | src/actorsprite.cpp | 101 | ||||
-rw-r--r-- | src/actorsprite.h | 61 | ||||
-rw-r--r-- | src/being.cpp | 85 | ||||
-rw-r--r-- | src/being.h | 50 | ||||
-rw-r--r-- | src/compoundsprite.cpp | 10 | ||||
-rw-r--r-- | src/localplayer.cpp | 22 | ||||
-rw-r--r-- | src/localplayer.h | 3 |
8 files changed, 160 insertions, 186 deletions
diff --git a/src/actor.h b/src/actor.h index b67b6402..a54fba0a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -48,20 +48,6 @@ public: virtual bool draw(Graphics *graphics, int offsetX, int offsetY) const = 0; /** - * Returns the horizontal size of the actors graphical representation - * in pixels or 0 when it is undefined. - */ - virtual int getWidth() const - { return 0; } - - /** - * Returns the vertical size of the actors graphical representation - * in pixels or 0 when it is undefined. - */ - virtual int getHeight() const - { return 0; } - - /** * Returns the pixel position of this actor. */ const Vector &getPosition() const diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index ae731305..b98cad70 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -20,13 +20,14 @@ #include "actorsprite.h" +#include "animatedsprite.h" #include "configuration.h" #include "event.h" #include "imagesprite.h" #include "localplayer.h" #include "log.h" +#include "particle.h" #include "simpleanimation.h" -#include "statuseffect.h" #include "resources/animation.h" #include "resources/image.h" @@ -44,10 +45,8 @@ ImageSet *ActorSprite::targetCursorImages[2][NUM_TC]; SimpleAnimation *ActorSprite::targetCursor[2][NUM_TC]; bool ActorSprite::loaded = false; -ActorSprite::ActorSprite(int id): - mId(id), - mStatusParticleEffects(&mStunParticleEffects, false), - mChildParticleEffects(&mStatusParticleEffects, false) +ActorSprite::ActorSprite(int id) + : mId(id) {} ActorSprite::~ActorSprite() @@ -99,18 +98,6 @@ void ActorSprite::logic() if (mUsedTargetCursor) mUsedTargetCursor->update(Time::deltaTimeMs()); - // Restart status/particle effects, if needed - if (mMustResetParticles) - { - mMustResetParticles = false; - for (int statusEffect : mStatusEffects) - { - const StatusEffect *effect = StatusEffect::getStatusEffect(statusEffect, true); - if (effect && effect->particleEffectIsPersistent()) - updateStatusEffect(statusEffect, true); - } - } - // See note at ActorSprite::draw float py = mPos.y; if (mMap) @@ -126,7 +113,6 @@ void ActorSprite::setMap(Map* map) // Clear particle effect list because child particles became invalid mChildParticleEffects.clear(); - mMustResetParticles = true; // Reset status particles on next redraw } void ActorSprite::controlParticle(Particle *particle) @@ -142,83 +128,6 @@ void ActorSprite::setTargetType(TargetCursorType type) mUsedTargetCursor = targetCursor[type][getTargetCursorSize()]; } -void ActorSprite::setStatusEffect(int index, bool active) -{ - const bool wasActive = mStatusEffects.find(index) != mStatusEffects.end(); - - if (active != wasActive) - { - updateStatusEffect(index, active); - if (active) - mStatusEffects.insert(index); - else - mStatusEffects.erase(index); - } -} - -void ActorSprite::setStatusEffectBlock(int offset, uint16_t newEffects) -{ - for (int i = 0; i < STATUS_EFFECTS; i++) - { - int index = StatusEffect::blockEffectIndexToEffectIndex(offset + i); - - if (index != -1) - setStatusEffect(index, (newEffects & (1 << i)) > 0); - } -} - -void ActorSprite::updateStunMode(int oldMode, int newMode) -{ - if (this == local_player) - { - Event event(Event::Stun); - event.setInt("oldMode", oldMode); - event.setInt("newMode", newMode); - event.trigger(Event::ActorSpriteChannel); - } - - handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1); - handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1); -} - -void ActorSprite::updateStatusEffect(int index, bool newStatus) -{ - if (this == local_player) - { - Event event(Event::UpdateStatusEffect); - event.setInt("index", index); - event.setBool("newStatus", newStatus); - event.trigger(Event::ActorSpriteChannel); - } - - handleStatusEffect(StatusEffect::getStatusEffect(index, newStatus), index); -} - -void ActorSprite::handleStatusEffect(StatusEffect *effect, int effectId) -{ - if (!effect) - return; - - // TODO: Find out how this is meant to be used - // (SpriteAction != Being::Action) - //SpriteAction action = effect->getAction(); - //if (action != ACTION_INVALID) - // setAction(action); - - Particle *particle = effect->getParticle(); - - if (effectId >= 0) - { - mStatusParticleEffects.setLocally(effectId, particle); - } - else - { - mStunParticleEffects.clearLocally(); - if (particle) - mStunParticleEffects.addLocally(particle); - } -} - void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, bool forceDisplay) { @@ -261,8 +170,6 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, for (const auto &particle : display.particles) controlParticle(particleEngine->addEffect(particle, 0, 0)); } - - mMustResetParticles = true; } void ActorSprite::load() diff --git a/src/actorsprite.h b/src/actorsprite.h index a25481ec..35635752 100644 --- a/src/actorsprite.h +++ b/src/actorsprite.h @@ -25,9 +25,6 @@ #include "map.h" #include "particlecontainer.h" -#include <cstdint> -#include <set> - class SimpleAnimation; class StatusEffect; @@ -78,7 +75,7 @@ public: bool draw(Graphics *graphics, int offsetX, int offsetY) const override; - virtual bool drawSpriteAt(Graphics *graphics, int x, int y) const; + bool drawSpriteAt(Graphics *graphics, int x, int y) const; virtual void logic(); @@ -111,79 +108,23 @@ public: */ void untarget() { mUsedTargetCursor = nullptr; } - /** - * Sets the actor's stun mode. If zero, the being is `normal', otherwise it - * is `stunned' in some fashion. - */ - void setStunMode(int stunMode) - { - if (mStunMode != stunMode) - updateStunMode(mStunMode, stunMode); - mStunMode = stunMode; - } - - void setStatusEffect(int index, bool active); - - /** - * 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(int offset, uint16_t flags); - void setAlpha(float alpha) override { CompoundSprite::setAlpha(alpha); } float getAlpha() const override { return CompoundSprite::getAlpha(); } - int getWidth() const override - { return CompoundSprite::getWidth(); } - - int getHeight() const override - { return CompoundSprite::getHeight(); } - static void load(); - static void unload(); protected: - /** - * Notify self that the stun mode has been updated. Invoked by - * setStunMode if something changed. - */ - virtual void updateStunMode(int oldMode, int newMode); - - /** - * Notify self that a status effect has flipped. - * The new flag is passed. - */ - virtual void updateStatusEffect(int index, bool newStatus); - - /** - * Handle an update to a status or stun effect - * - * \param effect The StatusEffect to effect - * \param effectId -1 for stun, otherwise the effect index - */ - virtual void handleStatusEffect(StatusEffect *effect, int effectId); - void setupSpriteDisplay(const SpriteDisplay &display, bool forceDisplay = true); int mId; - uint16_t mStunMode = 0; /**< Stun mode; zero if not stunned */ - std::set<int> mStatusEffects; /**< set of active status effects */ - - ParticleList mStunParticleEffects; - ParticleVector mStatusParticleEffects; ParticleList mChildParticleEffects; private: - /** Reset particle status effects on next redraw? */ - bool mMustResetParticles = false; - /** Load the target cursors into memory */ static void initTargetCursor(); diff --git a/src/being.cpp b/src/being.cpp index e62ac0e8..567850a5 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -36,6 +36,7 @@ #include "party.h" #include "playerrelations.h" #include "sound.h" +#include "statuseffect.h" #include "text.h" #include "gui/gui.h" @@ -60,9 +61,9 @@ #include <cmath> -Being::Being(int id, Type type, int subtype, Map *map): - ActorSprite(id), - mInfo(BeingInfo::Unknown) +Being::Being(int id, Type type, int subtype, Map *map) + : ActorSprite(id) + , mInfo(BeingInfo::Unknown) { setMap(map); setType(type, subtype); @@ -593,7 +594,67 @@ void Being::fireMissile(Being *victim, const std::string &particle) missile->setDieDistance(8); missile->setLifetime(900); } +} + +void Being::setStatusEffect(int index, bool active) +{ + const bool wasActive = mStatusEffects.find(index) != mStatusEffects.end(); + + if (active != wasActive) + { + updateStatusEffect(index, active); + if (active) + mStatusEffects.insert(index); + else + mStatusEffects.erase(index); + } +} + +void Being::setStatusEffectBlock(int offset, uint16_t newEffects) +{ + for (int i = 0; i < STATUS_EFFECTS; i++) + { + int index = StatusEffect::blockEffectIndexToEffectIndex(offset + i); + + if (index != -1) + setStatusEffect(index, (newEffects & (1 << i)) > 0); + } +} +void Being::updateStunMode(int oldMode, int newMode) +{ + handleStatusEffect(StatusEffect::getStatusEffect(oldMode, false), -1); + handleStatusEffect(StatusEffect::getStatusEffect(newMode, true), -1); +} + +void Being::updateStatusEffect(int index, bool newStatus) +{ + handleStatusEffect(StatusEffect::getStatusEffect(index, newStatus), index); +} + +void Being::handleStatusEffect(StatusEffect *effect, int effectId) +{ + if (!effect) + return; + + // TODO: Find out how this is meant to be used + // (SpriteAction != Being::Action) + //SpriteAction action = effect->getAction(); + //if (action != ACTION_INVALID) + // setAction(action); + + Particle *particle = effect->getParticle(); + + if (effectId >= 0) + { + mStatusParticleEffects.setLocally(effectId, particle); + } + else + { + mStunParticleEffects.clearLocally(); + if (particle) + mStunParticleEffects.addLocally(particle); + } } void Being::setAction(Action action, int attackId) @@ -784,10 +845,19 @@ void Being::logic() mText = nullptr; } - if (mRestoreSpriteParticlesOnLogic) + if (mRestoreParticlesOnLogic) { - mRestoreSpriteParticlesOnLogic = false; + mRestoreParticlesOnLogic = false; + restoreAllSpriteParticles(); + + // Restart status/particle effects, if needed + for (int statusEffect : mStatusEffects) + { + const StatusEffect *effect = StatusEffect::getStatusEffect(statusEffect, true); + if (effect && effect->particleEffectIsPersistent()) + updateStatusEffect(statusEffect, true); + } } if (mAction != DEAD && !mSpeedPixelsPerSecond.isNull()) @@ -1361,7 +1431,10 @@ void Being::setMap(Map *map) for (auto &spriteState : mSpriteStates) spriteState.particles.clear(); - mRestoreSpriteParticlesOnLogic = true; + mStunParticleEffects.clearLocally(); + mStatusParticleEffects.clearLocally(); + + mRestoreParticlesOnLogic = true; ActorSprite::setMap(map); diff --git a/src/being.h b/src/being.h index 4a29c739..aaf4c459 100644 --- a/src/being.h +++ b/src/being.h @@ -32,7 +32,9 @@ #include <guichan/color.hpp> +#include <cstdint> #include <map> +#include <set> #include <string> #include <vector> @@ -379,6 +381,27 @@ class Being : public ActorSprite, public EventListener void fireMissile(Being *target, const std::string &particle); /** + * Sets the being's stun mode. If zero, the being is `normal', + * otherwise it is `stunned' in some fashion. + */ + void setStunMode(int stunMode) + { + if (mStunMode != stunMode) + updateStunMode(mStunMode, stunMode); + mStunMode = stunMode; + } + + void setStatusEffect(int index, bool active); + + /** + * 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(int offset, uint16_t flags); + + /** * Returns the path this being is following. An empty path is returned * when this being isn't following any path currently. */ @@ -473,6 +496,18 @@ class Being : public ActorSprite, public EventListener */ virtual void pathFinished() {} + /** + * Notify self that the stun mode has been updated. Invoked by + * setStunMode if something changed. + */ + virtual void updateStunMode(int oldMode, int newMode); + + /** + * Notify self that a status effect has flipped. + * The new flag is passed. + */ + virtual void updateStatusEffect(int index, bool newStatus); + const BeingInfo *mInfo; Timer mActionTimer; /**< Time spent in current action. TODO: Remove use of it */ @@ -508,7 +543,7 @@ class Being : public ActorSprite, public EventListener Vector mDest; /**< destination coordinates. */ std::vector<SpriteState> mSpriteStates; - bool mRestoreSpriteParticlesOnLogic = false; + bool mRestoreParticlesOnLogic = false; Gender mGender = Gender::UNSPECIFIED; @@ -519,10 +554,23 @@ class Being : public ActorSprite, public EventListener bool mIsGM = false; private: + /** + * Handle an update to a status or stun effect + * + * \param effect The StatusEffect to effect + * \param effectId -1 for stun, otherwise the effect index + */ + void handleStatusEffect(StatusEffect *effect, int effectId); + void updateMovement(); Type mType = UNKNOWN; + uint16_t mStunMode = 0; /**< Stun mode; zero if not stunned */ + std::set<int> mStatusEffects; /**< set of active status effects */ + ParticleList mStunParticleEffects; + ParticleVector mStatusParticleEffects; + /** Speech Bubble components */ SpeechBubble *mSpeechBubble; diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index 76039bbd..cdf6cecd 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -94,19 +94,15 @@ bool CompoundSprite::draw(Graphics *graphics, int posX, int posY) const if (mAlpha && mAlphaImage) { - if (mAlphaImage->getAlpha() != mAlpha) - mAlphaImage->setAlpha(mAlpha); - - return graphics->drawImage(mAlphaImage, - posX, posY); + mAlphaImage->setAlpha(mAlpha); + return graphics->drawImage(mAlphaImage, posX, posY); } for (auto sprite : mSprites) { if (sprite) { - if (sprite->getAlpha() != mAlpha) - sprite->setAlpha(mAlpha); + sprite->setAlpha(mAlpha); sprite->draw(graphics, posX - sprite->getWidth() / 2, posY - sprite->getHeight()); } } diff --git a/src/localplayer.cpp b/src/localplayer.cpp index e2af5fa3..0813d7fc 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -932,7 +932,7 @@ bool LocalPlayer::withinRange(Actor *target, int range) const const Vector &pos = getPosition(); const int dx = abs(targetPos.x - pos.x); const int dy = abs(targetPos.y - pos.y); - return !(dx > range || dy > range); + return dx <= range && dy <= range; } void LocalPlayer::setGotoTarget(Being *target) @@ -1018,6 +1018,26 @@ void LocalPlayer::event(Event::Channel channel, const Event &event) Being::event(channel, event); } +void LocalPlayer::updateStunMode(int oldMode, int newMode) +{ + Event event(Event::Stun); + event.setInt("oldMode", oldMode); + event.setInt("newMode", newMode); + event.trigger(Event::ActorSpriteChannel); + + Being::updateStunMode(oldMode, newMode); +} + +void LocalPlayer::updateStatusEffect(int index, bool newStatus) +{ + Event event(Event::UpdateStatusEffect); + event.setInt("index", index); + event.setBool("newStatus", newStatus); + event.trigger(Event::ActorSpriteChannel); + + Being::updateStatusEffect(index, newStatus); +} + void LocalPlayer::changeAwayMode() { mAwayMode = !mAwayMode; diff --git a/src/localplayer.h b/src/localplayer.h index c88faaea..7d358f1c 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -184,6 +184,9 @@ class LocalPlayer final : public Being void event(Event::Channel channel, const Event &event) override; protected: + void updateStunMode(int oldMode, int newMode) override; + void updateStatusEffect(int index, bool newStatus) override; + /** Make the character starts to walk. */ void startWalking(unsigned char dir); |