summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-02-17 13:10:20 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-02-21 15:47:08 +0100
commit0d47dfbb0f7425db9ec8d10f9d4efbbd7daa9f24 (patch)
treeb6d5761900fff24d10247ac8c333f90885f320e9
parentd43e93d4f10769d86d2c1a6e8fc62af83812d672 (diff)
downloadmana-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.h14
-rw-r--r--src/actorsprite.cpp101
-rw-r--r--src/actorsprite.h61
-rw-r--r--src/being.cpp85
-rw-r--r--src/being.h50
-rw-r--r--src/compoundsprite.cpp10
-rw-r--r--src/localplayer.cpp22
-rw-r--r--src/localplayer.h3
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);