From 689dea4cb3ab2bf34e31a437cbb7452ade929956 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 16 Dec 2015 19:33:39 +0100 Subject: [PATCH] Add instant spell effects to the actor's magic effect list Via http://forum.openmw.org/viewtopic.php?f=2&t=3212&start=20#p36208 --- apps/openmw/mwmechanics/actors.cpp | 7 ++- apps/openmw/mwmechanics/spellcasting.cpp | 74 +++++++++++++----------- apps/openmw/mwworld/inventorystore.cpp | 5 -- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ed6ace57d..ee114dff2 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -497,7 +497,12 @@ namespace MWMechanics if (it->second.getMagnitude() > 0) { CastSpell cast(ptr, ptr); - cast.applyInstantEffect(ptr, ptr, it->first, it->second.getMagnitude()); + if (cast.applyInstantEffect(ptr, ptr, it->first, it->second.getMagnitude())) + { + creatureStats.getActiveSpells().purgeEffect(it->first.mId); + if (ptr.getClass().hasInventoryStore(ptr)) + ptr.getClass().getInventoryStore(ptr).purgeEffect(it->first.mId); + } } } } diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index a2d32b324..ab8784beb 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -452,42 +452,18 @@ namespace MWMechanics float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; magnitude *= magnitudeMult; - bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); - if (target.getClass().isActor() && hasDuration && effectIt->mDuration > 0) + if (!target.getClass().isActor()) { - ActiveSpells::ActiveEffect effect; - effect.mEffectId = effectIt->mEffectID; - effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; - effect.mDuration = static_cast(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 - // magnitude, since we're transfering stats from the target to the caster - if (!caster.isEmpty() && caster.getClass().isActor()) - { - for (int i=0; i<5; ++i) - { - if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) - { - std::vector effects; - ActiveSpells::ActiveEffect effect_ = effect; - effect_.mMagnitude *= -1; - effects.push_back(effect_); - // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies - caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, - effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); - } - } - } + // non-actor objects have no list of active magic effects, so have to apply instantly + if (!applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude)) + continue; } - else + else // target.getClass().isActor() == true { - if (hasDuration && target.getClass().isActor()) + bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); + if (hasDuration && effectIt->mDuration == 0) { + // duration 0 means apply full magnitude instantly bool wasDead = target.getClass().getCreatureStats(target).isDead(); effectTick(target.getClass().getCreatureStats(target), target, EffectKey(*effectIt), magnitude); bool isDead = target.getClass().getCreatureStats(target).isDead(); @@ -495,8 +471,38 @@ namespace MWMechanics if (!wasDead && isDead) MWBase::Environment::get().getMechanicsManager()->actorKilled(target, caster); } - else if (!applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude)) - continue; + else + { + // add to list of active effects, to apply in next frame + ActiveSpells::ActiveEffect effect; + effect.mEffectId = effectIt->mEffectID; + effect.mArg = MWMechanics::EffectKey(*effectIt).mArg; + effect.mDuration = static_cast(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 + // magnitude, since we're transfering stats from the target to the caster + if (!caster.isEmpty() && caster.getClass().isActor()) + { + for (int i=0; i<5; ++i) + { + if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i) + { + std::vector effects; + ActiveSpells::ActiveEffect effect_ = effect; + effect_.mMagnitude *= -1; + effects.push_back(effect_); + // Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies + caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, + effects, mSourceName, target.getClass().getCreatureStats(target).getActorId()); + } + } + } + } } // Re-casting a summon effect will remove the creature from previous castings of that effect. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index ebba4ae30..da591487e 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -410,11 +410,6 @@ void MWWorld::InventoryStore::updateMagicEffects(const Ptr& actor) // the items should appear as if they'd always been equipped. mListener->permanentEffectAdded(magicEffect, !mFirstAutoEquip, !mFirstAutoEquip && effectIt == enchantment.mEffects.mList.begin()); - - // Apply instant effects - MWMechanics::CastSpell cast(actor, actor); - if (magnitude) - cast.applyInstantEffect(actor, actor, effectIt->mEffectID, magnitude); } if (magnitude)