1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-21 09:39:56 +00:00

Don't wait a frame to recalculate magicka

This commit is contained in:
Evil Eye 2021-10-25 16:54:50 +02:00
parent 41318a585f
commit 289e1544d2
11 changed files with 67 additions and 89 deletions

View File

@ -5,6 +5,7 @@
Bug #3246: ESSImporter: Most NPCs are dead on save load Bug #3246: ESSImporter: Most NPCs are dead on save load
Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions) Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
Bug #3792: 1 frame late magicka recalc breaks early scripted magicka reactions to Intelligence change
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
Bug #3905: Great House Dagoth issues Bug #3905: Great House Dagoth issues
Bug #4203: Resurrecting an actor should close the loot GUI Bug #4203: Resurrecting an actor should close the loot GUI

View File

@ -112,7 +112,10 @@ namespace MWClass
{ {
if (!ptr.getRefData().getCustomData()) if (!ptr.getRefData().getCustomData())
{ {
std::unique_ptr<CreatureCustomData> data (new CreatureCustomData); auto tempData = std::make_unique<CreatureCustomData>();
CreatureCustomData* data = tempData.get();
MWMechanics::CreatureCustomDataResetter resetter(ptr);
ptr.getRefData().setCustomData(std::move(tempData));
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
@ -156,10 +159,7 @@ namespace MWClass
data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold); data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold);
data->mCreatureStats.setNeedRecalcDynamicStats(false); resetter.mPtr = {};
// store
ptr.getRefData().setCustomData(std::move(data));
getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId()); getContainerStore(ptr).fill(ref->mBase->mInventory, ptr.getCellRef().getRefId());

View File

@ -303,7 +303,11 @@ namespace MWClass
{ {
if (!ptr.getRefData().getCustomData()) if (!ptr.getRefData().getCustomData())
{ {
std::unique_ptr<NpcCustomData> data(new NpcCustomData); bool recalculate = false;
auto tempData = std::make_unique<NpcCustomData>();
NpcCustomData* data = tempData.get();
MWMechanics::CreatureCustomDataResetter resetter(ptr);
ptr.getRefData().setCustomData(std::move(tempData));
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>(); MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
@ -334,8 +338,6 @@ namespace MWClass
data->mNpcStats.setLevel(ref->mBase->mNpdt.mLevel); data->mNpcStats.setLevel(ref->mBase->mNpdt.mLevel);
data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt.mDisposition); data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt.mDisposition);
data->mNpcStats.setReputation(ref->mBase->mNpdt.mReputation); data->mNpcStats.setReputation(ref->mBase->mNpdt.mReputation);
data->mNpcStats.setNeedRecalcDynamicStats(false);
} }
else else
{ {
@ -351,7 +353,7 @@ namespace MWClass
autoCalculateAttributes(ref->mBase, data->mNpcStats); autoCalculateAttributes(ref->mBase, data->mNpcStats);
autoCalculateSkills(ref->mBase, data->mNpcStats, ptr, spellsInitialised); autoCalculateSkills(ref->mBase, data->mNpcStats, ptr, spellsInitialised);
data->mNpcStats.setNeedRecalcDynamicStats(true); recalculate = true;
} }
// Persistent actors with 0 health do not play death animation // Persistent actors with 0 health do not play death animation
@ -387,7 +389,9 @@ namespace MWClass
data->mNpcStats.setGoldPool(gold); data->mNpcStats.setGoldPool(gold);
// store // store
ptr.getRefData().setCustomData(std::move(data)); resetter.mPtr = {};
if(recalculate)
data->mNpcStats.recalculateMagicka();
// inventory // inventory
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items // setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items

View File

@ -240,10 +240,7 @@ namespace MWMechanics
{ {
// magic effects // magic effects
adjustMagicEffects (ptr, duration); adjustMagicEffects (ptr, duration);
if (ptr.getClass().getCreatureStats(ptr).needToRecalcDynamicStats())
calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr, duration);
// fatigue restoration // fatigue restoration
calculateRestoration(ptr, duration); calculateRestoration(ptr, duration);
} }
@ -654,29 +651,6 @@ namespace MWMechanics
updateSummons(creature, mTimerDisposeSummonsCorpses == 0.f); updateSummons(creature, mTimerDisposeSummonsCorpses == 0.f);
} }
void Actors::calculateDynamicStats (const MWWorld::Ptr& ptr)
{
CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr);
float intelligence = creatureStats.getAttribute(ESM::Attribute::Intelligence).getModified();
float base = 1.f;
if (ptr == getPlayer())
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
else
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
double magickaFactor = base +
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
DynamicStat<float> magicka = creatureStats.getMagicka();
float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase();
float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0;
magicka.setModified(magicka.getModified() + diff, 0);
magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true);
creatureStats.setMagicka(magicka);
}
void Actors::restoreDynamicStats (const MWWorld::Ptr& ptr, double hours, bool sleep) void Actors::restoreDynamicStats (const MWWorld::Ptr& ptr, double hours, bool sleep)
{ {
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
@ -771,14 +745,6 @@ namespace MWMechanics
stats.setFatigue (fatigue); stats.setFatigue (fatigue);
} }
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration)
{
CreatureStats &creatureStats = ptr.getClass().getCreatureStats(ptr);
if (creatureStats.needToRecalcDynamicStats())
calculateDynamicStats(ptr);
}
bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr) bool Actors::isAttackPreparing(const MWWorld::Ptr& ptr)
{ {
PtrActorMap::iterator it = mActors.find(ptr); PtrActorMap::iterator it = mActors.find(ptr);
@ -1711,10 +1677,6 @@ namespace MWMechanics
if (iter->first.getType() == ESM::Creature::sRecordId) if (iter->first.getType() == ESM::Creature::sRecordId)
soulTrap(iter->first); soulTrap(iter->first);
// Magic effects will be reset later, and the magic effect that could kill the actor
// needs to be determined now
calculateCreatureStatModifiers(iter->first, 0);
if (cls.isEssential(iter->first)) if (cls.isEssential(iter->first))
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
} }
@ -1730,8 +1692,6 @@ namespace MWMechanics
// Make sure spell effects are removed // Make sure spell effects are removed
purgeSpellEffects(stats.getActorId()); purgeSpellEffects(stats.getActorId());
// Reset dynamic stats, attributes and skills
calculateCreatureStatModifiers(iter->first, 0);
stats.getMagicEffects().add(ESM::MagicEffect::Vampirism, vampirism); stats.getMagicEffects().add(ESM::MagicEffect::Vampirism, vampirism);
if (isPlayer) if (isPlayer)
@ -1816,10 +1776,6 @@ namespace MWMechanics
continue; continue;
adjustMagicEffects (iter->first, duration); adjustMagicEffects (iter->first, duration);
if (iter->first.getClass().getCreatureStats(iter->first).needToRecalcDynamicStats())
calculateDynamicStats (iter->first);
calculateCreatureStatModifiers (iter->first, duration);
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first);
if (animation) if (animation)
@ -2209,7 +2165,6 @@ namespace MWMechanics
void Actors::updateMagicEffects(const MWWorld::Ptr &ptr) void Actors::updateMagicEffects(const MWWorld::Ptr &ptr)
{ {
adjustMagicEffects(ptr, 0.f); adjustMagicEffects(ptr, 0.f);
calculateCreatureStatModifiers(ptr, 0.f);
} }
bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const

