summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/actormanager.cpp15
-rw-r--r--src/actormanager.h2
-rw-r--r--src/being/actorsprite.cpp27
-rw-r--r--src/being/actorsprite.h11
-rw-r--r--src/being/being.cpp6
-rw-r--r--src/being/localplayer.cpp2
-rw-r--r--src/effectmanager.cpp4
-rw-r--r--src/particle/particle.cpp11
-rw-r--r--src/particle/particle.h7
-rw-r--r--src/particle/particlelist.cpp5
10 files changed, 77 insertions, 13 deletions
diff --git a/src/actormanager.cpp b/src/actormanager.cpp
index 7da8249b0..bee73cd05 100644
--- a/src/actormanager.cpp
+++ b/src/actormanager.cpp
@@ -405,6 +405,21 @@ Being *ActorManager::findBeing(const BeingId id) const
return nullptr;
}
+ActorSprite *ActorManager::findActor(const BeingId id) const
+{
+ const ActorSpritesMapConstIterator it = mActorsIdMap.find(id);
+ if (it != mActorsIdMap.end())
+ {
+ ActorSprite *const actor = (*it).second;
+ if (actor &&
+ actor->getId() == id)
+ {
+ return actor;
+ }
+ }
+ return nullptr;
+}
+
Being *ActorManager::findBeing(const int x, const int y,
const ActorTypeT type) const
{
diff --git a/src/actormanager.h b/src/actormanager.h
index 7ab4b1d67..ad53ff729 100644
--- a/src/actormanager.h
+++ b/src/actormanager.h
@@ -124,6 +124,8 @@ class ActorManager final: public ConfigListener
*/
Being *findBeing(const BeingId id) const A_WARN_UNUSED;
+ ActorSprite *findActor(const BeingId id) const A_WARN_UNUSED;
+
/**
* Returns a being at specific coordinates.
*/
diff --git a/src/being/actorsprite.cpp b/src/being/actorsprite.cpp
index f0dfc07ec..3a9c457a4 100644
--- a/src/being/actorsprite.cpp
+++ b/src/being/actorsprite.cpp
@@ -33,6 +33,7 @@
#include "listeners/debugmessagelistener.h"
+#include "particle/particle.h"
#include "particle/particleengine.h"
#include "resources/db/statuseffectdb.h"
@@ -141,9 +142,29 @@ void ActorSprite::setMap(Map *const map)
mMustResetParticles = true; // Reset status particles on next redraw
}
-void ActorSprite::controlParticle(Particle *const particle)
+void ActorSprite::controlAutoParticle(Particle *const particle)
{
- mChildParticleEffects.addLocally(particle);
+ if (particle)
+ {
+ particle->setActor(mId);
+ mChildParticleEffects.addLocally(particle);
+ }
+}
+
+void ActorSprite::controlCustomParticle(Particle *const particle)
+{
+ if (particle)
+ {
+ // The effect may not die without the beings permission or we segfault
+ particle->disableAutoDelete();
+ mChildParticleEffects.addLocally(particle);
+ }
+}
+
+void ActorSprite::controlParticleDeleted(Particle *const particle)
+{
+ if (particle)
+ mChildParticleEffects.removeLocally(particle);
}
void ActorSprite::setTargetType(const TargetCursorTypeT type)
@@ -456,7 +477,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
FOR_EACH (StringVectCIter, itr, display.particles)
{
Particle *const p = particleEngine->addEffect(*itr, 0, 0);
- controlParticle(p);
+ controlAutoParticle(p);
}
}
diff --git a/src/being/actorsprite.h b/src/being/actorsprite.h
index 6f5c020c2..c06f1c983 100644
--- a/src/being/actorsprite.h
+++ b/src/being/actorsprite.h
@@ -81,9 +81,14 @@ class ActorSprite notfinal : public CompoundSprite, public Actor
{ return BlockType::NONE; }
/**
- * Take control of a particle.
+ * Take control of a particle. Particle can be auto deleted.
*/
- void controlParticle(Particle *const particle);
+ 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.
@@ -190,6 +195,8 @@ class ActorSprite notfinal : public CompoundSprite, public Actor
mChildParticleEffects.size();
}
+ void controlParticleDeleted(Particle *const particle);
+
protected:
/**
* A status effect block is a 16 bit mask of status effects. We assign
diff --git a/src/being/being.cpp b/src/being/being.cpp
index b5732b15f..0cf52c353 100644
--- a/src/being/being.cpp
+++ b/src/being/being.cpp
@@ -1349,7 +1349,7 @@ void Being::fireMissile(Being *restrict const victim,
{
target->moveBy(Vector(0.0F, 0.0F, 32.0F));
target->setLifetime(1000);
- victim->controlParticle(target);
+ victim->controlAutoParticle(target);
missile->setDestination(target, 7, 0);
missile->setDieDistance(8);
@@ -4849,7 +4849,7 @@ void Being::addItemParticles(const int id,
FOR_EACH (StringVectCIter, itr, display.particles)
{
Particle *const p = particleEngine->addEffect(*itr, 0, 0);
- controlParticle(p);
+ controlCustomParticle(p);
pi->files.push_back(*itr);
pi->particles.push_back(p);
}
@@ -4893,7 +4893,7 @@ void Being::recreateItemParticles() restrict2
{
Particle *const p = particleEngine->addEffect(
*str, 0, 0);
- controlParticle(p);
+ controlCustomParticle(p);
pi->particles.push_back(p);
}
}
diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp
index 25699f704..e065fafe4 100644
--- a/src/being/localplayer.cpp
+++ b/src/being/localplayer.cpp
@@ -2709,7 +2709,7 @@ void LocalPlayer::setTestParticle(const std::string &fileName,
if (!fileName.empty())
{
mTestParticle = particleEngine->addEffect(fileName, 0, 0, 0);
- controlParticle(mTestParticle);
+ controlCustomParticle(mTestParticle);
if (updateHash)
mTestParticleHash = UpdaterWindow::getFileHash(mTestParticleName);
}
diff --git a/src/effectmanager.cpp b/src/effectmanager.cpp
index feec7ae98..7ed51092d 100644
--- a/src/effectmanager.cpp
+++ b/src/effectmanager.cpp
@@ -134,7 +134,7 @@ bool EffectManager::trigger(const int id,
{
Particle *const selfFX = particleEngine->addEffect(
effect.gfx, 0, 0, rotation);
- being->controlParticle(selfFX);
+ being->controlAutoParticle(selfFX);
}
if (!effect.sfx.empty())
soundManager.playSfx(effect.sfx);
@@ -165,7 +165,7 @@ Particle *EffectManager::triggerReturn(const int id,
{
rValue = particleEngine->addEffect(
effect.gfx, 0, 0, rotation);
- being->controlParticle(rValue);
+ being->controlCustomParticle(rValue);
}
if (!effect.sfx.empty())
soundManager.playSfx(effect.sfx);
diff --git a/src/particle/particle.cpp b/src/particle/particle.cpp
index 4e7b154c0..a04cee6f3 100644
--- a/src/particle/particle.cpp
+++ b/src/particle/particle.cpp
@@ -22,8 +22,11 @@
#include "particle/particle.h"
+#include "actormanager.h"
#include "logger.h"
+#include "being/actorsprite.h"
+
#include "particle/animationparticle.h"
#include "particle/particleemitter.h"
#include "particle/rotationalparticle.h"
@@ -61,6 +64,7 @@ Particle::Particle() :
mType(ParticleType::Normal),
mAnimation(nullptr),
mImage(nullptr),
+ mActor(BeingId_zero),
mChildEmitters(),
mChildParticles(),
mChildMoveParticles(),
@@ -82,6 +86,13 @@ Particle::Particle() :
Particle::~Particle()
{
+ if (mActor != BeingId_zero &&
+ actorManager)
+ {
+ ActorSprite *const actor = actorManager->findActor(mActor);
+ if (actor)
+ actor->controlParticleDeleted(this);
+ }
// Delete child emitters and child particles
clear();
delete2(mAnimation);
diff --git a/src/particle/particle.h b/src/particle/particle.h
index f1a8154b6..859a61505 100644
--- a/src/particle/particle.h
+++ b/src/particle/particle.h
@@ -28,6 +28,8 @@
#include "enums/particle/alivestatus.h"
#include "enums/particle/particletype.h"
+#include "enums/simpletypes/beingid.h"
+
#include "particle/particleengine.h"
#include "localconsts.h"
@@ -238,6 +240,9 @@ class Particle notfinal : public Actor
const signed char conditions) restrict2
{ mDeathEffect = effectFile; mDeathEffectConditions = conditions; }
+ void setActor(const BeingId actor)
+ { mActor = actor; }
+
protected:
void updateSelf() restrict2;
@@ -270,6 +275,8 @@ class Particle notfinal : public Actor
/**< The image used for this particle. */
Image *restrict mImage;
+ BeingId mActor;
+
private:
// List of child emitters.
Emitters mChildEmitters;
diff --git a/src/particle/particlelist.cpp b/src/particle/particlelist.cpp
index 0d2a2f195..209ecfd32 100644
--- a/src/particle/particlelist.cpp
+++ b/src/particle/particlelist.cpp
@@ -44,8 +44,6 @@ void ParticleList::addLocally(Particle *const particle)
{
if (particle)
{
- // The effect may not die without the beings permission or we segfault
- particle->disableAutoDelete();
mElements.push_back(particle);
mSize ++;
}
@@ -74,7 +72,10 @@ void ParticleList::removeLocally(const Particle *const particle)
void ParticleList::clearLocally()
{
FOR_EACH (ParticleListCIter, it, mElements)
+ {
(*it)->kill();
+ (*it)->prepareToDie();
+ }
mElements.clear();
mSize = 0U;