From 95651857f3eb90a5c6e0ee1879c7f2154c471508 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 14 Jan 2014 02:52:34 +0100 Subject: [PATCH] Fix code duplication --- apps/openmw/mwbase/mechanicsmanager.hpp | 3 + apps/openmw/mwgui/waitdialog.cpp | 38 +-------- apps/openmw/mwmechanics/actors.cpp | 77 +++++++++++++------ apps/openmw/mwmechanics/actors.hpp | 3 + .../mwmechanics/mechanicsmanagerimp.cpp | 5 ++ .../mwmechanics/mechanicsmanagerimp.hpp | 3 + 6 files changed, 69 insertions(+), 60 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index d1472de38..726c8cf04 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -80,6 +80,9 @@ namespace MWBase ///< If the player is sleeping or waiting, this should be called every hour. /// @param sleep is the player sleeping or waiting? + virtual int getHoursToRest() const = 0; + ///< Calculate how many hours the player needs to rest in order to be fully healed + virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying) = 0; ///< This is used by every service to determine the price of objects given the trading skills of the player and NPC. diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 5058e53ee..1ad703790 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -144,43 +144,7 @@ namespace MWGui void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender) { - // we need to sleep for a specific time, and since that isn't calculated yet, we'll do it here - // I'm making the assumption here that the # of hours rested is calculated when rest is started - // TODO: the rougher logic here (calculating the hourly deltas) should really go into helper funcs elsewhere - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player); - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); - - float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1; - - bool stunted = (stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0); - float fRestMagicMult = store.get().find("fRestMagicMult")->getFloat(); - float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified(); - - // this massive duplication is why it has to be put into helper functions instead - float fFatigueReturnBase = store.get().find("fFatigueReturnBase")->getFloat(); - float fFatigueReturnMult = store.get().find("fFatigueReturnMult")->getFloat(); - float fEndFatigueMult = store.get().find("fEndFatigueMult")->getFloat(); - float capacity = MWWorld::Class::get(player).getCapacity(player); - float encumbrance = MWWorld::Class::get(player).getEncumbrance(player); - float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); - if (normalizedEncumbrance > 1) - normalizedEncumbrance = 1; - float hourlyFatigueDelta = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance); - hourlyFatigueDelta *= 3600 * fEndFatigueMult * stats.getAttribute(ESM::Attribute::Endurance).getModified(); - - float healthHours = hourlyHealthDelta >= 0.0 - ? (stats.getHealth().getBase() - stats.getHealth().getCurrent()) / hourlyHealthDelta - : 1.0f; - float magickaHours = stunted ? 0.0 : - hourlyMagickaDelta >= 0.0 - ? (stats.getMagicka().getBase() - stats.getMagicka().getCurrent()) / hourlyMagickaDelta - : 1.0f; - float fatigueHours = hourlyFatigueDelta >= 0.0 - ? (stats.getFatigue().getBase() - stats.getFatigue().getCurrent()) / hourlyFatigueDelta - : 1.0f; - - int autoHours = int(std::ceil( std::max(std::max(healthHours, magickaHours), std::max(fatigueHours, 1.0f)) )); // this should use a variadic max if possible + int autoHours = MWBase::Environment::get().getMechanicsManager()->getHoursToRest(); startWaiting(autoHours); } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0fc7210b2..a0be8357d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -82,6 +82,23 @@ bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate) return false; } +void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float& magicka) +{ + MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); + const MWWorld::Store& settings = MWBase::Environment::get().getWorld()->getStore().get(); + + bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0; + int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); + + health = 0.1 * endurance; + + magicka = 0; + if (!stunted) + { + float fRestMagicMult = settings.find("fRestMagicMult")->getFloat (); + magicka = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified(); + } +} } @@ -261,37 +278,32 @@ namespace MWMechanics { if (ptr.getClass().getCreatureStats(ptr).isDead()) return; - CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr); + + MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr); const MWWorld::Store& settings = MWBase::Environment::get().getWorld()->getStore().get(); - int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); - - float capacity = MWWorld::Class::get(ptr).getCapacity(ptr); - float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr); - float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); - if (normalizedEncumbrance > 1) - normalizedEncumbrance = 1; - if (sleep) { - // the actor is sleeping, restore health and magicka - bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0; + float health, magicka; + getRestorationPerHourOfSleep(ptr, health, magicka); - DynamicStat health = stats.getHealth(); - health.setCurrent (health.getCurrent() + 0.1 * endurance); - stats.setHealth (health); + DynamicStat stat = stats.getHealth(); + stat.setCurrent(stat.getCurrent() + health); + stats.setHealth(stat); - if (!stunted) - { - float fRestMagicMult = settings.find("fRestMagicMult")->getFloat (); - - DynamicStat magicka = stats.getMagicka(); - magicka.setCurrent (magicka.getCurrent() - + fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified()); - stats.setMagicka (magicka); - } + stat = stats.getMagicka(); + stat.setCurrent(stat.getCurrent() + magicka); + stats.setMagicka(stat); } + int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified (); + + float capacity = ptr.getClass().getCapacity(ptr); + float encumbrance = ptr.getClass().getEncumbrance(ptr); + float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity); + if (normalizedEncumbrance > 1) + normalizedEncumbrance = 1; + // restore fatigue float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat (); float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat (); @@ -303,6 +315,7 @@ namespace MWMechanics DynamicStat fatigue = stats.getFatigue(); fatigue.setCurrent (fatigue.getCurrent() + duration * x); stats.setFatigue (fatigue); + } void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr, float duration) @@ -851,6 +864,24 @@ namespace MWMechanics calculateRestoration(iter->first, 3600, sleep); } + int Actors::getHoursToRest(const MWWorld::Ptr &ptr) const + { + float healthPerHour, magickaPerHour; + getRestorationPerHourOfSleep(ptr, healthPerHour, magickaPerHour); + + CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); + + float healthHours = healthPerHour >= 0 + ? (stats.getHealth().getModified() - stats.getHealth().getCurrent()) / healthPerHour + : 1.0f; + float magickaHours = magickaPerHour >= 0 + ? (stats.getMagicka().getModified() - stats.getMagicka().getCurrent()) / magickaPerHour + : 1.0f; + + int autoHours = std::ceil(std::max(1.f, std::max(healthHours, magickaHours))); + return autoHours; + } + int Actors::countDeaths (const std::string& id) const { std::map::const_iterator iter = mDeathCount.find(id); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 382aa5400..b7544dad4 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -81,6 +81,9 @@ namespace MWMechanics void restoreDynamicStats(bool sleep); ///< If the player is sleeping, this should be called every hour. + + int getHoursToRest(const MWWorld::Ptr& ptr) const; + ///< Calculate how many hours the given actor needs to rest in order to be fully healed int countDeaths (const std::string& id) const; ///< Return the number of deaths for actors with the given ID. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 456b3a8f9..d6dd73bd0 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -375,6 +375,11 @@ namespace MWMechanics mActors.restoreDynamicStats (sleep); } + int MechanicsManager::getHoursToRest() const + { + return mActors.getHoursToRest(mWatched); + } + void MechanicsManager::setPlayerName (const std::string& name) { MWBase::World *world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 25e556e6a..469123df9 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -85,6 +85,9 @@ namespace MWMechanics ///< If the player is sleeping or waiting, this should be called every hour. /// @param sleep is the player sleeping or waiting? + virtual int getHoursToRest() const; + ///< Calculate how many hours the player needs to rest in order to be fully healed + virtual int getBarterOffer(const MWWorld::Ptr& ptr,int basePrice, bool buying); ///< This is used by every service to determine the price of objects given the trading skills of the player and NPC.