|
|
|
@ -56,6 +56,64 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude)
|
|
|
|
|
{
|
|
|
|
|
MWMechanics::DynamicStat<float> value = target.getClass().getCreatureStats(target).getDynamic(attribute);
|
|
|
|
|
value.setCurrent(value.getCurrent()+magnitude, attribute == 2);
|
|
|
|
|
target.getClass().getCreatureStats(target).setDynamic(attribute, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: refactor the effect tick functions in Actors so they can be reused here
|
|
|
|
|
void applyInstantEffectTick(MWMechanics::EffectKey effect, const MWWorld::Ptr& target, float magnitude)
|
|
|
|
|
{
|
|
|
|
|
int effectId = effect.mId;
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageHealth)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(0, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreHealth)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(0, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageFatigue)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(2, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreFatigue)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(2, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageMagicka)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(1, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreMagicka)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(1, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute)
|
|
|
|
|
{
|
|
|
|
|
int attribute = effect.mArg;
|
|
|
|
|
MWMechanics::AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute);
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageAttribute)
|
|
|
|
|
value.damage(magnitude);
|
|
|
|
|
else
|
|
|
|
|
value.restore(magnitude);
|
|
|
|
|
target.getClass().getCreatureStats(target).setAttribute(attribute, value);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill)
|
|
|
|
|
{
|
|
|
|
|
if (target.getTypeName() != typeid(ESM::NPC).name())
|
|
|
|
|
return;
|
|
|
|
|
int skill = effect.mArg;
|
|
|
|
|
MWMechanics::SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill);
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageSkill)
|
|
|
|
|
value.damage(magnitude);
|
|
|
|
|
else
|
|
|
|
|
value.restore(magnitude);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace MWMechanics
|
|
|
|
@ -438,8 +496,8 @@ namespace MWMechanics
|
|
|
|
|
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
|
|
|
|
magnitude *= magnitudeMult;
|
|
|
|
|
|
|
|
|
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) && effectIt->mDuration > 0;
|
|
|
|
|
if (target.getClass().isActor() && hasDuration)
|
|
|
|
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
|
|
|
|
if (target.getClass().isActor() && hasDuration && effectIt->mDuration > 0)
|
|
|
|
|
{
|
|
|
|
|
ActiveSpells::ActiveEffect effect;
|
|
|
|
|
effect.mEffectId = effectIt->mEffectID;
|
|
|
|
@ -471,7 +529,12 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
|
|
|
|
{
|
|
|
|
|
if (hasDuration && target.getClass().isActor())
|
|
|
|
|
applyInstantEffectTick(EffectKey(*effectIt), target, magnitude);
|
|
|
|
|
else
|
|
|
|
|
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Re-casting a summon effect will remove the creature from previous castings of that effect.
|
|
|
|
|
if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor())
|
|
|
|
@ -485,16 +548,6 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent.
|
|
|
|
|
// This was probably just done to have the effect visible in the magic menu for a while
|
|
|
|
|
// to notify the player they've been damaged?
|
|
|
|
|
if (effectIt->mEffectID == ESM::MagicEffect::DamageAttribute
|
|
|
|
|
|| effectIt->mEffectID == ESM::MagicEffect::DamageSkill
|
|
|
|
|
|| effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute
|
|
|
|
|
|| effectIt->mEffectID == ESM::MagicEffect::RestoreSkill
|
|
|
|
|
)
|
|
|
|
|
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
|
|
|
|
|
|
|
|
|
if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)
|
|
|
|
|
{
|
|
|
|
|
// Play sound, only for the first effect
|
|
|
|
@ -584,53 +637,6 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute)
|
|
|
|
|
{
|
|
|
|
|
int attribute = effect.mArg;
|
|
|
|
|
AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute);
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageAttribute)
|
|
|
|
|
value.damage(magnitude);
|
|
|
|
|
else
|
|
|
|
|
value.restore(magnitude);
|
|
|
|
|
target.getClass().getCreatureStats(target).setAttribute(attribute, value);
|
|
|
|
|
}
|
|
|
|
|
// TODO: refactor the effect tick functions in Actors so they can be reused here
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageHealth)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(0, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreHealth)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(0, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageFatigue)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(2, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreFatigue)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(2, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageMagicka)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(1, target, magnitude * -1);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::RestoreMagicka)
|
|
|
|
|
{
|
|
|
|
|
applyDynamicStatsEffect(1, target, magnitude);
|
|
|
|
|
}
|
|
|
|
|
else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill)
|
|
|
|
|
{
|
|
|
|
|
if (target.getTypeName() != typeid(ESM::NPC).name())
|
|
|
|
|
return;
|
|
|
|
|
int skill = effect.mArg;
|
|
|
|
|
SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill);
|
|
|
|
|
if (effectId == ESM::MagicEffect::DamageSkill)
|
|
|
|
|
value.damage(magnitude);
|
|
|
|
|
else
|
|
|
|
|
value.restore(magnitude);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (effectId == ESM::MagicEffect::CurePoison)
|
|
|
|
|
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
|
|
|
|
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
|
|
|
@ -680,13 +686,7 @@ namespace MWMechanics
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CastSpell::applyDynamicStatsEffect(int attribute, const MWWorld::Ptr& target, float magnitude)
|
|
|
|
|
{
|
|
|
|
|
DynamicStat<float> value = target.getClass().getCreatureStats(target).getDynamic(attribute);
|
|
|
|
|
value.setCurrent(value.getCurrent()+magnitude, attribute == 2);
|
|
|
|
|
target.getClass().getCreatureStats(target).setDynamic(attribute, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CastSpell::cast(const std::string &id)
|
|
|
|
|
{
|
|
|
|
|