mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 21:45:35 +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
|
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…
Reference in a new issue