Restore dynamic stats for actors in inactive cells (bug #1875)

pull/541/head
Andrei Kortunov 6 years ago
parent 0e06a25f21
commit 8af021d729

@ -1,6 +1,7 @@
0.45.0 0.45.0
------ ------
Bug #1875: Actors in inactive cells don't heal from resting
Bug #1990: Sunrise/sunset not set correct Bug #1990: Sunrise/sunset not set correct
Bug #2131: Lustidrike's spell misses the player every time Bug #2131: Lustidrike's spell misses the player every time
Bug #2222: Fatigue's effect on selling price is backwards Bug #2222: Fatigue's effect on selling price is backwards

@ -90,6 +90,8 @@ namespace MWBase
virtual void setPlayerClass (const ESM::Class& class_) = 0; virtual void setPlayerClass (const ESM::Class& class_) = 0;
///< Set player class to custom class. ///< Set player class to custom class.
virtual void restoreDynamicStats(MWWorld::Ptr actor, bool sleep) = 0;
virtual void rest(bool sleep) = 0; virtual void rest(bool sleep) = 0;
///< If the player is sleeping or waiting, this should be called every hour. ///< If the player is sleeping or waiting, this should be called every hour.
/// @param sleep is the player sleeping or waiting? /// @param sleep is the player sleeping or waiting?

@ -571,6 +571,8 @@ namespace MWBase
virtual bool isPlayerInJail() const = 0; virtual bool isPlayerInJail() const = 0;
virtual void rest() = 0;
virtual void setPlayerTraveling(bool traveling) = 0; virtual void setPlayerTraveling(bool traveling) = 0;
virtual bool isPlayerTraveling() const = 0; virtual bool isPlayerTraveling() const = 0;

@ -545,10 +545,10 @@ namespace MWMechanics
void Actors::restoreDynamicStats (const MWWorld::Ptr& ptr, bool sleep) void Actors::restoreDynamicStats (const MWWorld::Ptr& ptr, bool sleep)
{ {
if (ptr.getClass().getCreatureStats(ptr).isDead()) MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
if (stats.isDead())
return; return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (sleep) if (sleep)
@ -565,12 +565,6 @@ namespace MWMechanics
stats.setMagicka(stat); stats.setMagicka(stat);
} }
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
// Current fatigue can be above base value due to a fortify effect. // Current fatigue can be above base value due to a fortify effect.
// In that case stop here and don't try to restore. // In that case stop here and don't try to restore.
DynamicStat<float> fatigue = stats.getFatigue(); DynamicStat<float> fatigue = stats.getFatigue();
@ -582,6 +576,12 @@ namespace MWMechanics
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat (); float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
float fEndFatigueMult = settings.find("fEndFatigueMult")->mValue.getFloat (); float fEndFatigueMult = settings.find("fEndFatigueMult")->mValue.getFloat ();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
float normalizedEncumbrance = ptr.getClass().getNormalizedEncumbrance(ptr);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance; x *= fEndFatigueMult * endurance;
@ -1667,7 +1667,8 @@ namespace MWMechanics
if (iter->first.getClass().getCreatureStats(iter->first).isDead()) if (iter->first.getClass().getCreatureStats(iter->first).isDead())
continue; continue;
restoreDynamicStats(iter->first, sleep); if (!sleep || iter->first == player)
restoreDynamicStats(iter->first, sleep);
if ((!iter->first.getRefData().getBaseNode()) || if ((!iter->first.getRefData().getBaseNode()) ||
(playerPos - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance) (playerPos - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance)

@ -453,9 +453,17 @@ namespace MWMechanics
void MechanicsManager::rest(bool sleep) void MechanicsManager::rest(bool sleep)
{ {
if (sleep)
MWBase::Environment::get().getWorld()->rest();
mActors.rest(sleep); mActors.rest(sleep);
} }
void MechanicsManager::restoreDynamicStats(MWWorld::Ptr actor, bool sleep)
{
mActors.restoreDynamicStats(actor, sleep);
}
int MechanicsManager::getHoursToRest() const int MechanicsManager::getHoursToRest() const
{ {
return mActors.getHoursToRest(mWatched); return mActors.getHoursToRest(mWatched);

@ -91,6 +91,8 @@ namespace MWMechanics
virtual void setPlayerClass (const ESM::Class& class_); virtual void setPlayerClass (const ESM::Class& class_);
///< Set player class to custom class. ///< Set player class to custom class.
virtual void restoreDynamicStats(MWWorld::Ptr actor, bool sleep);
virtual void rest(bool sleep); virtual void rest(bool sleep);
///< If the player is sleeping or waiting, this should be called every hour. ///< If the player is sleeping or waiting, this should be called every hour.
/// @param sleep is the player sleeping or waiting? /// @param sleep is the player sleeping or waiting?

@ -151,6 +151,19 @@ MWWorld::CellStore *MWWorld::Cells::getInterior (const std::string& name)
return &result->second; return &result->second;
} }
void MWWorld::Cells::rest ()
{
for (auto &interior : mInteriors)
{
interior.second.rest();
}
for (auto &exterior : mExteriors)
{
exterior.second.rest();
}
}
MWWorld::CellStore *MWWorld::Cells::getCell (const ESM::CellId& id) MWWorld::CellStore *MWWorld::Cells::getCell (const ESM::CellId& id)
{ {
if (id.mPaged) if (id.mPaged)

@ -61,6 +61,7 @@ namespace MWWorld
/// @note name must be lower case /// @note name must be lower case
Ptr getPtr (const std::string& name); Ptr getPtr (const std::string& name);
void rest ();
/// Get all Ptrs referencing \a name in exterior cells /// Get all Ptrs referencing \a name in exterior cells
/// @note Due to the current implementation of getPtr this only supports one Ptr per cell. /// @note Due to the current implementation of getPtr this only supports one Ptr per cell.

@ -17,6 +17,7 @@
#include <components/esm/doorstate.hpp> #include <components/esm/doorstate.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/creaturestats.hpp"
@ -954,6 +955,29 @@ namespace MWWorld
} }
} }
void CellStore::rest()
{
if (mState == State_Loaded)
{
for (CellRefList<ESM::Creature>::List::iterator it (mCreatures.mList.begin()); it!=mCreatures.mList.end(); ++it)
{
Ptr ptr = getCurrentPtr(&*it);
if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0)
{
MWBase::Environment::get().getMechanicsManager()->restoreDynamicStats(ptr, true);
}
}
for (CellRefList<ESM::NPC>::List::iterator it (mNpcs.mList.begin()); it!=mNpcs.mList.end(); ++it)
{
Ptr ptr = getCurrentPtr(&*it);
if (!ptr.isEmpty() && ptr.getRefData().getCount() > 0)
{
MWBase::Environment::get().getMechanicsManager()->restoreDynamicStats(ptr, true);
}
}
}
}
void CellStore::respawn() void CellStore::respawn()
{ {
if (mState == State_Loaded) if (mState == State_Loaded)

@ -183,6 +183,8 @@ namespace MWWorld
/// @return updated MWWorld::Ptr with the new CellStore pointer set. /// @return updated MWWorld::Ptr with the new CellStore pointer set.
MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo); MWWorld::Ptr moveTo(const MWWorld::Ptr& object, MWWorld::CellStore* cellToMoveTo);
void rest();
/// Make a copy of the given object and insert it into this cell. /// Make a copy of the given object and insert it into this cell.
/// @note If you get a linker error here, this means the given type can not be inserted into a cell. /// @note If you get a linker error here, this means the given type can not be inserted into a cell.
/// The supported types are defined at the bottom of this file. /// The supported types are defined at the bottom of this file.

@ -3118,6 +3118,10 @@ namespace MWWorld
return closestMarker; return closestMarker;
} }
void World::rest()
{
mCells.rest();
}
void World::teleportToClosestMarker (const MWWorld::Ptr& ptr, void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id) const std::string& id)

@ -552,11 +552,9 @@ namespace MWWorld
void enableActorCollision(const MWWorld::Ptr& actor, bool enable) override; void enableActorCollision(const MWWorld::Ptr& actor, bool enable) override;
RestPermitted canRest() const override; RestPermitted canRest() const override;
///< check if the player is allowed to rest \n ///< check if the player is allowed to rest
/// 0 - yes \n
/// 1 - only waiting \n void rest() override;
/// 2 - player is underwater \n
/// 3 - enemies are nearby (not implemented)
/// \todo Probably shouldn't be here /// \todo Probably shouldn't be here
MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) override; MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) override;

Loading…
Cancel
Save