Implement effect removal for abilities (Fixes #3455)

coverity_scan^2
MiroslavR 9 years ago
parent 252b27f0ef
commit 54f52f7bae

@ -121,7 +121,7 @@ public:
{ {
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel; mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel;
mContext->mPlayerBase = npc; mContext->mPlayerBase = npc;
std::map<int, float> empty; ESM::SpellState::SpellParams empty;
// FIXME: player start spells and birthsign spells aren't listed here, // FIXME: player start spells and birthsign spells aren't listed here,
// need to fix openmw to account for this // need to fix openmw to account for this
for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it) for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it)

@ -513,6 +513,7 @@ namespace MWMechanics
CastSpell cast(ptr, ptr); CastSpell cast(ptr, ptr);
if (cast.applyInstantEffect(ptr, ptr, it->first, it->second.getMagnitude())) if (cast.applyInstantEffect(ptr, ptr, it->first, it->second.getMagnitude()))
{ {
creatureStats.getSpells().purgeEffect(it->first.mId);
creatureStats.getActiveSpells().purgeEffect(it->first.mId); creatureStats.getActiveSpells().purgeEffect(it->first.mId);
if (ptr.getClass().hasInventoryStore(ptr)) if (ptr.getClass().hasInventoryStore(ptr))
ptr.getClass().getInventoryStore(ptr).purgeEffect(it->first.mId); ptr.getClass().getInventoryStore(ptr).purgeEffect(it->first.mId);

@ -66,7 +66,9 @@ namespace MWMechanics
mCorprusSpells[spell] = corprus; mCorprusSpells[spell] = corprus;
} }
mSpells.insert (std::make_pair (spell, random)); SpellParams params;
params.mEffectRands = random;
mSpells.insert (std::make_pair (spell, params));
} }
} }
@ -124,9 +126,12 @@ namespace MWMechanics
int i=0; int i=0;
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
{ {
if (iter->second.mPurgedEffects.find(i) != iter->second.mPurgedEffects.end())
continue; // effect was purged
float random = 1.f; float random = 1.f;
if (iter->second.find(i) != iter->second.end()) if (iter->second.mEffectRands.find(i) != iter->second.mEffectRands.end())
random = iter->second.at(i); random = iter->second.mEffectRands.at(i);
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random); effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random);
++i; ++i;
@ -259,9 +264,12 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin(); for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
effectIt != list.mList.end(); ++effectIt, ++i) effectIt != list.mList.end(); ++effectIt, ++i)
{ {
if (it->second.mPurgedEffects.find(i) != it->second.mPurgedEffects.end())
continue; // effect was purged
float random = 1.f; float random = 1.f;
if (it->second.find(i) != it->second.end()) if (it->second.mEffectRands.find(i) != it->second.mEffectRands.end())
random = it->second.at(i); random = it->second.mEffectRands.at(i);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, spell->mId, -1, magnitude); visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, spell->mId, -1, magnitude);
@ -283,8 +291,8 @@ namespace MWMechanics
if ((effectIt->mEffectID != ESM::MagicEffect::Corprus) && (magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE if ((effectIt->mEffectID != ESM::MagicEffect::Corprus) && (magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE
{ {
float random = 1.f; float random = 1.f;
if (mSpells[spell].find(i) != mSpells[spell].end()) if (mSpells[spell].mEffectRands.find(i) != mSpells[spell].mEffectRands.end())
random = mSpells[spell].at(i); random = mSpells[spell].mEffectRands.at(i);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
magnitude *= std::max(1, mCorprusSpells[spell].mWorsenings); magnitude *= std::max(1, mCorprusSpells[spell].mWorsenings);
@ -310,6 +318,36 @@ namespace MWMechanics
return mCorprusSpells; return mCorprusSpells;
} }
void Spells::purgeEffect(int effectId)
{
for (TContainer::iterator spellIt = mSpells.begin(); spellIt != mSpells.end(); ++spellIt)
{
int i = 0;
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
{
if (effectIt->mEffectID == effectId)
spellIt->second.mPurgedEffects.insert(i);
++i;
}
}
}
void Spells::purgeEffect(int effectId, const std::string & sourceId)
{
const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(sourceId);
TContainer::iterator spellIt = mSpells.find(spell);
if (spellIt == mSpells.end())
return;
int i = 0;
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
{
if (effectIt->mEffectID == effectId)
spellIt->second.mPurgedEffects.insert(i);
++i;
}
}
bool Spells::canUsePower(const ESM::Spell* spell) const bool Spells::canUsePower(const ESM::Spell* spell) const
{ {
std::map<SpellKey, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.find(spell); std::map<SpellKey, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.find(spell);
@ -332,7 +370,8 @@ namespace MWMechanics
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first);
if (spell) if (spell)
{ {
mSpells[spell] = it->second; mSpells[spell].mEffectRands = it->second.mEffectRands;
mSpells[spell].mPurgedEffects = it->second.mPurgedEffects;
if (it->first == state.mSelectedSpell) if (it->first == state.mSelectedSpell)
mSelectedSpell = it->first; mSelectedSpell = it->first;
@ -375,7 +414,12 @@ namespace MWMechanics
void Spells::writeState(ESM::SpellState &state) const void Spells::writeState(ESM::SpellState &state) const
{ {
for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it) for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it)
state.mSpells.insert(std::make_pair(it->first->mId, it->second)); {
ESM::SpellState::SpellParams params;
params.mEffectRands = it->second.mEffectRands;
params.mPurgedEffects = it->second.mPurgedEffects;
state.mSpells.insert(std::make_pair(it->first->mId, params));
}
state.mSelectedSpell = mSelectedSpell; state.mSelectedSpell = mSelectedSpell;

@ -3,6 +3,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <set>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
@ -32,8 +33,12 @@ namespace MWMechanics
public: public:
typedef const ESM::Spell* SpellKey; typedef const ESM::Spell* SpellKey;
struct SpellParams {
std::map<int, float> mEffectRands; // <effect index, normalised random magnitude>
std::set<int> mPurgedEffects; // indices of purged effects
};
typedef std::map<SpellKey, std::map<int, float> > TContainer; // ID, <effect index, normalised random magnitude> typedef std::map<SpellKey, SpellParams> TContainer;
typedef TContainer::const_iterator TIterator; typedef TContainer::const_iterator TIterator;
struct CorprusStats struct CorprusStats
@ -67,6 +72,9 @@ namespace MWMechanics
static bool hasCorprusEffect(const ESM::Spell *spell); static bool hasCorprusEffect(const ESM::Spell *spell);
const std::map<SpellKey, CorprusStats> & getCorprusSpells() const; const std::map<SpellKey, CorprusStats> & getCorprusSpells() const;
void purgeEffect(int effectId);
void purgeEffect(int effectId, const std::string & sourceId);
bool canUsePower (const ESM::Spell* spell) const; bool canUsePower (const ESM::Spell* spell) const;
void usePower (const ESM::Spell* spell); void usePower (const ESM::Spell* spell);

@ -2687,6 +2687,7 @@ namespace MWWorld
void World::breakInvisibility(const Ptr &actor) void World::breakInvisibility(const Ptr &actor)
{ {
actor.getClass().getCreatureStats(actor).getSpells().purgeEffect(ESM::MagicEffect::Invisibility);
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility); actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility);
if (actor.getClass().hasInventoryStore(actor)) if (actor.getClass().hasInventoryStore(actor))
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility); actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility);

@ -12,7 +12,7 @@ namespace ESM
{ {
std::string id = esm.getHString(); std::string id = esm.getHString();
std::map<int, float> random; SpellParams state;
while (esm.isNextSub("INDX")) while (esm.isNextSub("INDX"))
{ {
int index; int index;
@ -21,10 +21,16 @@ namespace ESM
float magnitude; float magnitude;
esm.getHNT(magnitude, "RAND"); esm.getHNT(magnitude, "RAND");
random[index] = magnitude; state.mEffectRands[index] = magnitude;
} }
mSpells[id] = random; while (esm.isNextSub("PURG")) {
int index;
esm.getHT(index);
state.mPurgedEffects.insert(index);
}
mSpells[id] = state;
} }
while (esm.isNextSub("PERM")) while (esm.isNextSub("PERM"))
@ -73,12 +79,16 @@ namespace ESM
{ {
esm.writeHNString("SPEL", it->first); esm.writeHNString("SPEL", it->first);
const std::map<int, float>& random = it->second; const std::map<int, float>& random = it->second.mEffectRands;
for (std::map<int, float>::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt) for (std::map<int, float>::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt)
{ {
esm.writeHNT("INDX", rIt->first); esm.writeHNT("INDX", rIt->first);
esm.writeHNT("RAND", rIt->second); esm.writeHNT("RAND", rIt->second);
} }
const std::set<int>& purges = it->second.mPurgedEffects;
for (std::set<int>::const_iterator pIt = purges.begin(); pIt != purges.end(); ++pIt)
esm.writeHNT("PURG", *pIt);
} }
for (std::map<std::string, std::vector<PermanentSpellEffectInfo> >::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it) for (std::map<std::string, std::vector<PermanentSpellEffectInfo> >::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it)

@ -4,6 +4,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <string> #include <string>
#include <set>
#include "defs.hpp" #include "defs.hpp"
@ -28,7 +29,11 @@ namespace ESM
float mMagnitude; float mMagnitude;
}; };
typedef std::map<std::string, std::map<int, float> > TContainer; struct SpellParams {
std::map<int, float> mEffectRands;
std::set<int> mPurgedEffects;
};
typedef std::map<std::string, SpellParams> TContainer;
TContainer mSpells; TContainer mSpells;
std::map<std::string, std::vector<PermanentSpellEffectInfo> > mPermanentSpellEffects; std::map<std::string, std::vector<PermanentSpellEffectInfo> > mPermanentSpellEffects;

Loading…
Cancel
Save