Implement effect removal for abilities (Fixes #3455)

pull/1/head
MiroslavR 8 years ago
parent 252b27f0ef
commit 54f52f7bae

@ -121,7 +121,7 @@ public:
{
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel;
mContext->mPlayerBase = npc;
std::map<int, float> empty;
ESM::SpellState::SpellParams empty;
// FIXME: player start spells and birthsign spells aren't listed here,
// 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)

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

@ -66,7 +66,9 @@ namespace MWMechanics
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;
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;
if (iter->second.find(i) != iter->second.end())
random = iter->second.at(i);
if (iter->second.mEffectRands.find(i) != iter->second.mEffectRands.end())
random = iter->second.mEffectRands.at(i);
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random);
++i;
@ -259,9 +264,12 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
effectIt != list.mList.end(); ++effectIt, ++i)
{
if (it->second.mPurgedEffects.find(i) != it->second.mPurgedEffects.end())
continue; // effect was purged
float random = 1.f;
if (it->second.find(i) != it->second.end())
random = it->second.at(i);
if (it->second.mEffectRands.find(i) != it->second.mEffectRands.end())
random = it->second.mEffectRands.at(i);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
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
{
float random = 1.f;
if (mSpells[spell].find(i) != mSpells[spell].end())
random = mSpells[spell].at(i);
if (mSpells[spell].mEffectRands.find(i) != mSpells[spell].mEffectRands.end())
random = mSpells[spell].mEffectRands.at(i);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
magnitude *= std::max(1, mCorprusSpells[spell].mWorsenings);
@ -310,6 +318,36 @@ namespace MWMechanics
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
{
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);
if (spell)
{
mSpells[spell] = it->second;
mSpells[spell].mEffectRands = it->second.mEffectRands;
mSpells[spell].mPurgedEffects = it->second.mPurgedEffects;
if (it->first == state.mSelectedSpell)
mSelectedSpell = it->first;
@ -375,7 +414,12 @@ namespace MWMechanics
void Spells::writeState(ESM::SpellState &state) const
{
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;

@ -3,6 +3,7 @@
#include <map>
#include <string>
#include <set>
#include <components/misc/stringops.hpp>
@ -32,8 +33,12 @@ namespace MWMechanics
public:
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;
struct CorprusStats
@ -67,6 +72,9 @@ namespace MWMechanics
static bool hasCorprusEffect(const ESM::Spell *spell);
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;
void usePower (const ESM::Spell* spell);

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

@ -12,7 +12,7 @@ namespace ESM
{
std::string id = esm.getHString();
std::map<int, float> random;
SpellParams state;
while (esm.isNextSub("INDX"))
{
int index;
@ -21,10 +21,16 @@ namespace ESM
float magnitude;
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"))
@ -73,12 +79,16 @@ namespace ESM
{
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)
{
esm.writeHNT("INDX", rIt->first);
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)

@ -4,6 +4,7 @@
#include <map>
#include <vector>
#include <string>
#include <set>
#include "defs.hpp"
@ -28,7 +29,11 @@ namespace ESM
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;
std::map<std::string, std::vector<PermanentSpellEffectInfo> > mPermanentSpellEffects;

Loading…
Cancel
Save