View File

@ -43,10 +43,6 @@ namespace MWMechanics
void adjustMagicEffects (const MWWorld::Ptr& creature, float duration); void adjustMagicEffects (const MWWorld::Ptr& creature, float duration);
void calculateDynamicStats (const MWWorld::Ptr& ptr);
void calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration);
void calculateRestoration (const MWWorld::Ptr& ptr, float duration); void calculateRestoration (const MWWorld::Ptr& ptr, float duration);
void updateDrowning (const MWWorld::Ptr& ptr, float duration, bool isKnockedOut, bool isPlayer); void updateDrowning (const MWWorld::Ptr& ptr, float duration, bool isKnockedOut, bool isPlayer);

View File

@ -29,4 +29,12 @@ namespace MWMechanics
const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects(); const MWMechanics::MagicEffects& effects = actor.getClass().getCreatureStats(actor).getMagicEffects();
return effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() > 0; return effects.get(ESM::MagicEffect::WaterWalking).getMagnitude() > 0;
} }
CreatureCustomDataResetter::CreatureCustomDataResetter(const MWWorld::Ptr& ptr) : mPtr(ptr) {}
CreatureCustomDataResetter::~CreatureCustomDataResetter()
{
if(!mPtr.isEmpty())
mPtr.getRefData().setCustomData({});
}
} }

