|
|
|
@ -324,6 +324,34 @@ namespace MWMechanics
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class GetAbsorptionProbability : public MWMechanics::EffectSourceVisitor
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
float mProbability;
|
|
|
|
|
|
|
|
|
|
GetAbsorptionProbability(const MWWorld::Ptr& actor)
|
|
|
|
|
: mProbability(0.f){}
|
|
|
|
|
|
|
|
|
|
virtual void visit (MWMechanics::EffectKey key,
|
|
|
|
|
const std::string& sourceName, const std::string& sourceId, int casterActorId,
|
|
|
|
|
float magnitude, float remainingTime = -1, float totalTime = -1)
|
|
|
|
|
{
|
|
|
|
|
if (key.mId == ESM::MagicEffect::SpellAbsorption)
|
|
|
|
|
{
|
|
|
|
|
if (mProbability == 0.f)
|
|
|
|
|
mProbability = magnitude / 100;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If there are different sources of SpellAbsorption effect, multiply failing probability for all effects.
|
|
|
|
|
// Real absorption probability will be the (1 - total fail chance) in this case.
|
|
|
|
|
float failProbability = 1.f - mProbability;
|
|
|
|
|
failProbability *= 1.f - magnitude / 100;
|
|
|
|
|
mProbability = 1.f - failProbability;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CastSpell::CastSpell(const MWWorld::Ptr &caster, const MWWorld::Ptr &target, const bool fromProjectile, const bool manualSpell)
|
|
|
|
|
: mCaster(caster)
|
|
|
|
|
, mTarget(target)
|
|
|
|
@ -444,12 +472,18 @@ namespace MWMechanics
|
|
|
|
|
MWBase::Environment::get().getWindowManager()->setEnemy(target);
|
|
|
|
|
|
|
|
|
|
// Try absorbing if it's a spell
|
|
|
|
|
// NOTE: Vanilla does this once per spell absorption effect source instead of adding the % from all sources together, not sure
|
|
|
|
|
// if that is worth replicating.
|
|
|
|
|
// NOTE: Vanilla does this once per spell absorption effect source instead of adding the % from all sources together, so use the same approach here
|
|
|
|
|
bool absorbed = false;
|
|
|
|
|
if (spell && caster != target && target.getClass().isActor())
|
|
|
|
|
{
|
|
|
|
|
float absorb = target.getClass().getCreatureStats(target).getMagicEffects().get(ESM::MagicEffect::SpellAbsorption).getMagnitude();
|
|
|
|
|
GetAbsorptionProbability check(target);
|
|
|
|
|
MWMechanics::CreatureStats& stats = target.getClass().getCreatureStats(target);
|
|
|
|
|
stats.getActiveSpells().visitEffectSources(check);
|
|
|
|
|
stats.getSpells().visitEffectSources(check);
|
|
|
|
|
if (target.getClass().hasInventoryStore(target))
|
|
|
|
|
target.getClass().getInventoryStore(target).visitEffectSources(check);
|
|
|
|
|
|
|
|
|
|
int absorb = check.mProbability * 100;
|
|
|
|
|
absorbed = (Misc::Rng::roll0to99() < absorb);
|
|
|
|
|
if (absorbed)
|
|
|
|
|
{
|
|
|
|
|