mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 20:19:57 +00:00
Restore dynamic stats for actors in inactive cells (bug #1875)
This commit is contained in:
parent
0e06a25f21
commit
8af021d729
12 changed files with 72 additions and 14 deletions
|
@ -1,6 +1,7 @@
|
|||
0.45.0
|
||||
------
|
||||
|
||||
Bug #1875: Actors in inactive cells don't heal from resting
|
||||
Bug #1990: Sunrise/sunset not set correct
|
||||
Bug #2131: Lustidrike's spell misses the player every time
|
||||
Bug #2222: Fatigue's effect on selling price is backwards
|
||||
|
|
|
@ -90,6 +90,8 @@ namespace MWBase
|
|||
virtual void setPlayerClass (const ESM::Class& class_) = 0;
|
||||
///< Set player class to custom class.
|
||||
|
||||
virtual void restoreDynamicStats(MWWorld::Ptr actor, bool sleep) = 0;
|
||||
|
||||
virtual void rest(bool sleep) = 0;
|
||||
///< If the player is sleeping or waiting, this should be called every hour.
|
||||
/// @param sleep is the player sleeping or waiting?
|
||||
|
|
|
@ -571,6 +571,8 @@ namespace MWBase
|
|||
|
||||
virtual bool isPlayerInJail() const = 0;
|
||||
|
||||
virtual void rest() = 0;
|
||||
|
||||
virtual void setPlayerTraveling(bool traveling) = 0;
|
||||
virtual bool isPlayerTraveling() const = 0;
|
||||
|
||||
|
|
|
@ -545,10 +545,10 @@ namespace MWMechanics
|
|||
|
||||
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;
|
||||
|
||||
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
|
||||
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
if (sleep)
|
||||
|
@ -565,12 +565,6 @@ namespace MWMechanics
|
|||
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.
|
||||
// In that case stop here and don't try to restore.
|
||||
DynamicStat<float> fatigue = stats.getFatigue();
|
||||
|
@ -582,6 +576,12 @@ namespace MWMechanics
|
|||
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->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);
|
||||
x *= fEndFatigueMult * endurance;
|
||||
|
||||
|
@ -1667,6 +1667,7 @@ namespace MWMechanics
|
|||
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||
continue;
|
||||
|
||||
if (!sleep || iter->first == player)
|
||||
restoreDynamicStats(iter->first, sleep);
|
||||
|
||||
if ((!iter->first.getRefData().getBaseNode()) ||
|
||||
|
|
|
@ -453,9 +453,17 @@ namespace MWMechanics
|
|||
|
||||
void MechanicsManager::rest(bool sleep)
|
||||
{
|
||||
if (sleep)
|
||||
MWBase::Environment::get().getWorld()->rest();
|
||||
|
||||
mActors.rest(sleep);
|
||||
}
|
||||
|
||||
void MechanicsManager::restoreDynamicStats(MWWorld::Ptr actor, bool sleep)
|
||||
{
|
||||
mActors.restoreDynamicStats(actor, sleep);
|
||||
}
|
||||
|
||||
int MechanicsManager::getHoursToRest() const
|
||||
{
|
||||
return mActors.getHoursToRest(mWatched);
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace MWMechanics
|
|||
virtual void setPlayerClass (const ESM::Class& class_);
|
||||
///< Set player class to custom class.
|
||||
|
||||
virtual void restoreDynamicStats(MWWorld::Ptr actor, bool sleep);
|
||||
|
||||
virtual void rest(bool sleep);
|
||||
///< If the player is sleeping or waiting, this should be called every hour.
|
||||
/// @param sleep is the player sleeping or waiting?
|
||||
|
|
|
@ -151,6 +151,19 @@ MWWorld::CellStore *MWWorld::Cells::getInterior (const std::string& name)
|
|||
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)
|
||||
{
|
||||
if (id.mPaged)
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace MWWorld
|
|||
|
||||
/// @note name must be lower case
|
||||
Ptr getPtr (const std::string& name);
|
||||
void rest ();
|
||||
|
||||
/// Get all Ptrs referencing \a name in exterior cells
|
||||
/// @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 "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/world.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()
|
||||
{
|
||||
if (mState == State_Loaded)
|
||||
|
|
|
@ -183,6 +183,8 @@ namespace MWWorld
|
|||
/// @return updated MWWorld::Ptr with the new CellStore pointer set.
|
||||
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.
|
||||
/// @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.
|
||||
|
|
|
@ -3118,6 +3118,10 @@ namespace MWWorld
|
|||
return closestMarker;
|
||||
}
|
||||
|
||||
void World::rest()
|
||||
{
|
||||
mCells.rest();
|
||||
}
|
||||
|
||||
void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,
|
||||
const std::string& id)
|
||||
|
|
|
@ -552,11 +552,9 @@ namespace MWWorld
|
|||
void enableActorCollision(const MWWorld::Ptr& actor, bool enable) override;
|
||||
|
||||
RestPermitted canRest() const override;
|
||||
///< check if the player is allowed to rest \n
|
||||
/// 0 - yes \n
|
||||
/// 1 - only waiting \n
|
||||
/// 2 - player is underwater \n
|
||||
/// 3 - enemies are nearby (not implemented)
|
||||
///< check if the player is allowed to rest
|
||||
|
||||
void rest() override;
|
||||
|
||||
/// \todo Probably shouldn't be here
|
||||
MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) override;
|
||||
|
|
Loading…
Reference in a new issue