View File

@ -86,6 +86,14 @@ namespace MWMechanics
template void modifyBaseInventory<ESM::Creature>(const std::string& actorId, const std::string& itemId, int amount); template void modifyBaseInventory<ESM::Creature>(const std::string& actorId, const std::string& itemId, int amount);
template void modifyBaseInventory<ESM::NPC>(const std::string& actorId, const std::string& itemId, int amount); template void modifyBaseInventory<ESM::NPC>(const std::string& actorId, const std::string& itemId, int amount);
template void modifyBaseInventory<ESM::Container>(const std::string& containerId, const std::string& itemId, int amount); template void modifyBaseInventory<ESM::Container>(const std::string& containerId, const std::string& itemId, int amount);
struct CreatureCustomDataResetter
{
MWWorld::Ptr mPtr;
CreatureCustomDataResetter(const MWWorld::Ptr& ptr);
~CreatureCustomDataResetter();
};
} }
#endif #endif

View File

@ -7,6 +7,7 @@
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp> #include <components/esm/esmwriter.hpp>
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
@ -22,7 +23,7 @@ namespace MWMechanics
mTalkedTo (false), mAlarmed (false), mAttacked (false), mTalkedTo (false), mAlarmed (false), mAttacked (false),
mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false),
mHitRecovery(false), mBlock(false), mMovementFlags(0), mHitRecovery(false), mBlock(false), mMovementFlags(0),
mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1), mFallHeight(0), mLastRestock(0,0), mGoldPool(0), mActorId(-1), mHitAttemptActorId(-1),
mDeathAnimation(-1), mTimeOfDeath(), mSideMovementAngle(0), mLevel (0) mDeathAnimation(-1), mTimeOfDeath(), mSideMovementAngle(0), mLevel (0)
{ {
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
@ -146,7 +147,7 @@ namespace MWMechanics
mAttributes[index] = value; mAttributes[index] = value;
if (index == ESM::Attribute::Intelligence) if (index == ESM::Attribute::Intelligence)
mRecalcMagicka = true; recalculateMagicka();
else if (index == ESM::Attribute::Strength || else if (index == ESM::Attribute::Strength ||
index == ESM::Attribute::Willpower || index == ESM::Attribute::Willpower ||
index == ESM::Attribute::Agility || index == ESM::Attribute::Agility ||
@ -208,11 +209,10 @@ namespace MWMechanics
void CreatureStats::modifyMagicEffects(const MagicEffects &effects) void CreatureStats::modifyMagicEffects(const MagicEffects &effects)
{ {
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier() bool recalc = effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier() != mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier();
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier())
mRecalcMagicka = true;
mMagicEffects.setModifiers(effects); mMagicEffects.setModifiers(effects);
if(recalc)
recalculateMagicka();
} }
void CreatureStats::setAiSetting (AiSetting index, Stat<int> value) void CreatureStats::setAiSetting (AiSetting index, Stat<int> value)
@ -400,19 +400,26 @@ namespace MWMechanics
return height; return height;
} }
bool CreatureStats::needToRecalcDynamicStats() void CreatureStats::recalculateMagicka()
{ {
if (mRecalcMagicka) auto world = MWBase::Environment::get().getWorld();
{ float intelligence = getAttribute(ESM::Attribute::Intelligence).getModified();
mRecalcMagicka = false;
return true;
}
return false;
}
void CreatureStats::setNeedRecalcDynamicStats(bool val) float base = 1.f;
{ const auto& player = world->getPlayerPtr();
mRecalcMagicka = val; if (this == &player.getClass().getCreatureStats(player))
base = world->getStore().get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
else
base = world->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
double magickaFactor = base + mMagicEffects.get(EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
DynamicStat<float> magicka = getMagicka();
float diff = (static_cast<int>(magickaFactor*intelligence)) - magicka.getBase();
float currentToBaseRatio = magicka.getBase() > 0 ? magicka.getCurrent() / magicka.getBase() : 0;
magicka.setModified(magicka.getModified() + diff, 0);
magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true);
setMagicka(magicka);
} }
void CreatureStats::setKnockedDown(bool value) void CreatureStats::setKnockedDown(bool value)
@ -532,7 +539,6 @@ namespace MWMechanics
state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?) state.mFallHeight = mFallHeight; // TODO: vertical velocity (move from PhysicActor to CreatureStats?)
state.mLastHitObject = mLastHitObject; state.mLastHitObject = mLastHitObject;
state.mLastHitAttemptObject = mLastHitAttemptObject; state.mLastHitAttemptObject = mLastHitAttemptObject;
state.mRecalcDynamicStats = mRecalcMagicka;
state.mDrawState = mDrawState; state.mDrawState = mDrawState;
state.mLevel = mLevel; state.mLevel = mLevel;
state.mActorId = mActorId; state.mActorId = mActorId;
@ -586,7 +592,6 @@ namespace MWMechanics
mFallHeight = state.mFallHeight; mFallHeight = state.mFallHeight;
mLastHitObject = state.mLastHitObject; mLastHitObject = state.mLastHitObject;
mLastHitAttemptObject = state.mLastHitAttemptObject; mLastHitAttemptObject = state.mLastHitAttemptObject;
mRecalcMagicka = state.mRecalcDynamicStats;
mDrawState = DrawState_(state.mDrawState); mDrawState = DrawState_(state.mDrawState);
mLevel = state.mLevel; mLevel = state.mLevel;
mActorId = state.mActorId; mActorId = state.mActorId;
@ -627,6 +632,8 @@ namespace MWMechanics
if (state.mHasAiSettings) if (state.mHasAiSettings)
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
mAiSettings[i].readState(state.mAiSettings[i]); mAiSettings[i].readState(state.mAiSettings[i]);
if(state.mRecalcDynamicStats)
recalculateMagicka();
} }
void CreatureStats::setLastRestockTime(MWWorld::TimeStamp tradeTime) void CreatureStats::setLastRestockTime(MWWorld::TimeStamp tradeTime)

