summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actorsprite.cpp8
-rw-r--r--src/being.cpp97
-rw-r--r--src/being.h22
-rw-r--r--src/particlecontainer.cpp4
-rw-r--r--src/resources/itemdb.cpp9
-rw-r--r--src/resources/iteminfo.h1
6 files changed, 104 insertions, 37 deletions
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp
index e279ba5f..62c5d1dc 100644
--- a/src/actorsprite.cpp
+++ b/src/actorsprite.cpp
@@ -235,8 +235,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
for (const auto &sprite : display.sprites)
{
std::string file = paths.getStringValue("sprites") + sprite.sprite;
- int variant = sprite.variant;
- addSprite(AnimatedSprite::load(file, variant));
+ addSprite(AnimatedSprite::load(file, sprite.variant));
}
// Ensure that something is shown, if desired
@@ -268,10 +267,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
if (Particle::enabled)
{
for (const auto &particle : display.particles)
- {
- Particle *p = particleEngine->addEffect(particle, 0, 0);
- controlParticle(p);
- }
+ controlParticle(particleEngine->addEffect(particle, 0, 0));
}
mMustResetParticles = true;
diff --git a/src/being.cpp b/src/being.cpp
index 0e344873..c9eee2c6 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -91,6 +91,8 @@ Being::~Being()
mSpeechBubble = nullptr;
mDispName = nullptr;
mText = nullptr;
+
+ removeAllSpriteParticles();
}
void Being::setSubtype(Uint16 subtype)
@@ -765,6 +767,12 @@ void Being::logic()
mText = nullptr;
}
+ if (mRestoreSpriteParticlesOnLogic)
+ {
+ mRestoreSpriteParticlesOnLogic = false;
+ restoreAllSpriteParticles();
+ }
+
if ((mAction != DEAD) && !mSpeedPixelsPerTick.isNull())
{
const Vector dest = (mPath.empty()) ?
@@ -979,6 +987,45 @@ void Being::showName()
updateCoords();
}
+void Being::addSpriteParticles(SpriteState &spriteState, const SpriteDisplay &display)
+{
+ if (!spriteState.particles.empty())
+ return;
+
+ for (const auto &particle : display.particles)
+ {
+ Particle *p = particleEngine->addEffect(particle, 0, 0, 0);
+ controlParticle(p);
+ spriteState.particles.push_back(p);
+ }
+}
+
+void Being::removeSpriteParticles(SpriteState &spriteState)
+{
+ for (auto particle : spriteState.particles)
+ mChildParticleEffects.removeLocally(particle);
+
+ spriteState.particles.clear();
+}
+
+void Being::removeAllSpriteParticles()
+{
+ for (auto &spriteState : mSpriteStates)
+ removeSpriteParticles(spriteState);
+}
+
+void Being::restoreAllSpriteParticles()
+{
+ for (auto &spriteState : mSpriteStates)
+ {
+ if (spriteState.id)
+ {
+ auto &itemInfo = itemDb->get(spriteState.id);
+ addSpriteParticles(spriteState, itemInfo.display);
+ }
+ }
+}
+
void Being::updateColors()
{
if (getType() == MONSTER)
@@ -1021,20 +1068,25 @@ void Being::updateColors()
}
}
-void Being::setSprite(unsigned int slot, int id, const std::string &color,
+void Being::setSprite(unsigned slot, int id, const std::string &color,
bool isWeapon)
{
if (slot >= size())
ensureSize(slot + 1);
- if (slot >= mSpriteIDs.size())
- mSpriteIDs.resize(slot + 1);
+ if (slot >= mSpriteStates.size())
+ mSpriteStates.resize(slot + 1);
+
+ auto &spriteState = mSpriteStates[slot];
+
+ // Clear current particles when the ID changes
+ if (spriteState.id != id)
+ removeSpriteParticles(spriteState);
- if (slot >= mSpriteColors.size())
- mSpriteColors.resize(slot + 1);
+ spriteState.id = id;
+ spriteState.color = color;
- // id = 0 means unequip
- if (id == 0)
+ if (id == 0) // id = 0 means unequip
{
removeSprite(slot);
@@ -1043,7 +1095,8 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color,
}
else
{
- std::string filename = itemDb->get(id).getSprite(mGender, mSubType);
+ auto &itemInfo = itemDb->get(id);
+ std::string filename = itemInfo.getSprite(mGender, mSubType);
AnimatedSprite *equipmentSprite = nullptr;
if (!filename.empty())
@@ -1060,24 +1113,25 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color,
CompoundSprite::setSprite(slot, equipmentSprite);
+ addSpriteParticles(spriteState, itemInfo.display);
+
if (isWeapon)
- mEquippedWeapon = &itemDb->get(id);
+ mEquippedWeapon = &itemInfo;
setAction(mAction);
}
-
- mSpriteIDs[slot] = id;
- mSpriteColors[slot] = color;
}
-void Being::setSpriteID(unsigned int slot, int id)
+void Being::setSpriteID(unsigned slot, int id)
{
- setSprite(slot, id, mSpriteColors[slot]);
+ assert(slot < mSpriteStates.size());
+ setSprite(slot, id, mSpriteStates[slot].color);
}
-void Being::setSpriteColor(unsigned int slot, const std::string &color)
+void Being::setSpriteColor(unsigned slot, const std::string &color)
{
- setSprite(slot, mSpriteIDs[slot], color);
+ assert(slot < mSpriteStates.size());
+ setSprite(slot, mSpriteStates[slot].id, color);
}
int Being::getNumberOfLayers() const
@@ -1098,10 +1152,11 @@ void Being::setGender(Gender gender)
mGender = gender;
// Reload all subsprites
- for (unsigned int i = 0; i < mSpriteIDs.size(); i++)
+ for (size_t i = 0; i < mSpriteStates.size(); i++)
{
- if (mSpriteIDs.at(i) != 0)
- setSprite(i, mSpriteIDs.at(i), mSpriteColors.at(i));
+ auto &sprite = mSpriteStates[i];
+ if (sprite.id != 0)
+ setSprite(i, sprite.id, sprite.color);
}
updateName();
@@ -1155,6 +1210,10 @@ void Being::event(Event::Channel channel, const Event &event)
void Being::setMap(Map *map)
{
+ // Remove sprite particles because ActorSprite is going to kill them all
+ removeAllSpriteParticles();
+ mRestoreSpriteParticlesOnLogic = true;
+
ActorSprite::setMap(map);
// Recalculate pixel/tick speed
diff --git a/src/being.h b/src/being.h
index 0c1d54d6..3bd66b06 100644
--- a/src/being.h
+++ b/src/being.h
@@ -259,13 +259,13 @@ class Being : public ActorSprite, public EventListener
/**
* Sets visible equipments for this being.
*/
- void setSprite(unsigned int slot, int id,
+ void setSprite(unsigned slot, int id,
const std::string &color = std::string(),
bool isWeapon = false);
- void setSpriteID(unsigned int slot, int id);
+ void setSpriteID(unsigned slot, int id);
- void setSpriteColor(unsigned int slot,
+ void setSpriteColor(unsigned slot,
const std::string &color = std::string());
/**
@@ -452,6 +452,12 @@ class Being : public ActorSprite, public EventListener
{ lookAt(Vector(destPos.x, destPos.y)); }
protected:
+ struct SpriteState {
+ int id = 0;
+ std::string color;
+ std::vector<Particle*> particles;
+ };
+
/**
* Sets the new path for this being.
*/
@@ -464,6 +470,11 @@ class Being : public ActorSprite, public EventListener
void showName();
+ void addSpriteParticles(SpriteState &spriteState, const SpriteDisplay &display);
+ void removeSpriteParticles(SpriteState &spriteState);
+ void removeAllSpriteParticles();
+ void restoreAllSpriteParticles();
+
void updateColors();
/**
@@ -505,8 +516,9 @@ class Being : public ActorSprite, public EventListener
Vector mDest; /**< destination coordinates. */
- std::vector<int> mSpriteIDs;
- std::vector<std::string> mSpriteColors;
+ std::vector<SpriteState> mSpriteStates;
+ bool mRestoreSpriteParticlesOnLogic = false;
+
Gender mGender = Gender::UNSPECIFIED;
// Character guild information
diff --git a/src/particlecontainer.cpp b/src/particlecontainer.cpp
index 9dfb8585..60485c44 100644
--- a/src/particlecontainer.cpp
+++ b/src/particlecontainer.cpp
@@ -70,9 +70,7 @@ void ParticleList::addLocally(Particle *particle)
void ParticleList::removeLocally(Particle *particle)
{
- std::list<Particle *>::iterator it, it_end;
- for (it = mElements.begin(), it_end = mElements.end();
- it != it_end;)
+ for (auto it = mElements.begin(), it_end = mElements.end(); it != it_end;)
{
if (*it == particle)
{
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 543caf8a..bb5b5abd 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -216,11 +216,14 @@ void ItemDB::loadCommonRef(ItemInfo &itemInfo, xmlNodePtr node, const std::strin
{
if (xmlStrEqual(itemChild->name, BAD_CAST "sprite"))
{
- itemInfo.particle = XML::getProperty(
- itemChild, "particle-effect", std::string());
-
loadSpriteRef(itemInfo, itemChild);
}
+ else if (xmlStrEqual(itemChild->name, BAD_CAST "particlefx"))
+ {
+ if (itemChild->children && itemChild->children->content)
+ itemInfo.display.particles.emplace_back(
+ (const char*)itemChild->children->content);
+ }
else if (xmlStrEqual(itemChild->name, BAD_CAST "sound"))
{
loadSoundRef(itemInfo, itemChild);
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index 90a70695..a5b62fdc 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -86,7 +86,6 @@ public:
int id = 0; /**< Item ID */
std::string name;
- std::string particle; /**< Particle effect used with this item */
SpriteDisplay display; /**< Display info (like icon) */
std::string description; /**< Short description. */
std::vector<std::string> effect; /**< Description of effects. */