From 30ee3c5cf6e98982743de01cff0d1c8adbd57cb5 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 15 Oct 2013 15:23:42 -0400 Subject: [PATCH 1/4] Equipped torches and lights run out of fuel --- apps/openmw/mwclass/light.cpp | 47 ++++++++++++++++++++++++++++++ apps/openmw/mwclass/light.hpp | 8 +++++ apps/openmw/mwmechanics/actors.cpp | 32 ++++++++++++++++++++ apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwworld/class.cpp | 10 +++++++ apps/openmw/mwworld/class.hpp | 8 +++++ 6 files changed, 107 insertions(+) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 7eefc6167..21d83d62e 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -16,12 +16,27 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/physicssystem.hpp" +#include "../mwworld/customdata.hpp" #include "../mwgui/tooltips.hpp" #include "../mwrender/objects.hpp" #include "../mwrender/renderinginterface.hpp" +namespace +{ + struct CustomData : public MWWorld::CustomData + { + float mTime; + ///< Time remaining + + virtual MWWorld::CustomData *clone() const + { + return new CustomData (*this); + } + }; +} + namespace MWClass { void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -182,6 +197,24 @@ namespace MWClass return action; } + void Light::setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const + { + ensureCustomData(ptr); + + float &timeCharge = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + + // TODO time it in vanilla, see if 1 second is really one unit. + timeCharge = duration; + } + + float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const + { + ensureCustomData(ptr); + + ESM::CellRef &ref = ptr.getCellRef(); + return dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + } + MWWorld::Ptr Light::copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const { @@ -191,6 +224,20 @@ namespace MWClass return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell); } + void Light::ensureCustomData (const MWWorld::Ptr& ptr) const + { + if (!ptr.getRefData().getCustomData()) + { + MWWorld::LiveCellRef *ref = ptr.get(); + + CustomData *data = new CustomData; + + data->mTime = ref->mBase->mData.mTime; + + ptr.getRefData().setCustomData(data); + } + } + bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const { return npcServices & ESM::NPC::Lights; diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 79d662763..c15228a6a 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -10,6 +10,8 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + void ensureCustomData (const MWWorld::Ptr& ptr) const; + public: virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const; @@ -56,6 +58,12 @@ namespace MWClass const; ///< Generate action for using via inventory menu + virtual void setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const; + ///< Sets the remaining duration of the object. + + virtual float getRemainingUsageTime (const MWWorld::Ptr& ptr) const; + ///< Returns the remaining duration of the object. + virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual float getWeight (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ca26e88ce..fb632159c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -42,7 +42,13 @@ namespace MWMechanics void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused) { if(!paused) + { updateDrowning(ptr, duration); + + // Only update the light of the player. + if(ptr.getRefData().getHandle()=="player") + updateEquippedLight(ptr, duration); + } } void Actors::adjustMagicEffects (const MWWorld::Ptr& creature) @@ -196,6 +202,32 @@ namespace MWMechanics stats.setTimeToStartDrowning(20); } + void Actors::updateEquippedLight (const MWWorld::Ptr& ptr, float duration) + { + //If holding a light... + MWWorld::InventoryStore &inventoryStore = MWWorld::Class::get(ptr).getInventoryStore(ptr); + MWWorld::ContainerStoreIterator heldIter = + inventoryStore.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + + if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) + { + // ... then use some "fuel" from the timer + float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); + + // If it's already -1, then it should be an infinite light. + // TODO see what happens for other negative values. + if(timeRemaining >= 0.0f) + { + timeRemaining -= duration; + + if(timeRemaining > 0.0f) + heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); + else + heldIter->getRefData().setCount(0); // remove it + } + } + } + Actors::Actors() : mDuration (0) {} void Actors::addActor (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 69878a000..a77e52ba3 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -44,6 +44,8 @@ namespace MWMechanics void updateDrowning (const MWWorld::Ptr& ptr, float duration); + void updateEquippedLight (const MWWorld::Ptr& ptr, float duration); + public: Actors(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c739ea831..c73662bb1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -132,6 +132,16 @@ namespace MWWorld throw std::runtime_error ("class does not support unlocking"); } + void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const + { + throw std::runtime_error ("class does not support time-based uses."); + } + + float Class::getRemainingUsageTime (const Ptr& ptr) const + { + throw std::runtime_error ("class does not support time-based uses."); + } + std::string Class::getScript (const Ptr& ptr) const { return ""; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 28e37cbf3..1b7b8518a 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -156,6 +156,14 @@ namespace MWWorld virtual void unlock (const Ptr& ptr) const; ///< Unlock object (default implementation: throw an exception) + virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const; + ///< Sets the remaining duration of the object, such as an equippable light + /// source. (default implementation: throw an exception) + + virtual float getRemainingUsageTime (const Ptr& ptr) const; + ///< Returns the remaining duration of the object, such as an equippable light + /// source. (default implementation: throw an exception) + virtual std::string getScript (const Ptr& ptr) const; ///< Return name of the script attached to ptr (default implementation: return an empty /// string). From 2643214ca6370a102ce69cb9788b9ef656006c50 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 15 Oct 2013 20:56:42 -0400 Subject: [PATCH 2/4] Lights extinguish underwater --- apps/openmw/mwclass/light.cpp | 6 ++-- apps/openmw/mwmechanics/actors.cpp | 44 ++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 21d83d62e..4cf4ae37e 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -201,10 +201,8 @@ namespace MWClass { ensureCustomData(ptr); - float &timeCharge = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; - - // TODO time it in vanilla, see if 1 second is really one unit. - timeCharge = duration; + float &timeRemaining = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; + timeRemaining = duration; } float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index fb632159c..0adc97606 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -44,10 +44,7 @@ namespace MWMechanics if(!paused) { updateDrowning(ptr, duration); - - // Only update the light of the player. - if(ptr.getRefData().getHandle()=="player") - updateEquippedLight(ptr, duration); + updateEquippedLight(ptr, duration); } } @@ -211,19 +208,36 @@ namespace MWMechanics if(heldIter.getType() == MWWorld::ContainerStore::Type_Light) { - // ... then use some "fuel" from the timer - float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); - - // If it's already -1, then it should be an infinite light. - // TODO see what happens for other negative values. - if(timeRemaining >= 0.0f) + // Use time from the player's light + bool isPlayer = ptr.getRefData().getHandle()=="player"; + if(isPlayer) { - timeRemaining -= duration; + float timeRemaining = heldIter->getClass().getRemainingUsageTime(*heldIter); - if(timeRemaining > 0.0f) - heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); - else - heldIter->getRefData().setCount(0); // remove it + // -1 is infinite light source. Other negative values are treated as 0. + if(timeRemaining != -1.0f) + { + timeRemaining -= duration; + + if(timeRemaining > 0.0f) + heldIter->getClass().setRemainingUsageTime(*heldIter, timeRemaining); + else + { + heldIter->getRefData().setCount(0); // remove it + return; + } + } + } + + // Both NPC and player lights extinguish in water. + if(MWBase::Environment::get().getWorld()->isSwimming(ptr)) + { + heldIter->getRefData().setCount(0); // remove it + + // ...But, only the player makes a sound. + if(isPlayer) + MWBase::Environment::get().getSoundManager()->playSound("torch out", + 1.0, 1.0, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_NoEnv); } } } From e11da5c0a3aec68078dd967fc0582f7908311941 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 16 Oct 2013 15:13:36 -0400 Subject: [PATCH 3/4] Added a constructor to Light CustomData --- apps/openmw/mwclass/light.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 4cf4ae37e..906ae8a1c 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -30,6 +30,13 @@ namespace float mTime; ///< Time remaining + CustomData(MWWorld::Ptr ptr) + { + MWWorld::LiveCellRef *ref = ptr.get(); + mTime = ref->mBase->mData.mTime; + } + ///< Constructs this CustomData from the base values for Ptr. + virtual MWWorld::CustomData *clone() const { return new CustomData (*this); @@ -225,15 +232,7 @@ namespace MWClass void Light::ensureCustomData (const MWWorld::Ptr& ptr) const { if (!ptr.getRefData().getCustomData()) - { - MWWorld::LiveCellRef *ref = ptr.get(); - - CustomData *data = new CustomData; - - data->mTime = ref->mBase->mData.mTime; - - ptr.getRefData().setCustomData(data); - } + ptr.getRefData().setCustomData(new CustomData(ptr)); } bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const From 65818155d8bb34640942ede25c3d9128baf07b08 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 16 Oct 2013 15:14:35 -0400 Subject: [PATCH 4/4] Fixed punctuation consistency --- apps/openmw/mwworld/class.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index c73662bb1..da98f99f1 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -134,12 +134,12 @@ namespace MWWorld void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const { - throw std::runtime_error ("class does not support time-based uses."); + throw std::runtime_error ("class does not support time-based uses"); } float Class::getRemainingUsageTime (const Ptr& ptr) const { - throw std::runtime_error ("class does not support time-based uses."); + throw std::runtime_error ("class does not support time-based uses"); } std::string Class::getScript (const Ptr& ptr) const