Skip to content

Commit

Permalink
Restore dynamic stats for actors in inactive cells (bug OpenMW#1875)
Browse files Browse the repository at this point in the history
  • Loading branch information
akortunov committed Sep 26, 2018
1 parent 0e06a25 commit 8af021d
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions apps/openmw/mwbase/mechanicsmanager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
2 changes: 2 additions & 0 deletions apps/openmw/mwbase/world.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
19 changes: 10 additions & 9 deletions apps/openmw/mwmechanics/actors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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();
Expand All @@ -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;

Expand Down Expand Up @@ -1667,7 +1667,8 @@ namespace MWMechanics
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
continue;

restoreDynamicStats(iter->first, sleep);
if (!sleep || iter->first == player)
restoreDynamicStats(iter->first, sleep);

if ((!iter->first.getRefData().getBaseNode()) ||
(playerPos - iter->first.getRefData().getPosition().asVec3()).length2() > sqrAiProcessingDistance)
Expand Down
8 changes: 8 additions & 0 deletions apps/openmw/mwmechanics/mechanicsmanagerimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions apps/openmw/mwmechanics/mechanicsmanagerimp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
13 changes: 13 additions & 0 deletions apps/openmw/mwworld/cells.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions apps/openmw/mwworld/cells.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
24 changes: 24 additions & 0 deletions apps/openmw/mwworld/cellstore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions apps/openmw/mwworld/cellstore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions apps/openmw/mwworld/worldimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3118,6 +3118,10 @@ namespace MWWorld
return closestMarker;
}

void World::rest()
{
mCells.rest();
}

void World::teleportToClosestMarker (const MWWorld::Ptr& ptr,
const std::string& id)
Expand Down
8 changes: 3 additions & 5 deletions apps/openmw/mwworld/worldimp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 8af021d

Please sign in to comment.