diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 2d535f57b..e68a5d398 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -546,7 +546,7 @@ namespace MWMechanics float diff = (static_cast(magickaFactor*intelligence)) - magicka.getBase(); float currentToBaseRatio = (magicka.getCurrent() / magicka.getBase()); magicka.setModified(magicka.getModified() + diff, 0); - magicka.setCurrent(magicka.getBase() * currentToBaseRatio); + magicka.setCurrent(magicka.getBase() * currentToBaseRatio, false, true); creatureStats.setMagicka(magicka); } @@ -577,8 +577,14 @@ namespace MWMechanics float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr); if (normalizedEncumbrance > 1) normalizedEncumbrance = 1; + + // Current fatigue can be above base value due to a fortify effect. + // In that case stop here and don't try to restore. + DynamicStat fatigue = stats.getFatigue(); + if (fatigue.getCurrent() >= fatigue.getBase()) + return; - // restore fatigue + // Restore fatigue float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat (); float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat (); float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat (); @@ -586,7 +592,6 @@ namespace MWMechanics float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); x *= fEndFatigueMult * endurance; - DynamicStat fatigue = stats.getFatigue(); fatigue.setCurrent (fatigue.getCurrent() + 3600 * x); stats.setFatigue (fatigue); } @@ -598,16 +603,20 @@ namespace MWMechanics MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); - int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); + // Current fatigue can be above base value due to a fortify effect. + // In that case stop here and don't try to restore. + DynamicStat fatigue = stats.getFatigue(); + if (fatigue.getCurrent() >= fatigue.getBase()) + return; - // restore fatigue + // Restore fatigue + int endurance = stats.getAttribute(ESM::Attribute::Endurance).getModified(); const MWWorld::Store& settings = MWBase::Environment::get().getWorld()->getStore().get(); static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat (); static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat (); float x = fFatigueReturnBase + fFatigueReturnMult * endurance; - DynamicStat fatigue = stats.getFatigue(); fatigue.setCurrent (fatigue.getCurrent() + duration * x); stats.setFatigue (fatigue); } @@ -723,7 +732,7 @@ namespace MWMechanics for(int i = 0;i < 3;++i) { DynamicStat stat = creatureStats.getDynamic(i); - stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).getMagnitude() - + stat.setCurrentModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).getMagnitude() - effects.get(ESM::MagicEffect::DrainHealth+i).getMagnitude(), // Magicka can be decreased below zero due to a fortify effect wearing off // Fatigue can be decreased below zero meaning the actor will be knocked out diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 49823d7a5..d1128860c 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -195,6 +195,7 @@ namespace MWMechanics mDead = true; mDynamic[index].setModifier(0); + mDynamic[index].setCurrentModifier(0); mDynamic[index].setCurrent(0); if (MWBase::Environment::get().getWorld()->getGodModeState()) diff --git a/apps/openmw/mwmechanics/stat.cpp b/apps/openmw/mwmechanics/stat.cpp index 41c5bac5a..f53052a28 100644 --- a/apps/openmw/mwmechanics/stat.cpp +++ b/apps/openmw/mwmechanics/stat.cpp @@ -5,11 +5,11 @@ namespace MWMechanics { template - Stat::Stat() : mBase (0), mModified (0) {} + Stat::Stat() : mBase (0), mModified (0), mCurrentModified (0) {} template - Stat::Stat(T base) : mBase (base), mModified (base) {} + Stat::Stat(T base) : mBase (base), mModified (base), mCurrentModified (base) {} template - Stat::Stat(T base, T modified) : mBase (base), mModified (modified) {} + Stat::Stat(T base, T modified) : mBase (base), mModified (modified), mCurrentModified (modified) {} template const T& Stat::getBase() const @@ -22,23 +22,42 @@ namespace MWMechanics { return std::max(static_cast(0), mModified); } + + template + T Stat::getCurrentModified() const + { + return mCurrentModified; + } + template T Stat::getModifier() const { return mModified-mBase; } + + template + T Stat::getCurrentModifier() const + { + return mCurrentModified - mModified; + } + template void Stat::set (const T& value) { + T diff = value - mBase; mBase = mModified = value; + mCurrentModified += diff; } + template void Stat::setBase (const T& value) { T diff = value - mBase; mBase = value; mModified += diff; + mCurrentModified += diff; } + template void Stat::setModified (T value, const T& min, const T& max) { @@ -57,24 +76,39 @@ namespace MWMechanics mModified = value; mBase += diff; + mCurrentModified += diff; } + + template + void Stat::setCurrentModified(T value) + { + mCurrentModified = value; + } + template void Stat::setModifier (const T& modifier) { mModified = mBase + modifier; } + template + void Stat::setCurrentModifier(const T& modifier) + { + mCurrentModified = mModified + modifier; + } + template void Stat::writeState (ESM::StatState& state) const { state.mBase = mBase; - state.mMod = mModified; + state.mMod = mCurrentModified; } template void Stat::readState (const ESM::StatState& state) { mBase = state.mBase; - mModified = state.mMod; + mModified = state.mBase; + mCurrentModified = state.mMod; } @@ -98,6 +132,12 @@ namespace MWMechanics { return mStatic.getModified(); } + template + T DynamicStat::getCurrentModified() const + { + return mStatic.getCurrentModified(); + } + template const T& DynamicStat::getCurrent() const { @@ -127,14 +167,21 @@ namespace MWMechanics mCurrent = getModified(); } template - void DynamicStat::setCurrent (const T& value, bool allowDecreaseBelowZero) + void DynamicStat::setCurrentModified(T value) + { + mStatic.setCurrentModified(value); + } + template + void DynamicStat::setCurrent (const T& value, bool allowDecreaseBelowZero, bool allowIncreaseAboveModified) { if (value > mCurrent) { // increase - mCurrent = value; - - if (mCurrent > getModified()) + if (value <= getModified() || allowIncreaseAboveModified) + mCurrent = value; + else if (mCurrent > getModified()) + return; + else mCurrent = getModified(); } else if (value > 0 || allowDecreaseBelowZero) @@ -156,6 +203,16 @@ namespace MWMechanics setCurrent (getCurrent()+diff, allowCurrentDecreaseBelowZero); } + template + void DynamicStat::setCurrentModifier(const T& modifier, bool allowCurrentDecreaseBelowZero) + { + T diff = modifier - mStatic.getCurrentModifier(); + mStatic.setCurrentModifier(modifier); + + // The (modifier > 0) check here allows increase over modified only if the modifier is positive (a fortify effect is active). + setCurrent (getCurrent() + diff, allowCurrentDecreaseBelowZero, (modifier > 0)); + } + template void DynamicStat::writeState (ESM::StatState& state) const { diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 5b5800634..751b80b9c 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -17,6 +17,7 @@ namespace MWMechanics { T mBase; T mModified; + T mCurrentModified; public: typedef T Type; @@ -28,7 +29,9 @@ namespace MWMechanics const T& getBase() const; T getModified() const; + T getCurrentModified() const; T getModifier() const; + T getCurrentModifier() const; /// Set base and modified to \a value. void set (const T& value); @@ -36,9 +39,15 @@ namespace MWMechanics /// Set base and adjust modified accordingly. void setBase (const T& value); - /// Set modified value an adjust base accordingly. + /// Set modified value and adjust base accordingly. void setModified (T value, const T& min, const T& max = std::numeric_limits::max()); + + /// Set "current modified," used for drain and fortify. Unlike the regular modifier + /// this just adds and subtracts from the current value without changing the maximum. + void setCurrentModified(T value); + void setModifier (const T& modifier); + void setCurrentModifier (const T& modifier); void writeState (ESM::StatState& state) const; void readState (const ESM::StatState& state); @@ -73,6 +82,7 @@ namespace MWMechanics const T& getBase() const; T getModified() const; + T getCurrentModified() const; const T& getCurrent() const; /// Set base, modified and current to \a value. @@ -81,11 +91,16 @@ namespace MWMechanics /// Set base and adjust modified accordingly. void setBase (const T& value); - /// Set modified value an adjust base accordingly. + /// Set modified value and adjust base accordingly. void setModified (T value, const T& min, const T& max = std::numeric_limits::max()); - void setCurrent (const T& value, bool allowDecreaseBelowZero = false); - void setModifier (const T& modifier, bool allowCurrentDecreaseBelowZero=false); + /// Set "current modified," used for drain and fortify. Unlike the regular modifier + /// this just adds and subtracts from the current value without changing the maximum. + void setCurrentModified(T value); + + void setCurrent (const T& value, bool allowDecreaseBelowZero = false, bool allowIncreaseAboveModified = false); + void setModifier (const T& modifier, bool allowCurrentToDecreaseBelowZero=false); + void setCurrentModifier (const T& modifier, bool allowCurrentToDecreaseBelowZero = false); void writeState (ESM::StatState& state) const; void readState (const ESM::StatState& state); diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index fadc99b66..28e6f95dd 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -261,6 +261,7 @@ namespace MWScript .getDynamic (mIndex)); stat.setModified (diff + stat.getModified(), 0); + stat.setCurrentModified (diff + stat.getCurrentModified()); stat.setCurrent (diff + current);