1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-03-04 03:19:41 +00:00

Simplify some inflict() logic

This commit is contained in:
Capostrophic 2020-04-27 12:43:34 +03:00
parent 4c1c30db33
commit e7f91ff341
3 changed files with 39 additions and 43 deletions

View file

@ -52,6 +52,9 @@ namespace MWMechanics
if (effect.mEffectID < ESM::MagicEffect::AbsorbAttribute || effect.mEffectID > ESM::MagicEffect::AbsorbSkill) if (effect.mEffectID < ESM::MagicEffect::AbsorbAttribute || effect.mEffectID > ESM::MagicEffect::AbsorbSkill)
throw std::runtime_error("invalid absorb stat effect"); throw std::runtime_error("invalid absorb stat effect");
if (appliedEffect.mMagnitude == 0)
return;
std::vector<ActiveSpells::ActiveEffect> absorbEffects; std::vector<ActiveSpells::ActiveEffect> absorbEffects;
ActiveSpells::ActiveEffect absorbEffect = appliedEffect; ActiveSpells::ActiveEffect absorbEffect = appliedEffect;
absorbEffect.mMagnitude *= -1; absorbEffect.mMagnitude *= -1;

View file

@ -113,6 +113,9 @@ namespace MWMechanics
// throughout the iteration of this spell's // throughout the iteration of this spell's
// effects, we display a "can't re-cast" message // effects, we display a "can't re-cast" message
// Try absorbing the spell. Some handling must still happen for absorbed effects.
bool absorbed = absorbSpell(spell, caster, target);
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt (effects.mList.begin()); for (std::vector<ESM::ENAMstruct>::const_iterator effectIt (effects.mList.begin());
!target.isEmpty() && effectIt != effects.mList.end(); ++effectIt) !target.isEmpty() && effectIt != effects.mList.end(); ++effectIt)
{ {
@ -140,20 +143,14 @@ namespace MWMechanics
&& (caster.isEmpty() || !caster.getClass().isActor())) && (caster.isEmpty() || !caster.getClass().isActor()))
continue; continue;
// If player is healing someone, show the target's HP bar // Notify the target actor they've been hit
if (castByPlayer && target != caster bool isHarmful = magicEffect->mData.mFlags & ESM::MagicEffect::Harmful;
&& effectIt->mEffectID == ESM::MagicEffect::RestoreHealth if (target.getClass().isActor() && target != caster && !caster.isEmpty() && isHarmful)
&& target.getClass().isActor()) target.getClass().onHit(target, 0.0f, true, MWWorld::Ptr(), caster, osg::Vec3f(), true);
MWBase::Environment::get().getWindowManager()->setEnemy(target);
// Try absorbing the spell // Avoid proceeding further for absorbed spells.
// FIXME: this should be done only once for the spell if (absorbed)
bool absorbed = false;
if (absorbSpell(spell, caster, target))
{
absorbed = true;
continue; continue;
}
// Reflect harmful effects // Reflect harmful effects
if (!reflected && reflectEffect(*effectIt, magicEffect, caster, target, reflectedEffects)) if (!reflected && reflectEffect(*effectIt, magicEffect, caster, target, reflectedEffects))
@ -162,37 +159,17 @@ namespace MWMechanics
continue; continue;
} }
float magnitudeMult = 1; // Try resisting.
float magnitudeMult = getEffectMultiplier(effectIt->mEffectID, target, caster, spell, &targetEffects);
if (target.getClass().isActor()) if (magnitudeMult == 0)
{ {
bool isHarmful = magicEffect->mData.mFlags & ESM::MagicEffect::Harmful; // Fully resisted, show message
if (target == getPlayer())
// Try resisting MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicPCResisted}");
magnitudeMult = MWMechanics::getEffectMultiplier(effectIt->mEffectID, target, caster, spell, &targetEffects); else if (castByPlayer)
if (magnitudeMult == 0) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}");
{
// Fully resisted, show message
if (target == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicPCResisted}");
else if (castByPlayer)
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}");
}
else if (isHarmful && castByPlayer && target != caster)
{
// If player is attempting to cast a harmful spell and it wasn't fully resisted, show the target's HP bar
MWBase::Environment::get().getWindowManager()->setEnemy(target);
}
if (target == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState() && isHarmful)
magnitudeMult = 0;
// Notify the target actor they've been hit
if (target != caster && !caster.isEmpty() && isHarmful)
target.getClass().onHit(target, 0.0f, true, MWWorld::Ptr(), caster, osg::Vec3f(), true);
} }
else
if (magnitudeMult > 0 && !absorbed)
{ {
float magnitude = effectIt->mMagnMin + Misc::Rng::rollDice(effectIt->mMagnMax - effectIt->mMagnMin + 1); float magnitude = effectIt->mMagnMin + Misc::Rng::rollDice(effectIt->mMagnMax - effectIt->mMagnMin + 1);
magnitude *= magnitudeMult; magnitude *= magnitudeMult;
@ -219,6 +196,19 @@ namespace MWMechanics
effect.mMagnitude = 0; effect.mMagnitude = 0;
} }
// Avoid applying harmful effects to the player in god mode
if (target == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState() && isHarmful)
{
effect.mMagnitude = 0;
}
bool effectAffectsHealth = isHarmful || effectIt->mEffectID == ESM::MagicEffect::RestoreHealth;
if (castByPlayer && target != caster && effectAffectsHealth)
{
// If player is attempting to cast a harmful spell or is healing someone, show the target's HP bar.
MWBase::Environment::get().getWindowManager()->setEnemy(target);
}
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration); bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
if (hasDuration && effectIt->mDuration == 0) if (hasDuration && effectIt->mDuration == 0)
{ {
@ -228,7 +218,7 @@ namespace MWMechanics
// duration 0 means apply full magnitude instantly // duration 0 means apply full magnitude instantly
bool wasDead = target.getClass().getCreatureStats(target).isDead(); bool wasDead = target.getClass().getCreatureStats(target).isDead();
effectTick(target.getClass().getCreatureStats(target), target, EffectKey(*effectIt), magnitude); effectTick(target.getClass().getCreatureStats(target), target, EffectKey(*effectIt), effect.mMagnitude);
bool isDead = target.getClass().getCreatureStats(target).isDead(); bool isDead = target.getClass().getCreatureStats(target).isDead();
if (!wasDead && isDead) if (!wasDead && isDead)
@ -253,7 +243,7 @@ namespace MWMechanics
// Command spells should have their effect, including taking the target out of combat, each time the spell successfully affects the target // Command spells should have their effect, including taking the target out of combat, each time the spell successfully affects the target
if (((effectIt->mEffectID == ESM::MagicEffect::CommandHumanoid && target.getClass().isNpc()) if (((effectIt->mEffectID == ESM::MagicEffect::CommandHumanoid && target.getClass().isNpc())
|| (effectIt->mEffectID == ESM::MagicEffect::CommandCreature && target.getTypeName() == typeid(ESM::Creature).name())) || (effectIt->mEffectID == ESM::MagicEffect::CommandCreature && target.getTypeName() == typeid(ESM::Creature).name()))
&& !caster.isEmpty() && caster.getClass().isActor() && target != getPlayer() && magnitude >= target.getClass().getCreatureStats(target).getLevel()) && !caster.isEmpty() && caster.getClass().isActor() && target != getPlayer() && effect.mMagnitude >= target.getClass().getCreatureStats(target).getLevel())
{ {
MWMechanics::AiFollow package(caster, true); MWMechanics::AiFollow package(caster, true);
target.getClass().getCreatureStats(target).getAiSequence().stack(package, target); target.getClass().getCreatureStats(target).getAiSequence().stack(package, target);

View file

@ -17,6 +17,9 @@ namespace MWMechanics
float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster, float getEffectMultiplier(short effectId, const MWWorld::Ptr& actor, const MWWorld::Ptr& caster,
const ESM::Spell* spell, const MagicEffects* effects) const ESM::Spell* spell, const MagicEffects* effects)
{ {
if (!actor.getClass().isActor())
return 1;
float resistance = getEffectResistance(effectId, actor, caster, spell, effects); float resistance = getEffectResistance(effectId, actor, caster, spell, effects);
return 1 - resistance / 100.f; return 1 - resistance / 100.f;
} }