View File

@ -65,8 +65,6 @@ namespace MWMechanics
std::string mLastHitObject; // The last object to hit this actor std::string mLastHitObject; // The last object to hit this actor
std::string mLastHitAttemptObject; // The last object to attempt to hit this actor std::string mLastHitAttemptObject; // The last object to attempt to hit this actor
bool mRecalcMagicka;
// For merchants: the last time items were restocked and gold pool refilled. // For merchants: the last time items were restocked and gold pool refilled.
MWWorld::TimeStamp mLastRestock; MWWorld::TimeStamp mLastRestock;
@ -103,8 +101,7 @@ namespace MWMechanics
DrawState_ getDrawState() const; DrawState_ getDrawState() const;
void setDrawState(DrawState_ state); void setDrawState(DrawState_ state);
bool needToRecalcDynamicStats(); void recalculateMagicka();
void setNeedRecalcDynamicStats(bool val);
float getFallHeight() const; float getFallHeight() const;
void addToFallHeight(float height); void addToFallHeight(float height);

View File

@ -77,7 +77,7 @@ namespace MWMechanics
MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr); MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats (ptr);
MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats (ptr); MWMechanics::NpcStats& npcStats = ptr.getClass().getNpcStats (ptr);
npcStats.setNeedRecalcDynamicStats(true); npcStats.recalculateMagicka();
const ESM::NPC *player = ptr.get<ESM::NPC>()->mBase; const ESM::NPC *player = ptr.get<ESM::NPC>()->mBase;
@ -222,7 +222,6 @@ namespace MWMechanics
// forced update and current value adjustments // forced update and current value adjustments
mActors.updateActor (ptr, 0); mActors.updateActor (ptr, 0);
mActors.updateActor (ptr, 0);
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
{ {

View File

@ -279,7 +279,7 @@ namespace
namespace MWMechanics namespace MWMechanics
{ {
void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ActiveSpells::ActiveSpellParams& spellParams, ESM::ActiveEffect& effect, bool& invalid, bool& receivedMagicDamage) void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, const ActiveSpells::ActiveSpellParams& spellParams, ESM::ActiveEffect& effect, bool& invalid, bool& receivedMagicDamage, bool& recalculateMagicka)
{ {
const auto world = MWBase::Environment::get().getWorld(); const auto world = MWBase::Environment::get().getWorld();
bool godmode = target == getPlayer() && world->getGodModeState(); bool godmode = target == getPlayer() && world->getGodModeState();
@ -609,7 +609,7 @@ void applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, co
fortifySkill(target, effect, effect.mMagnitude); fortifySkill(target, effect, effect.mMagnitude);
break; break;
case ESM::MagicEffect::FortifyMaximumMagicka: case ESM::MagicEffect::FortifyMaximumMagicka:
target.getClass().getCreatureStats(target).setNeedRecalcDynamicStats(true); recalculateMagicka = true;
break; break;
case ESM::MagicEffect::AbsorbHealth: case ESM::MagicEffect::AbsorbHealth:
case ESM::MagicEffect::AbsorbMagicka: case ESM::MagicEffect::AbsorbMagicka:
@ -687,13 +687,14 @@ bool applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, Ac
const auto world = MWBase::Environment::get().getWorld(); const auto world = MWBase::Environment::get().getWorld();
bool invalid = false; bool invalid = false;
bool receivedMagicDamage = false; bool receivedMagicDamage = false;
bool recalculateMagicka = false;
if(effect.mEffectId == ESM::MagicEffect::Corprus && spellParams.shouldWorsen()) if(effect.mEffectId == ESM::MagicEffect::Corprus && spellParams.shouldWorsen())
{ {
spellParams.worsen(); spellParams.worsen();
for(auto& otherEffect : spellParams.getEffects()) for(auto& otherEffect : spellParams.getEffects())
{ {
if(isCorprusEffect(otherEffect)) if(isCorprusEffect(otherEffect))
applyMagicEffect(target, caster, spellParams, otherEffect, invalid, receivedMagicDamage); applyMagicEffect(target, caster, spellParams, otherEffect, invalid, receivedMagicDamage, recalculateMagicka);
} }
if(target == getPlayer()) if(target == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicCorprusWorsens}");
@ -815,7 +816,7 @@ bool applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, Ac
if(effect.mEffectId == ESM::MagicEffect::Corprus) if(effect.mEffectId == ESM::MagicEffect::Corprus)
spellParams.worsen(); spellParams.worsen();
else else
applyMagicEffect(target, caster, spellParams, effect, invalid, receivedMagicDamage); applyMagicEffect(target, caster, spellParams, effect, invalid, receivedMagicDamage, recalculateMagicka);
effect.mMagnitude = magnitude; effect.mMagnitude = magnitude;
magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(effect.mMagnitude - oldMagnitude)); magnitudes.add(EffectKey(effect.mEffectId, effect.mArg), EffectParam(effect.mMagnitude - oldMagnitude));
} }
@ -832,6 +833,8 @@ bool applyMagicEffect(const MWWorld::Ptr& target, const MWWorld::Ptr& caster, Ac
effect.mFlags |= ESM::ActiveEffect::Flag_Applied | ESM::ActiveEffect::Flag_Remove; effect.mFlags |= ESM::ActiveEffect::Flag_Applied | ESM::ActiveEffect::Flag_Remove;
if (receivedMagicDamage && target == getPlayer()) if (receivedMagicDamage && target == getPlayer())
MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); MWBase::Environment::get().getWindowManager()->activateHitOverlay(false);
if(recalculateMagicka)
target.getClass().getCreatureStats(target).recalculateMagicka();
return false; return false;
} }
@ -981,7 +984,7 @@ void removeMagicEffect(const MWWorld::Ptr& target, ActiveSpells::ActiveSpellPara
fortifySkill(target, effect, -effect.mMagnitude); fortifySkill(target, effect, -effect.mMagnitude);
break; break;
case ESM::MagicEffect::FortifyMaximumMagicka: case ESM::MagicEffect::FortifyMaximumMagicka:
target.getClass().getCreatureStats(target).setNeedRecalcDynamicStats(true); target.getClass().getCreatureStats(target).recalculateMagicka();
break; break;
case ESM::MagicEffect::AbsorbAttribute: case ESM::MagicEffect::AbsorbAttribute:
{ {