diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 1d2ef827f..681f01f04 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -63,11 +63,25 @@ namespace MWMechanics TContainer::iterator iter = mSpells.find (lower); std::map::iterator corprusIt = mCorprusSpells.find(lower); - if (iter!=mSpells.end()) - mSpells.erase (iter); - + // if it's corprus, remove negative and keep positive effects if (corprusIt != mCorprusSpells.end()) + { + worsenCorprus(lower); + if (mPermanentSpellEffects.find(lower) != mPermanentSpellEffects.end()) + { + MagicEffects & effects = mPermanentSpellEffects[lower]; + for (MagicEffects::Collection::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + { + const ESM::MagicEffect * magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->first.mId); + if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) + effects.remove(effectIt->first); + } + } mCorprusSpells.erase(corprusIt); + } + + if (iter!=mSpells.end()) + mSpells.erase (iter); if (spellId==mSelectedSpell) mSelectedSpell.clear(); @@ -94,20 +108,17 @@ namespace MWMechanics if (iter->second.find(i) != iter->second.end()) random = iter->second.at(i); - int magnMult = 1; - if (mCorprusSpells.find(spell->mId) != mCorprusSpells.end()) - { - const ESM::MagicEffect* effect = MWBase::Environment::get().getWorld()->getStore().get().find(spell->mEffects.mList.front().mEffectID); - if ((it->mEffectID != ESM::MagicEffect::Corprus) && (effect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE - magnMult += mCorprusSpells.at(spell->mId).mWorsenings; - } - - effects.add (*it, (it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random) * magnMult); + effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random); ++i; } } } + for (std::map::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it) + { + effects += it->second; + } + return effects; } @@ -241,6 +252,25 @@ namespace MWMechanics { mCorprusSpells[corpSpellId].mNextWorsening = MWBase::Environment::get().getWorld()->getTimeStamp() + CorprusStats::sWorseningPeriod; mCorprusSpells[corpSpellId].mWorsenings++; + + // update worsened effects + mPermanentSpellEffects[corpSpellId] = MagicEffects(); + const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get().find(corpSpellId); + int i=0; + for (std::vector::const_iterator effectIt = spell->mEffects.mList.begin(); effectIt != spell->mEffects.mList.end(); ++effectIt, ++i) + { + const ESM::MagicEffect * magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find(effectIt->mEffectID); + if ((effectIt->mEffectID != ESM::MagicEffect::Corprus) && (magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE + { + float random = 1.f; + if (mSpells[corpSpellId].find(i) != mSpells[corpSpellId].end()) + random = mSpells[corpSpellId].at(i); + + float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; + magnitude *= std::max(1, mCorprusSpells[corpSpellId].mWorsenings); + mPermanentSpellEffects[corpSpellId].add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(magnitude)); + } + } } bool Spells::hasCorprusEffect(const ESM::Spell *spell) @@ -297,6 +327,20 @@ namespace MWMechanics for (std::map::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) mUsedPowers[it->first] = MWWorld::TimeStamp(it->second); + for (std::map >::const_iterator it = + state.mPermanentSpellEffects.begin(); it != state.mPermanentSpellEffects.end(); ++it) + { + const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get().search(it->first); + if (!spell) + continue; + + mPermanentSpellEffects[it->first] = MagicEffects(); + for (std::vector::const_iterator effectIt = it->second.begin(); effectIt != it->second.end(); ++effectIt) + { + mPermanentSpellEffects[it->first].add(EffectKey(effectIt->mId, effectIt->mArg), effectIt->mMagnitude); + } + } + mCorprusSpells.clear(); for (std::map::const_iterator it = state.mCorprusSpells.begin(); it != state.mCorprusSpells.end(); ++it) { @@ -316,6 +360,21 @@ namespace MWMechanics for (std::map::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it) state.mUsedPowers[it->first] = it->second.toEsm(); + for (std::map::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it) + { + std::vector effectList; + for (MagicEffects::Collection::const_iterator effectIt = it->second.begin(); effectIt != it->second.end(); ++effectIt) + { + ESM::SpellState::PermanentSpellEffectInfo info; + info.mId = effectIt->first.mId; + info.mArg = effectIt->first.mArg; + info.mMagnitude = effectIt->second.getModifier(); + + effectList.push_back(info); + } + state.mPermanentSpellEffects[it->first] = effectList; + } + for (std::map::const_iterator it = mCorprusSpells.begin(); it != mCorprusSpells.end(); ++it) { state.mCorprusSpells[it->first].mWorsenings = mCorprusSpells.at(it->first).mWorsenings; diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index c1dd3e159..7caeba6e8 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -46,6 +46,9 @@ namespace MWMechanics TContainer mSpells; + // spell-tied effects that will be applied even after removing the spell (currently used to keep positive effects when corprus is removed) + std::map mPermanentSpellEffects; + // Note: this is the spell that's about to be cast, *not* the spell selected in the GUI (which may be different) std::string mSelectedSpell; diff --git a/components/esm/spellstate.cpp b/components/esm/spellstate.cpp index 238f93901..3ed3329b4 100644 --- a/components/esm/spellstate.cpp +++ b/components/esm/spellstate.cpp @@ -27,6 +27,23 @@ namespace ESM mSpells[id] = random; } + while (esm.isNextSub("PERM")) + { + std::string spellId = esm.getHString(); + + std::vector permEffectList; + while (esm.isNextSub("EFID")) + { + PermanentSpellEffectInfo info; + esm.getHT(info.mId); + esm.getHNT(info.mArg, "ARG_"); + esm.getHNT(info.mMagnitude, "MAGN"); + + permEffectList.push_back(info); + } + mPermanentSpellEffects[spellId] = permEffectList; + } + while (esm.isNextSub("CORP")) { std::string id = esm.getHString(); @@ -64,6 +81,19 @@ namespace ESM } } + for (std::map >::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it) + { + esm.writeHNString("PERM", it->first); + + const std::vector & effects = it->second; + for (std::vector::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) + { + esm.writeHNT("EFID", effectIt->mId); + esm.writeHNT("ARG_", effectIt->mArg); + esm.writeHNT("MAGN", effectIt->mMagnitude); + } + } + for (std::map::const_iterator it = mCorprusSpells.begin(); it != mCorprusSpells.end(); ++it) { esm.writeHNString("CORP", it->first); diff --git a/components/esm/spellstate.hpp b/components/esm/spellstate.hpp index bf8240246..2ab27e908 100644 --- a/components/esm/spellstate.hpp +++ b/components/esm/spellstate.hpp @@ -2,6 +2,7 @@ #define OPENMW_ESM_SPELLSTATE_H #include +#include #include #include "defs.hpp" @@ -19,9 +20,18 @@ namespace ESM TimeStamp mNextWorsening; }; + struct PermanentSpellEffectInfo + { + int mId; + int mArg; + float mMagnitude; + }; + typedef std::map > TContainer; TContainer mSpells; + std::map > mPermanentSpellEffects; + std::map mCorprusSpells; std::map mUsedPowers;