Cache magic effects in MWMechanics::Spells

pull/1/head
MiroslavR 9 years ago
parent 700dde116e
commit c8b61cb234

@ -15,6 +15,11 @@
namespace MWMechanics namespace MWMechanics
{ {
Spells::Spells()
: mSpellsChanged(false)
{
}
Spells::TIterator Spells::begin() const Spells::TIterator Spells::begin() const
{ {
return mSpells.begin(); return mSpells.begin();
@ -30,6 +35,44 @@ namespace MWMechanics
return MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(id); return MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(id);
} }
void Spells::rebuildEffects() const
{
mEffects = MagicEffects();
mSourcedEffects.clear();
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
{
const ESM::Spell *spell = iter->first;
if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight ||
spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse)
{
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.mEffectRands.find(i) != iter->second.mEffectRands.end())
random = iter->second.mEffectRands.at(i);
float magnitude = it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random;
mEffects.add (*it, magnitude);
mSourcedEffects[spell].add(MWMechanics::EffectKey(*it), magnitude);
++i;
}
}
}
for (std::map<SpellKey, MagicEffects>::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it)
{
mEffects += it->second;
mSourcedEffects[it->first] += it->second;
}
}
bool Spells::hasSpell(const std::string &spell) const bool Spells::hasSpell(const std::string &spell) const
{ {
return hasSpell(getSpell(spell)); return hasSpell(getSpell(spell));
@ -69,6 +112,7 @@ namespace MWMechanics
SpellParams params; SpellParams params;
params.mEffectRands = random; params.mEffectRands = random;
mSpells.insert (std::make_pair (spell, params)); mSpells.insert (std::make_pair (spell, params));
mSpellsChanged = true;
} }
} }
@ -104,7 +148,10 @@ namespace MWMechanics
} }
if (iter!=mSpells.end()) if (iter!=mSpells.end())
{
mSpells.erase (iter); mSpells.erase (iter);
mSpellsChanged = true;
}
if (spellId==mSelectedSpell) if (spellId==mSelectedSpell)
mSelectedSpell.clear(); mSelectedSpell.clear();
@ -112,44 +159,17 @@ namespace MWMechanics
MagicEffects Spells::getMagicEffects() const MagicEffects Spells::getMagicEffects() const
{ {
// TODO: These are recalculated every frame, no need to do that if (mSpellsChanged) {
rebuildEffects();
MagicEffects effects; mSpellsChanged = false;
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
{
const ESM::Spell *spell = iter->first;
if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight ||
spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse)
{
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.mEffectRands.find(i) != iter->second.mEffectRands.end())
random = iter->second.mEffectRands.at(i);
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random);
++i;
}
}
}
for (std::map<SpellKey, MagicEffects>::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it)
{
effects += it->second;
} }
return mEffects;
return effects;
} }
void Spells::clear() void Spells::clear()
{ {
mSpells.clear(); mSpells.clear();
mSpellsChanged = true;
} }
void Spells::setSelectedSpell (const std::string& spellId) void Spells::setSelectedSpell (const std::string& spellId)
@ -205,7 +225,10 @@ namespace MWMechanics
{ {
const ESM::Spell *spell = iter->first; const ESM::Spell *spell = iter->first;
if (spell->mData.mType == ESM::Spell::ST_Disease) if (spell->mData.mType == ESM::Spell::ST_Disease)
{
mSpells.erase(iter++); mSpells.erase(iter++);
mSpellsChanged = true;
}
else else
++iter; ++iter;
} }
@ -217,7 +240,10 @@ namespace MWMechanics
{ {
const ESM::Spell *spell = iter->first; const ESM::Spell *spell = iter->first;
if (spell->mData.mType == ESM::Spell::ST_Blight && !hasCorprusEffect(spell)) if (spell->mData.mType == ESM::Spell::ST_Blight && !hasCorprusEffect(spell))
{
mSpells.erase(iter++); mSpells.erase(iter++);
mSpellsChanged = true;
}
else else
++iter; ++iter;
} }
@ -229,7 +255,10 @@ namespace MWMechanics
{ {
const ESM::Spell *spell = iter->first; const ESM::Spell *spell = iter->first;
if (hasCorprusEffect(spell)) if (hasCorprusEffect(spell))
{
mSpells.erase(iter++); mSpells.erase(iter++);
mSpellsChanged = true;
}
else else
++iter; ++iter;
} }
@ -241,7 +270,10 @@ namespace MWMechanics
{ {
const ESM::Spell *spell = iter->first; const ESM::Spell *spell = iter->first;
if (spell->mData.mType == ESM::Spell::ST_Curse) if (spell->mData.mType == ESM::Spell::ST_Curse)
{
mSpells.erase(iter++); mSpells.erase(iter++);
mSpellsChanged = true;
}
else else
++iter; ++iter;
} }
@ -249,45 +281,13 @@ namespace MWMechanics
void Spells::visitEffectSources(EffectSourceVisitor &visitor) const void Spells::visitEffectSources(EffectSourceVisitor &visitor) const
{ {
// needed to combine effects from mSpells and mPermanentSpellEffects, if (mSpellsChanged) {
// while still grouping them by their source spell rebuildEffects();
std::map<SpellKey, MagicEffects> combinedEffects; mSpellsChanged = false;
for (TIterator it = begin(); it != end(); ++it)
{
const ESM::Spell* spell = it->first;
// these are the spell types that are permanently in effect
if (!(spell->mData.mType == ESM::Spell::ST_Ability)
&& !(spell->mData.mType == ESM::Spell::ST_Disease)
&& !(spell->mData.mType == ESM::Spell::ST_Curse)
&& !(spell->mData.mType == ESM::Spell::ST_Blight))
continue;
const ESM::EffectList& list = spell->mEffects;
int i=0;
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.mEffectRands.find(i) != it->second.mEffectRands.end())
random = it->second.mEffectRands.at(i);
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
combinedEffects[spell].add(MWMechanics::EffectKey(*effectIt), magnitude);
}
}
for (std::map<SpellKey, MagicEffects>::const_iterator it = mPermanentSpellEffects.begin();
it != mPermanentSpellEffects.end(); ++it)
{
combinedEffects[it->first] += it->second;
} }
for (std::map<SpellKey, MagicEffects>::const_iterator it = combinedEffects.begin(); for (std::map<SpellKey, MagicEffects>::const_iterator it = mSourcedEffects.begin();
it != combinedEffects.end(); ++it) it != mSourcedEffects.end(); ++it)
{ {
const ESM::Spell * spell = it->first; const ESM::Spell * spell = it->first;
for (MagicEffects::Collection::const_iterator effectIt = it->second.begin(); for (MagicEffects::Collection::const_iterator effectIt = it->second.begin();
@ -318,6 +318,7 @@ namespace MWMechanics
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);
mPermanentSpellEffects[spell].add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(magnitude)); mPermanentSpellEffects[spell].add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(magnitude));
mSpellsChanged = true;
} }
} }
} }
@ -347,7 +348,10 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt) for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
{ {
if (effectIt->mEffectID == effectId) if (effectIt->mEffectID == effectId)
{
spellIt->second.mPurgedEffects.insert(i); spellIt->second.mPurgedEffects.insert(i);
mSpellsChanged = true;
}
++i; ++i;
} }
} }
@ -364,7 +368,10 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt) for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spellIt->first->mEffects.mList.begin(); effectIt != spellIt->first->mEffects.mList.end(); ++effectIt)
{ {
if (effectIt->mEffectID == effectId) if (effectIt->mEffectID == effectId)
{
spellIt->second.mPurgedEffects.insert(i); spellIt->second.mPurgedEffects.insert(i);
mSpellsChanged = true;
}
++i; ++i;
} }
} }
@ -430,6 +437,8 @@ namespace MWMechanics
mCorprusSpells[spell].mWorsenings = state.mCorprusSpells.at(it->first).mWorsenings; mCorprusSpells[spell].mWorsenings = state.mCorprusSpells.at(it->first).mWorsenings;
mCorprusSpells[spell].mNextWorsening = MWWorld::TimeStamp(state.mCorprusSpells.at(it->first).mNextWorsening); mCorprusSpells[spell].mNextWorsening = MWWorld::TimeStamp(state.mCorprusSpells.at(it->first).mNextWorsening);
} }
mSpellsChanged = true;
} }
void Spells::writeState(ESM::SpellState &state) const void Spells::writeState(ESM::SpellState &state) const

@ -50,7 +50,6 @@ namespace MWMechanics
}; };
private: private:
TContainer mSpells; TContainer mSpells;
// spell-tied effects that will be applied even after removing the spell (currently used to keep positive effects when corprus is removed) // spell-tied effects that will be applied even after removing the spell (currently used to keep positive effects when corprus is removed)
@ -63,10 +62,16 @@ namespace MWMechanics
std::map<SpellKey, CorprusStats> mCorprusSpells; std::map<SpellKey, CorprusStats> mCorprusSpells;
mutable bool mSpellsChanged;
mutable MagicEffects mEffects;
mutable std::map<SpellKey, MagicEffects> mSourcedEffects;
void rebuildEffects() const;
/// Get spell from ID, throws exception if not found /// Get spell from ID, throws exception if not found
const ESM::Spell* getSpell(const std::string& id) const; const ESM::Spell* getSpell(const std::string& id) const;
public: public:
Spells();
void worsenCorprus(const ESM::Spell* spell); void worsenCorprus(const ESM::Spell* spell);
static bool hasCorprusEffect(const ESM::Spell *spell); static bool hasCorprusEffect(const ESM::Spell *spell);

Loading…
Cancel
Save