From e8dcd747416eacd5e098609b2bf6f9c598ec9584 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 19 Nov 2013 16:42:24 +0100 Subject: [PATCH] Recharge enchanted items in player's inventory over time --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 ++ .../mwmechanics/mechanicsmanagerimp.cpp | 8 +++++ .../mwmechanics/mechanicsmanagerimp.hpp | 2 ++ apps/openmw/mwworld/inventorystore.cpp | 36 +++++++++++++++++++ apps/openmw/mwworld/inventorystore.hpp | 8 +++++ apps/openmw/mwworld/worldimp.cpp | 2 ++ 6 files changed, 58 insertions(+) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 24dc569d8..c8db20325 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -59,6 +59,8 @@ namespace MWBase /// \param paused In game type does not currently advance (this usually means some GUI /// component is up). + virtual void advanceTime (float duration) = 0; + virtual void setPlayerName (const std::string& name) = 0; ///< Set player name. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index e1a7ac123..8ae413b0a 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -213,6 +213,14 @@ namespace MWMechanics mWatched = ptr; } + void MechanicsManager::advanceTime (float duration) + { + // Uses ingame time, but scaled to real time + duration /= MWBase::Environment::get().getWorld()->getTimeScaleFactor(); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + player.getClass().getInventoryStore(player).rechargeItems(duration); + } + void MechanicsManager::update(float duration, bool paused) { if(!mWatched.isEmpty()) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 42656d5ab..57309a6f0 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -63,6 +63,8 @@ namespace MWMechanics /// \param paused In game type does not currently advance (this usually means some GUI /// component is up). + virtual void advanceTime (float duration); + virtual void setPlayerName (const std::string& name); ///< Set player name. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 6483b32b2..349c664c3 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -88,6 +88,8 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr, autoEquip(actorPtr); } + updateRechargingItems(); + return retVal; } @@ -459,6 +461,8 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor MWBase::Environment::get().getWindowManager()->unsetSelectedSpell(); } + updateRechargingItems(); + return retCount; } @@ -577,3 +581,35 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito } } } + +void MWWorld::InventoryStore::updateRechargingItems() +{ + mRechargingItems.clear(); + for (ContainerStoreIterator it = begin(); it != end(); ++it) + { + if (it->getClass().getEnchantment(*it) != "") + { + const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get().find( + it->getClass().getEnchantment(*it)); + if (enchantment->mData.mType == ESM::Enchantment::WhenUsed + || enchantment->mData.mType == ESM::Enchantment::WhenStrikes) + mRechargingItems.push_back(std::make_pair(it, enchantment->mData.mCharge)); + } + } +} + +void MWWorld::InventoryStore::rechargeItems(float duration) +{ + for (TRechargingItems::iterator it = mRechargingItems.begin(); it != mRechargingItems.end(); ++it) + { + if (it->first->getCellRef().mEnchantmentCharge == -1 + || it->first->getCellRef().mEnchantmentCharge == it->second) + continue; + + static float fMagicItemRechargePerSecond = MWBase::Environment::get().getWorld()->getStore().get().find( + "fMagicItemRechargePerSecond")->getFloat(); + + it->first->getCellRef().mEnchantmentCharge = std::min (it->first->getCellRef().mEnchantmentCharge + fMagicItemRechargePerSecond * duration, + it->second); + } +} diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index f53ce8efb..58ff50ead 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -92,11 +92,16 @@ namespace MWWorld // selected magic item (for using enchantments of type "Cast once" or "Cast when used") ContainerStoreIterator mSelectedEnchantItem; + // (item, max charge) + typedef std::vector > TRechargingItems; + TRechargingItems mRechargingItems; + void copySlots (const InventoryStore& store); void initSlots (TSlots& slots_); void updateMagicEffects(const Ptr& actor); + void updateRechargingItems(); void fireEquipmentChangedEvent(); @@ -172,6 +177,9 @@ namespace MWWorld ///< Set a listener for various events, see \a InventoryStoreListener void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor); + + void rechargeItems (float duration); + /// Restore charge on enchanted items. Note this should only be done for the player. }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7dec848ad..7702ea250 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -607,6 +607,8 @@ namespace MWWorld void World::advanceTime (double hours) { + MWBase::Environment::get().getMechanicsManager()->advanceTime(hours*3600); + mWeatherManager->advanceTime (hours); hours += mGlobalVariables->getFloat ("gamehour");