diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index c996e90d6..26480ed03 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -148,13 +148,17 @@ namespace MWMechanics return school; } - float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell) + float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, + const ESM::Spell* spell, const MagicEffects* effects) { const ESM::MagicEffect *magicEffect = MWBase::Environment::get().getWorld()->getStore().get().find ( effectId); const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); + const MWMechanics::MagicEffects* magicEffects = &stats.getMagicEffects(); + if (effects) + magicEffects = effects; float resisted = 0; if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful) @@ -165,9 +169,9 @@ namespace MWMechanics float resistance = 0; if (resistanceEffect != -1) - resistance += stats.getMagicEffects().get(resistanceEffect).mMagnitude; + resistance += magicEffects->get(resistanceEffect).mMagnitude; if (weaknessEffect != -1) - resistance -= stats.getMagicEffects().get(weaknessEffect).mMagnitude; + resistance -= magicEffects->get(weaknessEffect).mMagnitude; float willpower = stats.getAttribute(ESM::Attribute::Willpower).getModified(); @@ -204,9 +208,10 @@ namespace MWMechanics return resisted; } - float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell) + float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, + const ESM::Spell* spell, const MagicEffects* effects) { - float resistance = getEffectResistance(effectId, actor, caster, spell); + float resistance = getEffectResistance(effectId, actor, caster, spell, effects); if (resistance >= 0) return 1 - resistance / 100.f; else @@ -261,6 +266,13 @@ namespace MWMechanics bool firstAppliedEffect = true; bool anyHarmfulEffect = false; + // HACK: cache target's magic effects here, and add any applied effects to it. Use the cached effects for determining resistance. + // This is required for Weakness effects in a spell to apply to any subsequent effects in the spell. + // Otherwise, they'd only apply after the whole spell was added. + MagicEffects targetEffects; + if (target.getClass().isActor()) + targetEffects += target.getClass().getCreatureStats(target).getMagicEffects(); + bool castByPlayer = (!caster.isEmpty() && caster.getRefData().getHandle() == "player"); for (std::vector::const_iterator effectIt (effects.mList.begin()); @@ -346,8 +358,7 @@ namespace MWMechanics // Try resisting if (magnitudeMult > 0 && target.getClass().isActor()) { - - magnitudeMult = MWMechanics::getEffectMultiplier(effectIt->mEffectID, target, caster, spell); + magnitudeMult = MWMechanics::getEffectMultiplier(effectIt->mEffectID, target, caster, spell, &targetEffects); if (magnitudeMult == 0) { // Fully resisted, show message @@ -375,6 +386,8 @@ namespace MWMechanics effect.mDuration = effectIt->mDuration; effect.mMagnitude = magnitude; + targetEffects.add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(effect.mMagnitude)); + appliedLastingEffects.push_back(effect); // For absorb effects, also apply the effect to the caster - but with a negative diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index dce4b792e..821d7ae0e 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -18,6 +18,7 @@ namespace ESM namespace MWMechanics { class EffectKey; + class MagicEffects; ESM::Skill::SkillEnum spellSchoolToSkill(int school); @@ -35,9 +36,13 @@ namespace MWMechanics int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor); /// @return >=100 for fully resisted. can also return negative value for damage amplification. - float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL); + /// @param effects Override the actor's current magicEffects. Useful if there are effects currently + /// being applied (but not applied yet) that should also be considered. + float getEffectResistance (short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, + const ESM::Spell* spell = NULL, const MagicEffects* effects = NULL); - float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, const ESM::Spell* spell = NULL); + float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, + const ESM::Spell* spell = NULL, const MagicEffects* effects = NULL); class CastSpell {