Keep showing NPC health while dealing damage

crashfix_debugdraw
unknown 2 years ago
parent 7a0a11b30c
commit f68e7ce0b5

@ -6,6 +6,7 @@
Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses
Bug #5129: Stuttering animation on Centurion Archer
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
Bug #6427: Enemy health bar disappears before damaging effect ends
Bug #6937: Divided by Nix Hounds quest is broken
Bug #6939: OpenMW-CS: ID columns are too short
Bug #6949: Sun Damage effect doesn't work in quasi exteriors

@ -13,11 +13,13 @@
#include <components/settings/settings.hpp>
#include "actorutil.hpp"
#include "creaturestats.hpp"
#include "spellcasting.hpp"
#include "spelleffects.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwrender/animation.hpp"
@ -230,6 +232,9 @@ namespace MWMechanics
}
}
const MWWorld::Ptr player = MWMechanics::getPlayer();
bool updatedHitOverlay = false;
bool updatedEnemy = false;
// Update effects
for(auto spellIt = mSpells.begin(); spellIt != mSpells.end();)
{
@ -239,7 +244,7 @@ namespace MWMechanics
for(auto it = spellIt->mEffects.begin(); it != spellIt->mEffects.end();)
{
auto result = applyMagicEffect(ptr, caster, *spellIt, *it, duration);
if(result == MagicApplicationResult::REFLECTED)
if(result.mType == MagicApplicationResult::Type::REFLECTED)
{
if(!reflected)
{
@ -253,10 +258,22 @@ namespace MWMechanics
reflectedEffect.mFlags = ESM::ActiveEffect::Flag_Ignore_Reflect | ESM::ActiveEffect::Flag_Ignore_SpellAbsorption;
it = spellIt->mEffects.erase(it);
}
else if(result == MagicApplicationResult::REMOVED)
else if(result.mType == MagicApplicationResult::Type::REMOVED)
it = spellIt->mEffects.erase(it);
else
{
++it;
if(!updatedEnemy && result.mShowHealth && caster == player && ptr != player)
{
MWBase::Environment::get().getWindowManager()->setEnemy(ptr);
updatedEnemy = true;
}
if(!updatedHitOverlay && result.mShowHit && ptr == player)
{
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
updatedHitOverlay = true;
}
}
removedSpell = applyPurges(ptr, &spellIt, &it);
if(removedSpell)
break;

@ -299,7 +299,7 @@ namespace
stats.setMagicka(magicka);
}
MWMechanics::MagicApplicationResult applyProtections(const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
MWMechanics::MagicApplicationResult::Type applyProtections(const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
const MWMechanics::ActiveSpells::ActiveSpellParams& spellParams, ESM::ActiveEffect& effect, const ESM::MagicEffect* magicEffect)
{
auto& stats = target.getClass().getCreatureStats(target);
@ -323,7 +323,7 @@ namespace
{
if(canReflect && Misc::Rng::roll0to99(prng) < activeEffect.mMagnitude)
{
return MWMechanics::MagicApplicationResult::REFLECTED;
return MWMechanics::MagicApplicationResult::Type::REFLECTED;
}
}
else if(activeEffect.mEffectId == ESM::MagicEffect::SpellAbsorption)
@ -331,7 +331,7 @@ namespace
if(canAbsorb && Misc::Rng::roll0to99(prng) < activeEffect.mMagnitude)
{
absorbSpell(spellParams.getId(), caster, target);
return MWMechanics::MagicApplicationResult::REMOVED;
return MWMechanics::MagicApplicationResult::Type::REMOVED;
}
}
}
@ -356,12 +356,12 @@ namespace
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicPCResisted}");
else if (caster == MWMechanics::getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}");
return MWMechanics::MagicApplicationResult::REMOVED;
return MWMechanics::MagicApplicationResult::Type::REMOVED;
}
effect.mMinMagnitude *= magnitudeMult;
effect.mMaxMagnitude *= magnitudeMult;
}
return MWMechanics::MagicApplicationResult::APPLIED;
return MWMechanics::MagicApplicationResult::Type::APPLIED;
}
static const std::map<int, std::string> sBoundItemsMap{
@ -382,7 +382,7 @@ namespace
namespace MWMechanics
{
void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ActiveSpells::ActiveSpellParams& spellParams, ESM::ActiveEffect& effect, bool& invalid, bool& receivedMagicDamage, bool& recalculateMagicka)
void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ActiveSpells::ActiveSpellParams& spellParams, ESM::ActiveEffect& effect, bool& invalid, bool& receivedMagicDamage, bool& affectedHealth, bool& recalculateMagicka)
{
const auto world = MWBase::Environment::get().getWorld();
bool godmode = target == getPlayer() && world->getGodModeState();
@ -606,7 +606,7 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
static const bool uncappedDamageFatigue = Settings::Manager::getBool("uncapped damage fatigue", "Game");
adjustDynamicStat(target, index, -effect.mMagnitude, index == 2 && uncappedDamageFatigue);
if(index == 0)
receivedMagicDamage = true;
receivedMagicDamage = affectedHealth = true;
}
}
break;
@ -641,6 +641,8 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
restoreSkill(target, effect, effect.mMagnitude);
break;
case ESM::MagicEffect::RestoreHealth:
affectedHealth = true;
[[fallthrough]];
case ESM::MagicEffect::RestoreMagicka:
case ESM::MagicEffect::RestoreFatigue:
adjustDynamicStat(target, effect.mEffectId - ESM::MagicEffect::RestoreHealth, effect.mMagnitude);
@ -662,7 +664,7 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
float damage = effect.mMagnitude * damageScale;
adjustDynamicStat(target, 0, -damage);
if (damage > 0.f)
receivedMagicDamage = true;
receivedMagicDamage = affectedHealth = true;
}
break;
case ESM::MagicEffect::DrainHealth:
@ -674,7 +676,7 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
int index = effect.mEffectId - ESM::MagicEffect::DrainHealth;
adjustDynamicStat(target, index, -effect.mMagnitude, uncappedDamageFatigue && index == 2);
if(index == 0)
receivedMagicDamage = true;
receivedMagicDamage = affectedHealth = true;
}
break;
case ESM::MagicEffect::FortifyHealth:
@ -733,7 +735,7 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
if(!caster.isEmpty())
adjustDynamicStat(caster, index, effect.mMagnitude);
if(index == 0)
receivedMagicDamage = true;
receivedMagicDamage = affectedHealth = true;
}
break;
case ESM::MagicEffect::AbsorbAttribute:
@ -839,22 +841,23 @@ MagicApplicationResult applyMagicEffect(const MWWorld::Ptr& target, const MWWorl
bool invalid = false;
bool receivedMagicDamage = false;
bool recalculateMagicka = false;
bool affectedHealth = false;
if(effect.mEffectId == ESM::MagicEffect::Corprus && spellParams.shouldWorsen())
{
spellParams.worsen();
for(auto& otherEffect : spellParams.getEffects())
{
if(isCorprusEffect(otherEffect))
applyMagicEffect(target, caster, spellParams, otherEffect, invalid, receivedMagicDamage, recalculateMagicka);
applyMagicEffect(target, caster, spellParams, otherEffect, invalid, receivedMagicDamage, affectedHealth, recalculateMagicka);
}
if(target == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}");
return MagicApplicationResult::APPLIED;
return {MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth};
}
else if(shouldRemoveEffect(target, effect))
{
onMagicEffectRemoved(target, spellParams, effect);
return MagicApplicationResult::REMOVED;
return {MagicApplicationResult::Type::REMOVED, receivedMagicDamage, affectedHealth};
}
const auto* magicEffect = world->getStore().get<ESM::MagicEffect>().find(effect.mEffectId);
if(effect.mFlags & ESM::ActiveEffect::Flag_Applied)
@ -862,10 +865,10 @@ MagicApplicationResult applyMagicEffect(const MWWorld::Ptr& target, const MWWorl
if(magicEffect->mData.mFlags & ESM::MagicEffect::Flags::AppliedOnce)
{
effect.mTimeLeft -= dt;
return MagicApplicationResult::APPLIED;
return {MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth};
}
else if(!dt)
return MagicApplicationResult::APPLIED;
return {MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth};
}
if(effect.mEffectId == ESM::MagicEffect::Lock)
{
@ -925,9 +928,9 @@ MagicApplicationResult applyMagicEffect(const MWWorld::Ptr& target, const MWWorl
auto& magnitudes = stats.getMagicEffects();
if(spellParams.getType() != ESM::ActiveSpells::Type_Ability && !(effect.mFlags & ESM::ActiveEffect::Flag_Applied))
{
MagicApplicationResult result = applyProtections(target, caster, spellParams, effect, magicEffect);
if(result != MagicApplicationResult::APPLIED)
return result;
MagicApplicationResult::Type result = applyProtections(target, caster, spellParams, effect, magicEffect);
if(result != MagicApplicationResult::Type::APPLIED)
return {result, receivedMagicDamage, affectedHealth};
}
float oldMagnitude = 0.f;
if(effect.mFlags & ESM::ActiveEffect::Flag_Applied)
@ -956,13 +959,13 @@ MagicApplicationResult applyMagicEffect(const MWWorld::Ptr& target, const MWWorl
effect.mMagnitude = oldMagnitude;
effect.mFlags |= ESM::ActiveEffect::Flag_Applied | ESM::ActiveEffect::Flag_Remove;
effect.mTimeLeft -= dt;
return MagicApplicationResult::APPLIED;
return {MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth};
}
}
if(effect.mEffectId == ESM::MagicEffect::Corprus)
spellParams.worsen();
else
applyMagicEffect(target, caster, spellParams, effect, invalid, receivedMagicDamage, recalculateMagicka);
applyMagicEffect(target, caster, spellParams, effect, invalid, receivedMagicDamage, affectedHealth, recalculateMagicka);
effect.mMagnitude = magnitude;
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(effect.mMagnitude - oldMagnitude));
}
@ -977,11 +980,9 @@ MagicApplicationResult applyMagicEffect(const MWWorld::Ptr& target, const MWWorl
}
else
effect.mFlags |= ESM::ActiveEffect::Flag_Applied | ESM::ActiveEffect::Flag_Remove;
if (receivedMagicDamage && target == getPlayer())
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
if(recalculateMagicka)
target.getClass().getCreatureStats(target).recalculateMagicka();
return MagicApplicationResult::APPLIED;
return {MagicApplicationResult::Type::APPLIED, receivedMagicDamage, affectedHealth};
}
void removeMagicEffect(const MWWorld::Ptr& target, ActiveSpells::ActiveSpellParams& spellParams, const ESM::ActiveEffect& effect)

@ -13,9 +13,15 @@ namespace MWWorld
namespace MWMechanics
{
enum class MagicApplicationResult
struct MagicApplicationResult
{
APPLIED, REMOVED, REFLECTED
enum class Type
{
APPLIED, REMOVED, REFLECTED
};
Type mType;
bool mShowHit;
bool mShowHealth;
};
// Applies a tick of a single effect. Returns true if the effect should be removed immediately

Loading…
Cancel
Save