From 123157b216919f58a6d72fd5b0c8366e2e85a486 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 15 Jul 2014 21:53:11 +0200 Subject: [PATCH] Implement elemental shield damage to attacker (Feature #1121) --- apps/openmw/mwclass/creature.cpp | 2 ++ apps/openmw/mwclass/npc.cpp | 2 ++ apps/openmw/mwmechanics/combat.cpp | 48 ++++++++++++++++++++++++++++++ apps/openmw/mwmechanics/combat.hpp | 3 ++ 4 files changed, 55 insertions(+) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index feb6a2714..e78134802 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -330,6 +330,8 @@ namespace MWClass } } + MWMechanics::applyElementalShields(ptr, victim); + if (!weapon.isEmpty() && MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage)) damage = 0; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e2cb8ba7a..a5175c1f6 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -630,6 +630,8 @@ namespace MWClass } } + MWMechanics::applyElementalShields(ptr, victim); + if (!weapon.isEmpty() && MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage)) damage = 0; diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 6feb5879b..19f00e81b 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -256,4 +256,52 @@ namespace MWMechanics return hitchance; } + void applyElementalShields(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim) + { + for (int i=0; i<3; ++i) + { + float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).mMagnitude; + + if (!magnitude) + continue; + + CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); + float saveTerm = attacker.getClass().getSkill(attacker, ESM::Skill::Destruction) + + 0.2f * attackerStats.getAttribute(ESM::Attribute::Willpower).getModified() + + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); + + int fatigueMax = attackerStats.getFatigue().getModified(); + int fatigueCurrent = attackerStats.getFatigue().getCurrent(); + + float normalisedFatigue = fatigueMax==0 ? 1 : std::max (0.0f, static_cast (fatigueCurrent)/fatigueMax); + + saveTerm *= 1.25f * normalisedFatigue; + + float roll = std::rand()/ (static_cast (RAND_MAX) + 1) * 100; // [0, 99] + float x = std::max(0.f, saveTerm - roll); + + int element = ESM::MagicEffect::FireDamage; + if (i == 1) + element = ESM::MagicEffect::ShockDamage; + if (i == 2) + element = ESM::MagicEffect::FrostDamage; + + short resistanceEffect = ESM::MagicEffect::getResistanceEffect(element); + short weaknessEffect = ESM::MagicEffect::getWeaknessEffect(element); + float elementResistance = 0; + if (resistanceEffect != -1) + elementResistance += attackerStats.getMagicEffects().get(resistanceEffect).mMagnitude; + if (weaknessEffect != -1) + elementResistance -= attackerStats.getMagicEffects().get(weaknessEffect).mMagnitude; + + x = std::min(100.f, x + elementResistance); + + static const float fElementalShieldMult = MWBase::Environment::get().getWorld()->getStore().get().find("fElementalShieldMult")->getFloat(); + x = fElementalShieldMult * magnitude * (1.f - 0.01f * x); + MWMechanics::DynamicStat health = attackerStats.getHealth(); + health.setCurrent(health.getCurrent() - x); + attackerStats.setHealth(health); + } + } + } diff --git a/apps/openmw/mwmechanics/combat.hpp b/apps/openmw/mwmechanics/combat.hpp index bc58227bf..eb89cb820 100644 --- a/apps/openmw/mwmechanics/combat.hpp +++ b/apps/openmw/mwmechanics/combat.hpp @@ -19,6 +19,9 @@ void projectileHit (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, MW /// Get the chance (in percent) for \a attacker to successfully hit \a victim with a given weapon skill value float getHitChance (const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, int skillValue); +/// Applies damage to attacker based on the victim's elemental shields. +void applyElementalShields(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim); + } #endif