From 7ba6bdb56c01a67fdef62c00cfaeb8c1c79e2eaf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 3 Aug 2010 22:43:53 +0200 Subject: [PATCH 01/19] prepared InterpreterContext for activation implementation --- apps/openmw/mwscript/interpretercontext.cpp | 117 +++++++++++++------- apps/openmw/mwscript/interpretercontext.hpp | 72 +++++++----- apps/openmw/mwscript/miscextensions.cpp | 30 ++--- 3 files changed, 138 insertions(+), 81 deletions(-) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index f2dc57dd0..404aa69a6 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -27,9 +27,9 @@ namespace MWScript { if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - + return mReference; - } + } } const MWWorld::Ptr InterpreterContext::getReference ( @@ -43,21 +43,22 @@ namespace MWScript { if (mReference.isEmpty()) throw std::runtime_error ("no implicit reference"); - + return mReference; - } + } } - + InterpreterContext::InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference) - : mEnvironment (environment), mLocals (locals), mReference (reference) + : mEnvironment (environment), mLocals (locals), mReference (reference), + mActivationHandled (false) {} int InterpreterContext::getLocalShort (int index) const { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mShorts.at (index); } @@ -65,7 +66,7 @@ namespace MWScript { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mLongs.at (index); } @@ -73,7 +74,7 @@ namespace MWScript { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - + return mLocals->mFloats.at (index); } @@ -90,45 +91,45 @@ namespace MWScript if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - mLocals->mLongs.at (index) = value; + mLocals->mLongs.at (index) = value; } void InterpreterContext::setLocalFloat (int index, float value) { if (!mLocals) throw std::runtime_error ("local variables not available in this context"); - - mLocals->mFloats.at (index) = value; + + mLocals->mFloats.at (index) = value; } - + void InterpreterContext::messageBox (const std::string& message, const std::vector& buttons) { std::cout << "message box: " << message << std::endl; - - if (!buttons.empty()) + + if (!buttons.empty()) std::cerr << "error: message box buttons not supported" << std::endl; } - + bool InterpreterContext::menuMode() { return mEnvironment.mWindowManager->isGuiMode(); } - + int InterpreterContext::getGlobalShort (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mShort; + return mEnvironment.mWorld->getGlobalVariable (name).mShort; } int InterpreterContext::getGlobalLong (const std::string& name) const { // a global long is internally a float. - return mEnvironment.mWorld->getGlobalVariable (name).mLong; + return mEnvironment.mWorld->getGlobalVariable (name).mLong; } float InterpreterContext::getGlobalFloat (const std::string& name) const { - return mEnvironment.mWorld->getGlobalVariable (name).mFloat; + return mEnvironment.mWorld->getGlobalVariable (name).mFloat; } void InterpreterContext::setGlobalShort (const std::string& name, int value) @@ -166,83 +167,117 @@ namespace MWScript else mEnvironment.mWorld->getGlobalVariable (name).mFloat = value; } - + bool InterpreterContext::isScriptRunning (const std::string& name) const { return mEnvironment.mGlobalScripts->isRunning (name); } - + void InterpreterContext::startScript (const std::string& name) { mEnvironment.mGlobalScripts->addScript (name); } - + void InterpreterContext::stopScript (const std::string& name) { mEnvironment.mGlobalScripts->removeScript (name); } - + float InterpreterContext::getDistance (const std::string& name, const std::string& id) const { // TODO handle exterior cells (when ref and ref2 are located in different cells) const MWWorld::Ptr ref2 = getReference (id, false); - + const MWWorld::Ptr ref = mEnvironment.mWorld->getPtr (name, true); - + double diff[3]; - - for (int i=0; i<3; ++i) + + for (int i=0; i<3; ++i) diff[i] = ref.getCellRef().pos.pos[i] - ref2.getCellRef().pos.pos[i]; - + return std::sqrt (diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]); } - - bool InterpreterContext::hasBeenActivated() const + + bool InterpreterContext::hasBeenActivated (const MWWorld::Ptr& ptr) { + if (!mActivated.isEmpty() && mActivated==ptr) + { + mActivationHandled = true; + return true; + } + return false; } - + + bool InterpreterContext::hasActivationBeenHandled() const + { + return mActivationHandled; + } + + void InterpreterContext::activate (const MWWorld::Ptr& ptr, + boost::shared_ptr action) + { + mActivated = ptr; + mActivationHandled = false; + mAction = action; + } + + void InterpreterContext::executeActivation() + { + if (!mAction.get()) + throw std::runtime_error ("activation failed, because no action to perform"); + + mAction->execute (mEnvironment); + mActivationHandled = true; + } + + void InterpreterContext::clearActivation() + { + mActivated = MWWorld::Ptr(); + mActivationHandled = false; + mAction.reset(); + } + float InterpreterContext::getSecondsPassed() const { return mEnvironment.mFrameDuration; } - + bool InterpreterContext::isDisabled (const std::string& id) const { const MWWorld::Ptr ref = getReference (id, false); return !ref.getRefData().isEnabled(); } - + void InterpreterContext::enable (const std::string& id) { MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->enable (ref); } - + void InterpreterContext::disable (const std::string& id) { - MWWorld::Ptr ref = getReference (id, false); + MWWorld::Ptr ref = getReference (id, false); mEnvironment.mWorld->disable (ref); } - + MWGui::WindowManager& InterpreterContext::getWindowManager() { return *mEnvironment.mWindowManager; } - + MWWorld::World& InterpreterContext::getWorld() { return *mEnvironment.mWorld; } - + MWSound::SoundManager& InterpreterContext::getSoundManager() { return *mEnvironment.mSoundManager; } - + MWWorld::Ptr InterpreterContext::getReference() { return getReference ("", true); } } - diff --git a/apps/openmw/mwscript/interpretercontext.hpp b/apps/openmw/mwscript/interpretercontext.hpp index ee35964b8..e63c4838c 100644 --- a/apps/openmw/mwscript/interpretercontext.hpp +++ b/apps/openmw/mwscript/interpretercontext.hpp @@ -1,11 +1,14 @@ #ifndef GAME_SCRIPT_INTERPRETERCONTEXT_H #define GAME_SCRIPT_INTERPRETERCONTEXT_H +#include + #include #include "../mwworld/ptr.hpp" #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "../mwworld/action.hpp" namespace MWSound { @@ -17,80 +20,95 @@ namespace MWScript struct Locals; class InterpreterContext : public Interpreter::Context - { + { MWWorld::Environment& mEnvironment; Locals *mLocals; MWWorld::Ptr mReference; - - + + MWWorld::Ptr mActivated; + bool mActivationHandled; + boost::shared_ptr mAction; + MWWorld::Ptr getReference (const std::string& id, bool activeOnly); const MWWorld::Ptr getReference (const std::string& id, bool activeOnly) const; public: - - InterpreterContext (MWWorld::Environment& environment, + + InterpreterContext (MWWorld::Environment& environment, MWScript::Locals *locals, MWWorld::Ptr reference); ///< The ownership of \a locals is not transferred. 0-pointer allowed. - + virtual int getLocalShort (int index) const; virtual int getLocalLong (int index) const; virtual float getLocalFloat (int index) const; - virtual void setLocalShort (int index, int value); + virtual void setLocalShort (int index, int value); virtual void setLocalLong (int index, int value); virtual void setLocalFloat (int index, float value); - + virtual void messageBox (const std::string& message, - const std::vector& buttons); + const std::vector& buttons); virtual bool menuMode(); - + virtual int getGlobalShort (const std::string& name) const; virtual int getGlobalLong (const std::string& name) const; virtual float getGlobalFloat (const std::string& name) const; - virtual void setGlobalShort (const std::string& name, int value); + virtual void setGlobalShort (const std::string& name, int value); - virtual void setGlobalLong (const std::string& name, int value); + virtual void setGlobalLong (const std::string& name, int value); virtual void setGlobalFloat (const std::string& name, float value); - + virtual bool isScriptRunning (const std::string& name) const; - + virtual void startScript (const std::string& name); - + virtual void stopScript (const std::string& name); - + virtual float getDistance (const std::string& name, const std::string& id = "") const; - - virtual bool hasBeenActivated() const; - + + bool hasBeenActivated (const MWWorld::Ptr& ptr); + ///< \attention Calling this function for the right reference will mark the action as + /// been handled. + + bool hasActivationBeenHandled() const; + + void activate (const MWWorld::Ptr& ptr, boost::shared_ptr action); + ///< Store reference acted upon and action. The actual execution of the action does not + /// take place here. + + void executeActivation(); + ///< Execute the action defined by the last activate call. + + void clearActivation(); + ///< Discard the action defined by the last activate call. + virtual float getSecondsPassed() const; - + virtual bool isDisabled (const std::string& id = "") const; - + virtual void enable (const std::string& id = ""); - + virtual void disable (const std::string& id = ""); - + MWWorld::World& getWorld(); - + MWSound::SoundManager& getSoundManager(); MWGui::WindowManager& getWindowManager(); - + MWWorld::Ptr getReference(); ///< Reference, that the script is running from (can be empty) }; } #endif - - diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 3d865d56f..6abd22454 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -16,37 +16,41 @@ namespace MWScript class OpXBox : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { runtime.push (0); - } + } }; - + class OpOnActivate : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { - runtime.push (static_cast ( - runtime.getContext()).hasBeenActivated()); - } + InterpreterContext& context = + static_cast (runtime.getContext()); + + MWWorld::Ptr ptr = context.getReference(); + + runtime.push (context.hasBeenActivated (ptr)); + } }; - + const int opcodeXBox = 0x200000c; - const int opcodeOnActivate = 0x200000d; - + const int opcodeOnActivate = 0x200000d; + void registerExtensions (Compiler::Extensions& extensions) { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate); } - + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeXBox, new OpXBox); interpreter.installSegment5 (opcodeOnActivate, new OpOnActivate); - } - } + } + } } From e0a3b1b1db7521b7e1cf0f3f52a5d321b925791d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 4 Aug 2010 14:04:22 +0200 Subject: [PATCH 02/19] implemented item count --- apps/openmw/mwrender/cellimp.cpp | 19 +++++++-------- apps/openmw/mwworld/refdata.hpp | 41 ++++++++++++++++++++------------ apps/openmw/mwworld/world.cpp | 2 +- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index 50047c1d9..121f17383 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -48,24 +48,25 @@ void insertObj(CellRenderImp& cellRender, ESMS::LiveCellRefmodel; - + cellRender.insertBegin(liveRef.ref); cellRender.insertMesh(headModel); //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the right place cellRender.insertMesh("meshes\\" + store.bodyParts.find(bodyRaceID + "chest")->model); - + liveRef.mData.setHandle (cellRender.insertEnd (liveRef.mData.isEnabled())); } - + template void insertCellRefList (CellRenderImp& cellRender, const ESMS::ESMStore& store, T& cellRefList) { - for(typename T::List::iterator it = cellRefList.list.begin(); - it != cellRefList.list.end(); it++) - { - insertObj (cellRender, *it, store); - } + for(typename T::List::iterator it = cellRefList.list.begin(); + it != cellRefList.list.end(); it++) + { + if (it->mData.getCount()) + insertObj (cellRender, *it, store); + } } void CellRenderImp::insertCell(ESMS::CellStore &cell, const ESMS::ESMStore& store) @@ -92,5 +93,3 @@ void CellRenderImp::insertCell(ESMS::CellStore &cell, const ES insertCellRefList (*this, store, cell.statics); insertCellRefList (*this, store, cell.weapons); } - - diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 919f4f8a0..8f76635f9 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -22,28 +22,34 @@ namespace MWWorld class RefData { std::string mHandle; - + MWScript::Locals mLocals; // if we find the overhead of heaving a locals // object in the refdata of refs without a script, // we can make this a pointer later. bool mHasLocals; bool mEnabled; - + int mCount; // 0: deleted + // we are using shared pointer here to avoid having to create custom copy-constructor, // assignment operator and destructor. As a consequence though copying a RefData object // manually will probably give unexcepted results. This is not a problem since RefData // are never copied outside of container operations. boost::shared_ptr mCreatureStats; - + public: - - RefData() : mHasLocals (false), mEnabled (true) {} - + + RefData() : mHasLocals (false), mEnabled (true), mCount (1) {} + std::string getHandle() { return mHandle; } - + + int getCount() const + { + return mCount; + } + void setLocals (const ESM::Script& script) { if (!mHasLocals) @@ -52,37 +58,42 @@ namespace MWWorld mHasLocals = true; } } - + void setHandle (const std::string& handle) { mHandle = handle; } - + + void setCount (int count) + { + mCount = count; + } + MWScript::Locals& getLocals() { return mLocals; } - + bool isEnabled() const { return mEnabled; } - + void enable() { mEnabled = true; } - + void disable() { mEnabled = true; } - + boost::shared_ptr& getCreatureStats() { - return mCreatureStats; + return mCreatureStats; } - }; + }; } #endif diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 73a9d6ad3..430f518ec 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -25,7 +25,7 @@ namespace cellRefList.list.begin()); iter!=cellRefList.list.end(); ++iter) { - if (!iter->base->script.empty()) + if (!iter->base->script.empty() && iter->mData.getCount()) { if (const ESM::Script *script = store.scripts.find (iter->base->script)) { From ee7570f7e7f825a4becd93491dab052441711e41 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 4 Aug 2010 14:37:23 +0200 Subject: [PATCH 03/19] added containerstore --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwclass/container.cpp | 16 ++++++++++++++++ apps/openmw/mwclass/container.hpp | 4 ++++ apps/openmw/mwclass/creature.cpp | 16 ++++++++++++++++ apps/openmw/mwclass/creature.hpp | 4 ++++ apps/openmw/mwclass/npc.cpp | 15 +++++++++++++++ apps/openmw/mwclass/npc.hpp | 4 ++++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 6 ++++++ apps/openmw/mwworld/containerstore.hpp | 26 ++++++++++++++++++++++++++ apps/openmw/mwworld/refdata.hpp | 9 +++++++++ 11 files changed, 106 insertions(+) create mode 100644 apps/openmw/mwworld/containerstore.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0fe62ea4f..c9112b0ee 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -92,6 +92,7 @@ set(GAMEWORLD_HEADER mwworld/action.hpp mwworld/nullaction.hpp mwworld/actionteleport.hpp + mwworld/containerstore.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index a6df294e7..1048329be 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -17,6 +17,22 @@ namespace MWClass return ref->base->name; } + MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) + const + { + if (!ptr.getRefData().getContainerStore().get()) + { + boost::shared_ptr > store ( + new MWWorld::ContainerStore); + + // TODO add initial content + + ptr.getRefData().getContainerStore() = store; + } + + return *ptr.getRefData().getContainerStore(); + } + void Container::registerSelf() { boost::shared_ptr instance (new Container); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 0b907b2b7..6f5b872b9 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual MWWorld::ContainerStore& getContainerStore ( + const MWWorld::Ptr& ptr) const; + ///< Return container store + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 198c0e72f..d7aa2d357 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -44,6 +44,22 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) + const + { + if (!ptr.getRefData().getContainerStore().get()) + { + boost::shared_ptr > store ( + new MWWorld::ContainerStore); + + // TODO add initial content + + ptr.getRefData().getContainerStore() = store; + } + + return *ptr.getRefData().getContainerStore(); + } + void Creature::registerSelf() { boost::shared_ptr instance (new Creature); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 5056501c5..4dbbcc386 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -16,6 +16,10 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual MWWorld::ContainerStore& getContainerStore ( + const MWWorld::Ptr& ptr) const; + ///< Return container store + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index dbb7f2a93..f5547a934 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -44,6 +44,21 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr) const + { + if (!ptr.getRefData().getContainerStore().get()) + { + boost::shared_ptr > store ( + new MWWorld::ContainerStore); + + // TODO add initial content + + ptr.getRefData().getContainerStore() = store; + } + + return *ptr.getRefData().getContainerStore(); + } + void Npc::registerSelf() { boost::shared_ptr instance (new Npc); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 76c56de40..54536f180 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -16,6 +16,10 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual MWWorld::ContainerStore& getContainerStore ( + const MWWorld::Ptr& ptr) const; + ///< Return container store + static void registerSelf(); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 9cca8035e..33c5ff114 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -41,6 +41,11 @@ namespace MWWorld return boost::shared_ptr (new NullAction); } + ContainerStore& Class::getContainerStore (const Ptr& ptr) const + { + throw std::runtime_error ("class does not have a container store"); + } + const Class& Class::get (const std::string& key) { std::map >::const_iterator iter = sClasses.find (key); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 9535786e2..159ff3c5f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -7,6 +7,8 @@ #include #include "action.hpp" +#include "containerstore.hpp" +#include "refdata.hpp" namespace MWMechanics { @@ -58,6 +60,10 @@ namespace MWWorld ///< Generate action for using via inventory menu (default implementation: return a /// null action). + virtual ContainerStore& getContainerStore (const Ptr& ptr) const; + ///< Return container store or throw an exception, if class does not have a + /// container store (default implementation: throw an exceoption) + static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp new file mode 100644 index 000000000..c05bfe156 --- /dev/null +++ b/apps/openmw/mwworld/containerstore.hpp @@ -0,0 +1,26 @@ +#ifndef GAME_MWWORLD_CONTAINERSTORE_H +#define GAME_MWWORLD_CONTAINERSTORE_H + +#include + +namespace MWWorld +{ + template + struct ContainerStore + { + ESMS::CellRefList potions; + ESMS::CellRefList appas; + ESMS::CellRefList armors; + ESMS::CellRefList books; + ESMS::CellRefList clothes; + ESMS::CellRefList ingreds; + ESMS::CellRefList lights; + ESMS::CellRefList lockpicks; + ESMS::CellRefList miscItems; + ESMS::CellRefList probes; + ESMS::CellRefList repairs; + ESMS::CellRefList weapons; + }; +} + +#endif diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 8f76635f9..b041a06cb 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -7,6 +7,8 @@ #include "../mwscript/locals.hpp" +#include "containerstore.hpp" + namespace ESM { class Script; @@ -36,6 +38,8 @@ namespace MWWorld // are never copied outside of container operations. boost::shared_ptr mCreatureStats; + boost::shared_ptr > mContainerStore; + public: RefData() : mHasLocals (false), mEnabled (true), mCount (1) {} @@ -93,6 +97,11 @@ namespace MWWorld { return mCreatureStats; } + + boost::shared_ptr >& getContainerStore() + { + return mContainerStore; + } }; } From 87c84e6fcdc04f1935ba8f10cddf32b5a95a09c4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 13:29:49 +0200 Subject: [PATCH 04/19] limited activation range according to GMST settings --- apps/openmw/engine.cpp | 10 ++++------ apps/openmw/mwworld/world.cpp | 11 +++++++++++ apps/openmw/mwworld/world.hpp | 5 +++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8734ffaad..3c6eb6f16 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -74,22 +74,20 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) if (focusFrameCounter++ == focusUpdateFrame) { - std::pair handle = mEnvironment.mWorld->getMWScene()->getFacedHandle(); + std::string handle = mEnvironment.mWorld->getFacedHandle(); std::string name; - if (!handle.first.empty()) + if (!handle.empty()) { - // TODO compare handle.second with max activation range (from a GMST) - - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle.first); + MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); if (!ptr.isEmpty()) name = MWWorld::Class::get (ptr).getName (ptr); } if (!name.empty()) - std::cout << "Object: " << name << ", distance: " << handle.second << std::endl; + std::cout << "Object: " << name << std::endl; focusFrameCounter = 0; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 73a9d6ad3..94a6758c7 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -600,4 +600,15 @@ namespace MWWorld { mCellChanged = false; } + + std::string World::getFacedHandle() + { + std::pair result = mScene.getFacedHandle(); + + if (result.first.empty() || + result.second>getStore().gameSettings.find ("iMaxActivateDist")->i) + return ""; + + return result.first; + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 354c3603c..d20161698 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -83,8 +83,6 @@ namespace MWWorld ~World(); - MWRender::MWScene* getMWScene() { return &mScene; } - MWRender::PlayerPos& getPlayerPos(); ESMS::ESMStore& getStore(); @@ -133,6 +131,9 @@ namespace MWWorld ///< works only for interior cells currently. void markCellAsUnchanged(); + + std::string getFacedHandle(); + ///< Return handle of the object the player is looking at }; } From 2d695cc8065d2faa4226dbcab2774b99948d9a8d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 13:36:33 +0200 Subject: [PATCH 05/19] routed activate signal from input sub-system to engine-class --- apps/openmw/engine.cpp | 7 ++++++- apps/openmw/engine.hpp | 5 ++++- apps/openmw/mwinput/inputmanager.cpp | 14 ++++++++++---- apps/openmw/mwinput/inputmanager.hpp | 8 +++++++- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 3c6eb6f16..251aeac20 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -253,7 +253,7 @@ void OMW::Engine::go() // Sets up the input system MWInput::MWInputManager input(mOgre, mEnvironment.mWorld->getPlayerPos(), - *mEnvironment.mWindowManager, mDebug); + *mEnvironment.mWindowManager, mDebug, *this); focusFrameCounter = 0; @@ -266,3 +266,8 @@ void OMW::Engine::go() std::cout << "Quitting peacefully.\n"; } + +void OMW::Engine::activate() +{ + std::cout << "activate" << std::endl; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 412c4fa73..62166e050 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -111,12 +111,15 @@ namespace OMW /// Enable verbose script output void enableVerboseScripts(); - + /// Start as a new game. void setNewGame(); /// Initialise and enter main loop. void go(); + + /// Activate the focussed object. + void activate(); }; } diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index f851b43b2..f730150b0 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -17,6 +17,8 @@ #include #include "../mwrender/playerpos.hpp" +#include "../engine.hpp" + #include #include #include @@ -58,6 +60,7 @@ namespace MWInput OEngine::GUI::EventInjectorPtr guiEvents; MWRender::PlayerPos &player; MWGui::WindowManager &windows; + OMW::Engine& mEngine; // Count screenshots. int shotCount; @@ -137,7 +140,7 @@ namespace MWInput void activate() { - + mEngine.activate(); } // Exit program now button (which is disabled in GUI mode) @@ -151,13 +154,15 @@ namespace MWInput InputImpl(OEngine::Render::OgreRenderer &_ogre, MWRender::PlayerPos &_player, MWGui::WindowManager &_windows, - bool debug) + bool debug, + OMW::Engine& engine) : ogre(_ogre), exit(ogre.getWindow()), input(ogre.getWindow(), !debug), poller(input), player(_player), windows(_windows), + mEngine (engine), shotCount(0) { using namespace OEngine::Input; @@ -275,9 +280,10 @@ namespace MWInput MWInputManager::MWInputManager(OEngine::Render::OgreRenderer &ogre, MWRender::PlayerPos &player, MWGui::WindowManager &windows, - bool debug) + bool debug, + OMW::Engine& engine) { - impl = new InputImpl(ogre,player,windows,debug); + impl = new InputImpl(ogre,player,windows,debug, engine); } MWInputManager::~MWInputManager() diff --git a/apps/openmw/mwinput/inputmanager.hpp b/apps/openmw/mwinput/inputmanager.hpp index 094b848ee..554089588 100644 --- a/apps/openmw/mwinput/inputmanager.hpp +++ b/apps/openmw/mwinput/inputmanager.hpp @@ -19,6 +19,11 @@ namespace MWGui class WindowManager; } +namespace OMW +{ + class Engine; +} + namespace MWInput { // Forward declaration of the real implementation. @@ -37,7 +42,8 @@ namespace MWInput MWInputManager(OEngine::Render::OgreRenderer &_ogre, MWRender::PlayerPos &_player, MWGui::WindowManager &_windows, - bool debug); + bool debug, + OMW::Engine& engine); ~MWInputManager(); }; } From f630157bf8222e540e3570722dd011d3d3f701bf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 13:51:26 +0200 Subject: [PATCH 06/19] implemented basic object activation --- apps/openmw/engine.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 251aeac20..4e7b3eef7 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -269,5 +269,19 @@ void OMW::Engine::go() void OMW::Engine::activate() { - std::cout << "activate" << std::endl; + std::string handle = mEnvironment.mWorld->getFacedHandle(); + + if (handle.empty()) + return; + + MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + + if (ptr.isEmpty()) + return; + + boost::shared_ptr action = + MWWorld::Class::get (ptr).activate (ptr, mEnvironment.mWorld->getPlayerPos().getPlayer(), + mEnvironment); + + action->execute (mEnvironment); } From 7a313f24abc0362955ab90dccd4b60dfc4ff029b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 15:40:03 +0200 Subject: [PATCH 07/19] integrated activation into script system --- apps/openmw/engine.cpp | 15 ++++++++++++++- apps/openmw/mwclass/activator.cpp | 8 ++++++++ apps/openmw/mwclass/activator.hpp | 3 +++ apps/openmw/mwclass/apparatus.cpp | 8 ++++++++ apps/openmw/mwclass/apparatus.hpp | 3 +++ apps/openmw/mwclass/armor.cpp | 8 ++++++++ apps/openmw/mwclass/armor.hpp | 3 +++ apps/openmw/mwclass/book.cpp | 8 ++++++++ apps/openmw/mwclass/book.hpp | 3 +++ apps/openmw/mwclass/clothing.cpp | 8 ++++++++ apps/openmw/mwclass/clothing.hpp | 3 +++ apps/openmw/mwclass/container.cpp | 8 ++++++++ apps/openmw/mwclass/container.hpp | 3 +++ apps/openmw/mwclass/creature.cpp | 8 ++++++++ apps/openmw/mwclass/creature.hpp | 3 +++ apps/openmw/mwclass/door.cpp | 8 ++++++++ apps/openmw/mwclass/door.hpp | 3 +++ apps/openmw/mwclass/ingredient.cpp | 8 ++++++++ apps/openmw/mwclass/ingredient.hpp | 3 +++ apps/openmw/mwclass/light.cpp | 8 ++++++++ apps/openmw/mwclass/light.hpp | 3 +++ apps/openmw/mwclass/lockpick.cpp | 8 ++++++++ apps/openmw/mwclass/lockpick.hpp | 3 +++ apps/openmw/mwclass/misc.cpp | 8 ++++++++ apps/openmw/mwclass/misc.hpp | 3 +++ apps/openmw/mwclass/npc.cpp | 8 ++++++++ apps/openmw/mwclass/npc.hpp | 3 +++ apps/openmw/mwclass/potion.cpp | 8 ++++++++ apps/openmw/mwclass/potion.hpp | 3 +++ apps/openmw/mwclass/probe.cpp | 8 ++++++++ apps/openmw/mwclass/probe.hpp | 3 +++ apps/openmw/mwclass/repair.cpp | 8 ++++++++ apps/openmw/mwclass/repair.hpp | 3 +++ apps/openmw/mwclass/weapon.cpp | 8 ++++++++ apps/openmw/mwclass/weapon.hpp | 3 +++ apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 4 ++++ 37 files changed, 210 insertions(+), 1 deletion(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 4e7b3eef7..badb19629 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -279,9 +279,22 @@ void OMW::Engine::activate() if (ptr.isEmpty()) return; + MWScript::InterpreterContext interpreterContext (mEnvironment, + &ptr.getRefData().getLocals(), ptr); + boost::shared_ptr action = MWWorld::Class::get (ptr).activate (ptr, mEnvironment.mWorld->getPlayerPos().getPlayer(), mEnvironment); - action->execute (mEnvironment); + interpreterContext.activate (ptr, action); + + std::string script = MWWorld::Class::get (ptr).getScript (ptr); + + if (!script.empty()) + mScriptManager->run (script, interpreterContext); + + if (!interpreterContext.hasActivationBeenHandled()) + { + interpreterContext.executeActivation(); + } } diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index ff2d559f4..3cdc1f850 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Activator::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Activator::registerSelf() { boost::shared_ptr instance (new Activator); diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 5639117b7..66821a7c5 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 1a936e76b..066eacd3f 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Apparatus::registerSelf() { boost::shared_ptr instance (new Apparatus); diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 96c838e8d..7b3ccff6a 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 1a339c703..786868c81 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -30,6 +30,14 @@ namespace MWClass return ref->base->data.health; } + std::string Armor::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Armor::registerSelf() { boost::shared_ptr instance (new Armor); diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 4a6cd2f75..ebae75a9f 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -19,6 +19,9 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index d16269857..9c0a48409 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Book::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Book::registerSelf() { boost::shared_ptr instance (new Book); diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index b9a03f2e7..d45f569b5 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index a728394d9..2c0d76fb3 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Clothing::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Clothing::registerSelf() { boost::shared_ptr instance (new Clothing); diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 1b8dcf16d..09b66b92d 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index a6df294e7..dd0fc729c 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Container::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Container::registerSelf() { boost::shared_ptr instance (new Container); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index 0b907b2b7..959e6a634 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 198c0e72f..e34f92fb4 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -44,6 +44,14 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + std::string Creature::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Creature::registerSelf() { boost::shared_ptr instance (new Creature); diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 5056501c5..03333a50a 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -16,6 +16,9 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 24710fa4c..2c4bd3562 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -53,6 +53,14 @@ namespace MWClass } } + std::string Door::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Door::registerSelf() { boost::shared_ptr instance (new Door); diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index 28d048633..fa3b6d657 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -17,6 +17,9 @@ namespace MWClass const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; ///< Generate action for activation + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 6ae80c440..81d19b2fa 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Ingredient::registerSelf() { boost::shared_ptr instance (new Ingredient); diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index eed520cb1..c2edd9484 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index bf983259b..98e0b01b4 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -20,6 +20,14 @@ namespace MWClass return ref->base->name; } + std::string Light::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Light::registerSelf() { boost::shared_ptr instance (new Light); diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 8fa53aeaf..08c3ddf7c 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index ee861c30b..ce57e0c99 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Lockpick::registerSelf() { boost::shared_ptr instance (new Lockpick); diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index daff07f85..e009e9fdd 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index eabb7ba7a..dda21aaa7 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Misc::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Misc::registerSelf() { boost::shared_ptr instance (new Misc); diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index d2f685d40..526235aa0 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index dbb7f2a93..2887ad0b5 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -44,6 +44,14 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + std::string Npc::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Npc::registerSelf() { boost::shared_ptr instance (new Npc); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 76c56de40..e0b828f61 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -16,6 +16,9 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 75f2f6ccb..f8e9ee0a0 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Potion::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Potion::registerSelf() { boost::shared_ptr instance (new Potion); diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 350aba156..c851d1b4e 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 65fbf47cb..3c22e4c7f 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Probe::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Probe::registerSelf() { boost::shared_ptr instance (new Probe); diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 1a60f220a..84e93d1ce 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 722baebde..f22b8607a 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -17,6 +17,14 @@ namespace MWClass return ref->base->name; } + std::string Repair::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Repair::registerSelf() { boost::shared_ptr instance (new Repair); diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index e7a9928ed..803e21d51 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 5ca80bcb7..a7fce960c 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -30,6 +30,14 @@ namespace MWClass return ref->base->data.health; } + std::string Weapon::getScript (const MWWorld::Ptr& ptr) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + return ref->base->script; + } + void Weapon::registerSelf() { boost::shared_ptr instance (new Weapon); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 98e5930f8..01b6f8e13 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -19,6 +19,9 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + virtual std::string getScript (const MWWorld::Ptr& ptr) const; + ///< Return name of the script attached to ptr + static void registerSelf(); }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 9cca8035e..267ff7294 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -41,6 +41,11 @@ namespace MWWorld return boost::shared_ptr (new NullAction); } + std::string Class::getScript (const Ptr& ptr) const + { + return ""; + } + const Class& Class::get (const std::string& key) { std::map >::const_iterator iter = sClasses.find (key); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 9535786e2..3f5722ce2 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -58,6 +58,10 @@ namespace MWWorld ///< Generate action for using via inventory menu (default implementation: return a /// null action). + virtual std::string getScript (const Ptr& ptr) const; + ///< Return name of the script attached to ptr (default implementation: return an empty + /// string). + static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. From 15124601aa23927253202a6fe268d4cd7b182cf6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 15:46:50 +0200 Subject: [PATCH 08/19] stop local scripts from being run twice in case of activation --- apps/openmw/engine.cpp | 18 +++++++++++++----- apps/openmw/engine.hpp | 3 +++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index badb19629..b67bcd0ac 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -38,13 +38,18 @@ void OMW::Engine::executeLocalScripts() mEnvironment.mWorld->getLocalScripts().begin()); iter!=mEnvironment.mWorld->getLocalScripts().end(); ++iter) { - MWScript::InterpreterContext interpreterContext (mEnvironment, - &iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second)); - mScriptManager->run (iter->first, interpreterContext); + if (!mIgnoreLocalPtr.isEmpty() && mIgnoreLocalPtr!=iter->second) + { + MWScript::InterpreterContext interpreterContext (mEnvironment, + &iter->second.getRefData().getLocals(), MWWorld::Ptr (iter->second)); + mScriptManager->run (iter->first, interpreterContext); - if (mEnvironment.mWorld->hasCellChanged()) - break; + if (mEnvironment.mWorld->hasCellChanged()) + break; + } } + + mIgnoreLocalPtr = MWWorld::Ptr(); } bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt) @@ -291,7 +296,10 @@ void OMW::Engine::activate() std::string script = MWWorld::Class::get (ptr).getScript (ptr); if (!script.empty()) + { + mIgnoreLocalPtr = ptr; mScriptManager->run (script, interpreterContext); + } if (!interpreterContext.hasActivationBeenHandled()) { diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 62166e050..bc612d13c 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -11,6 +11,7 @@ #include #include "mwworld/environment.hpp" +#include "mwworld/ptr.hpp" namespace Compiler { @@ -68,6 +69,8 @@ namespace OMW int focusFrameCounter; static const int focusUpdateFrame = 10; + MWWorld::Ptr mIgnoreLocalPtr; + // not implemented Engine (const Engine&); Engine& operator= (const Engine&); From 1902dfb7b2623f312bf13a60ffb63c8351a04266 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 15:52:07 +0200 Subject: [PATCH 09/19] added activate instruction --- apps/openmw/mwscript/docs/vmformat.txt | 3 ++- apps/openmw/mwscript/miscextensions.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 939467960..5807f26d4 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -76,4 +76,5 @@ op 0x2000069-0x200006b: ModDynamic (health, magicka, fatigue) op 0x200006c-0x200006e: ModDynamic (health, magicka, fatigue), explicit reference op 0x200006f-0x2000071: GetDynamic (health, magicka, fatigue) op 0x2000072-0x2000074: GetDynamic (health, magicka, fatigue), explicit reference -opcodes 0x2000075-0x3ffffff unused +op 0x2000075: Activate +opcodes 0x2000076-0x3ffffff unused diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 6abd22454..1ecfd0c57 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -38,19 +38,37 @@ namespace MWScript } }; + class OpActivate : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context = + static_cast (runtime.getContext()); + + MWWorld::Ptr ptr = context.getReference(); + + context.executeActivation(); + } + }; + const int opcodeXBox = 0x200000c; const int opcodeOnActivate = 0x200000d; + const int opcodeActivate = 0x2000075; void registerExtensions (Compiler::Extensions& extensions) { extensions.registerFunction ("xbox", 'l', "", opcodeXBox); extensions.registerFunction ("onactivate", 'l', "", opcodeOnActivate); + extensions.registerInstruction ("activate", "", opcodeActivate); } void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeXBox, new OpXBox); interpreter.installSegment5 (opcodeOnActivate, new OpOnActivate); + interpreter.installSegment5 (opcodeActivate, new OpActivate); } } } From c883921af31da3816e1cdb106acedbbb6b357ad8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 15:57:06 +0200 Subject: [PATCH 10/19] minor cell change fix --- apps/openmw/mwworld/world.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 94a6758c7..581dcc586 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -544,7 +544,7 @@ namespace MWWorld insertInteriorScripts (*cell); // adjust player - mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2]); + mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true); mPlayerPos->setCell (cell); // TODO orientation From 8e6a765603398a2565656f1f0e736773992c30b3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 5 Aug 2010 16:40:21 +0200 Subject: [PATCH 11/19] fixed a stats bug (reducing modified stats via setModified didn't work correctly --- apps/openmw/mwmechanics/stat.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index a42b53444..d6422b084 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -49,7 +49,7 @@ namespace MWMechanics value = min + (mModified - mBase); diff = value - mModified; } - else if (mBase>max-diff) + else if (mBase+diff>max) { value = max + (mModified - mBase); diff = value - mModified; From 09c42589ccc0431788f1ccb78a41db62ac7ee678 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 18:15:46 +0200 Subject: [PATCH 12/19] implemented npc/creature activation (enters dialog gui mode for now) --- apps/openmw/CMakeLists.txt | 2 ++ apps/openmw/mwclass/creature.cpp | 7 +++++++ apps/openmw/mwclass/creature.hpp | 4 ++++ apps/openmw/mwclass/npc.cpp | 7 +++++++ apps/openmw/mwclass/npc.hpp | 4 ++++ apps/openmw/mwworld/actiontalk.cpp | 16 ++++++++++++++++ apps/openmw/mwworld/actiontalk.hpp | 21 +++++++++++++++++++++ 7 files changed, 61 insertions(+) create mode 100644 apps/openmw/mwworld/actiontalk.cpp create mode 100644 apps/openmw/mwworld/actiontalk.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0fe62ea4f..f4b231807 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -81,6 +81,7 @@ set(GAMEWORLD mwworld/globals.cpp mwworld/class.cpp mwworld/actionteleport.cpp + mwworld/actiontalk.cpp ) set(GAMEWORLD_HEADER mwworld/refdata.hpp @@ -92,6 +93,7 @@ set(GAMEWORLD_HEADER mwworld/action.hpp mwworld/nullaction.hpp mwworld/actionteleport.hpp + mwworld/actiontalk.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index e34f92fb4..32575d7db 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -6,6 +6,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontalk.hpp" namespace MWClass { @@ -44,6 +45,12 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + boost::shared_ptr Creature::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); + } + std::string Creature::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 03333a50a..71fb4dbec 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -16,6 +16,10 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 2887ad0b5..56d601edc 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -6,6 +6,7 @@ #include "../mwmechanics/creaturestats.hpp" #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontalk.hpp" namespace MWClass { @@ -44,6 +45,12 @@ namespace MWClass return *ptr.getRefData().getCreatureStats(); } + boost::shared_ptr Npc::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr (new MWWorld::ActionTalk (ptr)); + } + std::string Npc::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index e0b828f61..eb18cb2bd 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -16,6 +16,10 @@ namespace MWClass virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp new file mode 100644 index 000000000..2b4aba735 --- /dev/null +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -0,0 +1,16 @@ + +#include "actiontalk.hpp" + +#include "environment.hpp" + +#include "../mwgui/window_manager.hpp" + +namespace MWWorld +{ + ActionTalk::ActionTalk (const Ptr& actor) : mActor (actor) {} + + void ActionTalk::execute (Environment& environment) + { + environment.mWindowManager->setMode (MWGui::GM_Dialogue); + } +} diff --git a/apps/openmw/mwworld/actiontalk.hpp b/apps/openmw/mwworld/actiontalk.hpp new file mode 100644 index 000000000..034d6131c --- /dev/null +++ b/apps/openmw/mwworld/actiontalk.hpp @@ -0,0 +1,21 @@ +#ifndef GAME_MWWORLD_ACTIONTALK_H +#define GAME_MWWORLD_ACTIONTALK_H + +#include "ptr.hpp" +#include "action.hpp" + +namespace MWWorld +{ + class ActionTalk : public Action + { + Ptr mActor; + + public: + + ActionTalk (const Ptr& actor); + + virtual void execute (Environment& environment); + }; +} + +#endif From 0a60bde83406b7dbbf34a24b57f066ecbb834511 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 22:20:20 +0200 Subject: [PATCH 13/19] added insertIntoContainer function to class hierarchy --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwclass/apparatus.cpp | 8 +++++++ apps/openmw/mwclass/apparatus.hpp | 4 ++++ apps/openmw/mwclass/armor.cpp | 8 +++++++ apps/openmw/mwclass/armor.hpp | 4 ++++ apps/openmw/mwclass/book.cpp | 8 +++++++ apps/openmw/mwclass/book.hpp | 4 ++++ apps/openmw/mwclass/clothing.cpp | 8 +++++++ apps/openmw/mwclass/clothing.hpp | 4 ++++ apps/openmw/mwclass/containerutil.hpp | 31 +++++++++++++++++++++++++++ apps/openmw/mwclass/ingredient.cpp | 8 +++++++ apps/openmw/mwclass/ingredient.hpp | 4 ++++ apps/openmw/mwclass/light.cpp | 8 +++++++ apps/openmw/mwclass/light.hpp | 4 ++++ apps/openmw/mwclass/lockpick.cpp | 8 +++++++ apps/openmw/mwclass/lockpick.hpp | 4 ++++ apps/openmw/mwclass/misc.cpp | 8 +++++++ apps/openmw/mwclass/misc.hpp | 4 ++++ apps/openmw/mwclass/potion.cpp | 8 +++++++ apps/openmw/mwclass/potion.hpp | 4 ++++ apps/openmw/mwclass/probe.cpp | 8 +++++++ apps/openmw/mwclass/probe.hpp | 4 ++++ apps/openmw/mwclass/repair.cpp | 8 +++++++ apps/openmw/mwclass/repair.hpp | 4 ++++ apps/openmw/mwclass/weapon.cpp | 8 +++++++ apps/openmw/mwclass/weapon.hpp | 4 ++++ apps/openmw/mwworld/class.cpp | 7 +++++- apps/openmw/mwworld/class.hpp | 5 +++++ 28 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwclass/containerutil.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c9112b0ee..c41ffb50b 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -141,6 +141,7 @@ set(GAMECLASS_HEADER mwclass/probe.hpp mwclass/repair.hpp mwclass/static.hpp + mwclass/containerutil.hpp ) source_group(apps\\openmw\\mwclass FILES ${GAMECLASS} ${GAMECLASS_HEADER}) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 066eacd3f..fb2080ded 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Apparatus::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Apparatus::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.appas); + } + std::string Apparatus::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 7b3ccff6a..16d41a34a 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 786868c81..4c0550362 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Armor::getName (const MWWorld::Ptr& ptr) const @@ -30,6 +32,12 @@ namespace MWClass return ref->base->data.health; } + void Armor::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.armors); + } + std::string Armor::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index ebae75a9f..8b6c6e163 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -19,6 +19,10 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 9c0a48409..8faef5494 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Book::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Book::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.books); + } + std::string Book::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index d45f569b5..c79545d55 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index 2c0d76fb3..f1c769cd4 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Clothing::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Clothing::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.clothes); + } + std::string Clothing::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 09b66b92d..bd57f7849 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/containerutil.hpp b/apps/openmw/mwclass/containerutil.hpp new file mode 100644 index 000000000..5f89983ac --- /dev/null +++ b/apps/openmw/mwclass/containerutil.hpp @@ -0,0 +1,31 @@ +#ifndef GAME_MWCLASS_CONTAINERUTIL_H +#define GAME_MWCLASS_CONTAINERUTIL_H + +#include + +#include "../mwworld/ptr.hpp" +#include "../mwworld/containerstore.hpp" + +namespace MWClass +{ + template + void insertIntoContainerStore (const MWWorld::Ptr& ptr, + ESMS::CellRefList& containerStore) + { + if (!ptr.isEmpty()) + { + // TODO check stacking + + ESMS::LiveCellRef cellRef; + + cellRef.base = ptr.get()->base; + cellRef.ref = ptr.getCellRef(); + cellRef.mData = ptr.getRefData(); + + containerStore.list.push_back (cellRef); + + } + } +} + +#endif diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 81d19b2fa..7389ec5a7 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Ingredient::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Ingredient::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.ingreds); + } + std::string Ingredient::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index c2edd9484..8e1e14198 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 98e0b01b4..405aa2745 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Light::getName (const MWWorld::Ptr& ptr) const @@ -20,6 +22,12 @@ namespace MWClass return ref->base->name; } + void Light::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.lights); + } + std::string Light::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 08c3ddf7c..9627d5918 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index ce57e0c99..7062a0367 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Lockpick::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Lockpick::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.lockpicks); + } + std::string Lockpick::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index e009e9fdd..d9c8147e9 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index dda21aaa7..2d6614776 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Misc::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Misc::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.miscItems); + } + std::string Misc::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 526235aa0..ec61c5f3e 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index f8e9ee0a0..b368f5cb2 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Potion::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Potion::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.potions); + } + std::string Potion::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index c851d1b4e..ff1408533 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 3c22e4c7f..19f9ac8b2 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Probe::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Probe::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.probes); + } + std::string Probe::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 84e93d1ce..cf77700c7 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index f22b8607a..463daedfd 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Repair::getName (const MWWorld::Ptr& ptr) const @@ -17,6 +19,12 @@ namespace MWClass return ref->base->name; } + void Repair::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.repairs); + } + std::string Repair::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 803e21d51..c9619fb74 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index a7fce960c..471ae2634 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -7,6 +7,8 @@ #include "../mwworld/ptr.hpp" +#include "containerutil.hpp" + namespace MWClass { std::string Weapon::getName (const MWWorld::Ptr& ptr) const @@ -30,6 +32,12 @@ namespace MWClass return ref->base->data.health; } + void Weapon::insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const + { + insertIntoContainerStore (ptr, containerStore.weapons); + } + std::string Weapon::getScript (const MWWorld::Ptr& ptr) const { ESMS::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 01b6f8e13..1321fc962 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -19,6 +19,10 @@ namespace MWClass virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const; ///< Return item max health or throw an exception, if class does not have item health + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, + MWWorld::ContainerStore& containerStore) const; + ///< Insert into a containe + virtual std::string getScript (const MWWorld::Ptr& ptr) const; ///< Return name of the script attached to ptr diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index f3b231974..85e5140ea 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -44,7 +44,12 @@ namespace MWWorld ContainerStore& Class::getContainerStore (const Ptr& ptr) const { throw std::runtime_error ("class does not have a container store"); - } + } + + void Class::insertIntoContainer (const Ptr& ptr, ContainerStore& containerStore) const + { + throw std::runtime_error ("class does not support inserting into a container"); + } std::string Class::getScript (const Ptr& ptr) const { diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 86345edd5..28d96d69f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -64,6 +64,11 @@ namespace MWWorld ///< Return container store or throw an exception, if class does not have a /// container store (default implementation: throw an exceoption) + virtual void insertIntoContainer (const Ptr& ptr, ContainerStore& containerStore) + const; + ///< Insert into a container or throw an exception, if class does not support inserting into + /// a container. + virtual std::string getScript (const Ptr& ptr) const; ///< Return name of the script attached to ptr (default implementation: return an empty /// string). From 3ea85b46193aa5cf840fa1e94c36b8013d206e0b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 15:11:31 +0200 Subject: [PATCH 14/19] added AddItem instruction --- apps/openmw/CMakeLists.txt | 3 + apps/openmw/mwscript/containerextensions.cpp | 88 ++++++++++++++++++++ apps/openmw/mwscript/containerextensions.hpp | 25 ++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +- apps/openmw/mwscript/extensions.cpp | 8 +- apps/openmw/mwworld/manualref.hpp | 86 +++++++++++++++++++ 6 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 apps/openmw/mwscript/containerextensions.cpp create mode 100644 apps/openmw/mwscript/containerextensions.hpp create mode 100644 apps/openmw/mwworld/manualref.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c41ffb50b..a4883b77d 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -51,6 +51,7 @@ set(GAMESCRIPT mwscript/soundextensions.cpp mwscript/skyextensions.cpp mwscript/statsextensions.cpp + mwscript/containerextensions.cpp mwscript/extensions.cpp mwscript/globalscripts.cpp ) @@ -65,6 +66,7 @@ set(GAMESCRIPT_HEADER mwscript/soundextensions.hpp mwscript/skyextensions.hpp mwscript/statsextensions.hpp + mwscript/containerextensions.hpp mwscript/extensions.hpp mwscript/globalscripts.hpp ) @@ -93,6 +95,7 @@ set(GAMEWORLD_HEADER mwworld/nullaction.hpp mwworld/actionteleport.hpp mwworld/containerstore.hpp + mwworld/manualref.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp new file mode 100644 index 000000000..73111145b --- /dev/null +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -0,0 +1,88 @@ + +#include "containerextensions.hpp" + +#include + +#include +#include +#include + +#include "../mwworld/manualref.hpp" +#include "../mwworld/class.hpp" + +#include "interpretercontext.hpp" + +namespace MWScript +{ + namespace Container + { + class OpAddItem : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer count = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Ptr ptr = context.getReference(); + + MWWorld::ManualRef ref (context.getWorld().getStore(), item); + + ref.getPtr().getRefData().setCount (count); + + MWWorld::Class::get (ref.getPtr()).insertIntoContainer (ref.getPtr(), + MWWorld::Class::get (ptr).getContainerStore (ptr)); + } + }; + + class OpAddItemExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer count = runtime[0].mInteger; + runtime.pop(); + + MWWorld::Ptr ptr = context.getWorld().getPtr (id, false); + + MWWorld::ManualRef ref (context.getWorld().getStore(), item); + + ref.getPtr().getRefData().setCount (count); + + MWWorld::Class::get (ref.getPtr()).insertIntoContainer (ref.getPtr(), + MWWorld::Class::get (ptr).getContainerStore (ptr)); + } + }; + + const int opcodeAddItem = 0x2000076; + const int opcodeAddItemExplicit = 0x2000077; + + void registerExtensions (Compiler::Extensions& extensions) + { + extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); + } + + void installOpcodes (Interpreter::Interpreter& interpreter) + { + interpreter.installSegment5 (opcodeAddItem, new OpAddItem); + interpreter.installSegment5 (opcodeAddItemExplicit, new OpAddItemExplicit); + } + } +} diff --git a/apps/openmw/mwscript/containerextensions.hpp b/apps/openmw/mwscript/containerextensions.hpp new file mode 100644 index 000000000..f99a71b4d --- /dev/null +++ b/apps/openmw/mwscript/containerextensions.hpp @@ -0,0 +1,25 @@ +#ifndef GAME_SCRIPT_CONTAINEREXTENSIONS_H +#define GAME_SCRIPT_CONTAINEREXTENSIONS_H + +namespace Compiler +{ + class Extensions; +} + +namespace Interpreter +{ + class Interpreter; +} + +namespace MWScript +{ + /// \brief stats-related script functionality (creatures and NPCs) + namespace Container + { + void registerExtensions (Compiler::Extensions& extensions); + + void installOpcodes (Interpreter::Interpreter& interpreter); + } +} + +#endif diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 5807f26d4..e2de2cbc1 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -77,4 +77,6 @@ op 0x200006c-0x200006e: ModDynamic (health, magicka, fatigue), explicit referenc op 0x200006f-0x2000071: GetDynamic (health, magicka, fatigue) op 0x2000072-0x2000074: GetDynamic (health, magicka, fatigue), explicit reference op 0x2000075: Activate -opcodes 0x2000076-0x3ffffff unused +op 0x2000076: AddItem +op 0x2000077: AddItem, explicit reference +opcodes 0x2000078-0x3ffffff unused diff --git a/apps/openmw/mwscript/extensions.cpp b/apps/openmw/mwscript/extensions.cpp index 3abaac58c..1b3d3df14 100644 --- a/apps/openmw/mwscript/extensions.cpp +++ b/apps/openmw/mwscript/extensions.cpp @@ -10,6 +10,7 @@ #include "guiextensions.hpp" #include "skyextensions.hpp" #include "statsextensions.hpp" +#include "containerextensions.hpp" namespace MWScript { @@ -21,8 +22,9 @@ namespace MWScript Sound::registerExtensions (extensions); Sky::registerExtensions (extensions); Stats::registerExtensions (extensions); + Container::registerExtensions (extensions); } - + void installOpcodes (Interpreter::Interpreter& interpreter) { Interpreter::installOpcodes (interpreter); @@ -32,6 +34,6 @@ namespace MWScript Sound::installOpcodes (interpreter); Sky::installOpcodes (interpreter); Stats::installOpcodes (interpreter); - } + Container::installOpcodes (interpreter); + } } - diff --git a/apps/openmw/mwworld/manualref.hpp b/apps/openmw/mwworld/manualref.hpp new file mode 100644 index 000000000..4b7edfa43 --- /dev/null +++ b/apps/openmw/mwworld/manualref.hpp @@ -0,0 +1,86 @@ +#ifndef GAME_MWWORLD_MANUALREF_H +#define GAME_MWWORLD_MANUALREF_H + +#include + +#include +#include + +#include "ptr.hpp" + +namespace MWWorld +{ + /// \brief Manually constructed live cell ref + class ManualRef + { + boost::any mRef; + Ptr mPtr; + + ManualRef (const ManualRef&); + ManualRef& operator= (const ManualRef&); + + template + bool create (const ESMS::RecListT& list, const std::string& name) + { + if (const T *instance = list.search (name)) + { + ESMS::LiveCellRef ref; + ref.base = instance; + + mRef = ref; + mPtr = Ptr (&boost::any_cast&> (mRef), 0); + + return true; + } + + return false; + } + + public: + + ManualRef (const ESMS::ESMStore& store, const std::string& name) + { + // create + if (!create (store.activators, name) && + !create (store.potions, name) && + !create (store.appas, name) && + !create (store.armors, name) && + !create (store.books, name) && + !create (store.clothes, name) && + !create (store.containers, name) && + !create (store.creatures, name) && + !create (store.doors, name) && + !create (store.ingreds, name) && + !create (store.creatureLists, name) && + !create (store.itemLists, name) && + !create (store.lights, name) && + !create (store.lockpicks, name) && + !create (store.miscItems, name) && + !create (store.npcs, name) && + !create (store.probes, name) && + !create (store.repairs, name) && + !create (store.statics, name) && + !create (store.weapons, name)) + throw std::logic_error ("failed to create manual cell ref for " + name); + + // initialise + ESM::CellRef& cellRef = mPtr.getCellRef(); + cellRef.refnum = -1; + cellRef.scale = 1; + cellRef.factIndex = 0; + cellRef.charge = 0; + cellRef.intv = 0; + cellRef.nam9 = 0; + cellRef.teleport = false; + cellRef.lockLevel = 0; + cellRef.unam = 0; + } + + const Ptr& getPtr() const + { + return mPtr; + } + }; +} + +#endif From 589f8b5ede58b7ecc2327b6579da66ddba6a7d3b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 16:21:07 +0200 Subject: [PATCH 15/19] added GetItemCount --- apps/openmw/CMakeLists.txt | 2 + apps/openmw/mwscript/containerextensions.cpp | 74 ++++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +- apps/openmw/mwworld/containerutil.cpp | 43 ++++++++++++ apps/openmw/mwworld/containerutil.hpp | 20 ++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwworld/containerutil.cpp create mode 100644 apps/openmw/mwworld/containerutil.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a4883b77d..7e3532f41 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -83,6 +83,7 @@ set(GAMEWORLD mwworld/globals.cpp mwworld/class.cpp mwworld/actionteleport.cpp + mwworld/containerutil.cpp ) set(GAMEWORLD_HEADER mwworld/refdata.hpp @@ -96,6 +97,7 @@ set(GAMEWORLD_HEADER mwworld/actionteleport.hpp mwworld/containerstore.hpp mwworld/manualref.hpp + mwworld/containerutil.hpp ) source_group(apps\\openmw\\mwworld FILES ${GAMEWORLD} ${GAMEWORLD_HEADER}) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 73111145b..dad88a7e1 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -9,6 +9,7 @@ #include "../mwworld/manualref.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/containerutil.hpp" #include "interpretercontext.hpp" @@ -71,18 +72,91 @@ namespace MWScript } }; + class OpGetItemCount : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + MWWorld::Ptr ptr = context.getReference(); + + std::vector list; + + MWWorld::listItemsInContainer (item, + MWWorld::Class::get (ptr).getContainerStore (ptr), + context.getWorld().getStore(), list); + + Interpreter::Type_Integer sum = 0; + + for (std::vector::iterator iter (list.begin()); iter!=list.end(); + ++iter) + { + sum += iter->getRefData().getCount(); + } + + runtime.push (sum); + } + }; + + class OpGetItemCountExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + MWWorld::Ptr ptr = context.getWorld().getPtr (id, false); + + std::vector list; + + MWWorld::listItemsInContainer (item, + MWWorld::Class::get (ptr).getContainerStore (ptr), + context.getWorld().getStore(), list); + + Interpreter::Type_Integer sum = 0; + + for (std::vector::iterator iter (list.begin()); iter!=list.end(); + ++iter) + { + sum += iter->getRefData().getCount(); + } + + runtime.push (sum); + } + }; + const int opcodeAddItem = 0x2000076; const int opcodeAddItemExplicit = 0x2000077; + const int opcodeGetItemCount = 0x2000078; + const int opcodeGetItemCountExplicit = 0x2000079; void registerExtensions (Compiler::Extensions& extensions) { extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); + extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount, + opcodeGetItemCountExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeAddItem, new OpAddItem); interpreter.installSegment5 (opcodeAddItemExplicit, new OpAddItemExplicit); + interpreter.installSegment5 (opcodeGetItemCount, new OpGetItemCount); + interpreter.installSegment5 (opcodeGetItemCountExplicit, new OpGetItemCountExplicit); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index e2de2cbc1..0b91bb8d5 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -79,4 +79,6 @@ op 0x2000072-0x2000074: GetDynamic (health, magicka, fatigue), explicit referenc op 0x2000075: Activate op 0x2000076: AddItem op 0x2000077: AddItem, explicit reference -opcodes 0x2000078-0x3ffffff unused +op 0x2000078: GetItemCount +op 0x2000079: GetItemCount, explicit reference +opcodes 0x200007a-0x3ffffff unused diff --git a/apps/openmw/mwworld/containerutil.cpp b/apps/openmw/mwworld/containerutil.cpp new file mode 100644 index 000000000..7c7e5e5e8 --- /dev/null +++ b/apps/openmw/mwworld/containerutil.cpp @@ -0,0 +1,43 @@ + +#include "containerutil.hpp" + +namespace +{ + template + void listItemsInContainerImp (const std::string& id, + ESMS::CellRefList& containerStore, + const ESMS::RecListT& store, std::vector& list) + { + if (const T *record = store.search (id)) + { + for (typename ESMS::CellRefList::List::iterator iter + (containerStore.list.begin()); + iter!=containerStore.list.end(); ++iter) + { + if (iter->base==record) + list.push_back (MWWorld::Ptr (&*iter, 0)); + } + } + } +} + +namespace MWWorld +{ + void listItemsInContainer (const std::string& id, + ContainerStore& containerStore, + const ESMS::ESMStore& store, std::vector& list) + { + listItemsInContainerImp (id, containerStore.potions, store.potions, list); + listItemsInContainerImp (id, containerStore.appas, store.appas, list); + listItemsInContainerImp (id, containerStore.armors, store.armors, list); + listItemsInContainerImp (id, containerStore.books, store.books, list); + listItemsInContainerImp (id, containerStore.clothes, store.clothes, list); + listItemsInContainerImp (id, containerStore.ingreds, store.ingreds, list); + listItemsInContainerImp (id, containerStore.lights, store.lights, list); + listItemsInContainerImp (id, containerStore.lockpicks, store.lockpicks, list); + listItemsInContainerImp (id, containerStore.miscItems, store.miscItems, list); + listItemsInContainerImp (id, containerStore.probes, store.probes, list); + listItemsInContainerImp (id, containerStore.repairs, store.repairs, list); + listItemsInContainerImp (id, containerStore.weapons, store.weapons, list); + } +} diff --git a/apps/openmw/mwworld/containerutil.hpp b/apps/openmw/mwworld/containerutil.hpp new file mode 100644 index 000000000..21e770404 --- /dev/null +++ b/apps/openmw/mwworld/containerutil.hpp @@ -0,0 +1,20 @@ +#ifndef GAME_MWWORLD_CONTAINERUTIL_H +#define GAME_MWWORLD_CONTAINERUTIL_H + +#include +#include + +#include + +#include "containerstore.hpp" +#include "ptr.hpp" +#include "refdata.hpp" + +namespace MWWorld +{ + void listItemsInContainer (const std::string& id, ContainerStore& containerStore, + const ESMS::ESMStore& store, std::vector& list); + ///< append all references with the given id to list. +} + +#endif From db24a55e365544cb17558a01714a16a7c4c0fe59 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 16:34:49 +0200 Subject: [PATCH 16/19] added sanity check for AddItem arguments --- apps/openmw/mwscript/containerextensions.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index dad88a7e1..c9601e594 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -1,6 +1,8 @@ #include "containerextensions.hpp" +#include + #include #include @@ -32,6 +34,9 @@ namespace MWScript Interpreter::Type_Integer count = runtime[0].mInteger; runtime.pop(); + if (count<0) + throw std::runtime_error ("second argument for AddItem must be non-negative"); + MWWorld::Ptr ptr = context.getReference(); MWWorld::ManualRef ref (context.getWorld().getStore(), item); @@ -61,6 +66,9 @@ namespace MWScript Interpreter::Type_Integer count = runtime[0].mInteger; runtime.pop(); + if (count<0) + throw std::runtime_error ("second argument for AddItem must be non-negative"); + MWWorld::Ptr ptr = context.getWorld().getPtr (id, false); MWWorld::ManualRef ref (context.getWorld().getStore(), item); From aa637cb9d4258a46af233b106b9d9c3f85e9b524 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 17:00:04 +0200 Subject: [PATCH 17/19] added RemoveItem --- apps/openmw/mwscript/containerextensions.cpp | 103 +++++++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index c9601e594..1121d8eff 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -147,16 +147,117 @@ namespace MWScript } }; + class OpRemoveItem : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer count = runtime[0].mInteger; + runtime.pop(); + + if (count<0) + throw std::runtime_error ("second argument for RemoveItem must be non-negative"); + + MWWorld::Ptr ptr = context.getReference(); + + std::vector list; + + MWWorld::listItemsInContainer (item, + MWWorld::Class::get (ptr).getContainerStore (ptr), + context.getWorld().getStore(), list); + + for (std::vector::iterator iter (list.begin()); + iter!=list.end() && count; + ++iter) + { + if (iter->getRefData().getCount()<=count) + { + count -= iter->getRefData().getCount(); + iter->getRefData().setCount (0); + } + else + { + iter->getRefData().setCount (iter->getRefData().getCount()-count); + count = 0; + } + } + + // To be fully compatible with original Morrowind, we would need to check if + // count is >= 0 here and throw an exception. But let's be tollerant instead. + } + }; + + class OpRemoveItemExplicit : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWScript::InterpreterContext& context + = static_cast (runtime.getContext()); + + std::string id = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + std::string item = runtime.getStringLiteral (runtime[0].mInteger); + runtime.pop(); + + Interpreter::Type_Integer count = runtime[0].mInteger; + runtime.pop(); + + if (count<0) + throw std::runtime_error ("second argument for RemoveItem must be non-negative"); + + MWWorld::Ptr ptr = context.getWorld().getPtr (id, false); + + std::vector list; + + MWWorld::listItemsInContainer (item, + MWWorld::Class::get (ptr).getContainerStore (ptr), + context.getWorld().getStore(), list); + + for (std::vector::iterator iter (list.begin()); + iter!=list.end() && count; + ++iter) + { + if (iter->getRefData().getCount()<=count) + { + count -= iter->getRefData().getCount(); + iter->getRefData().setCount (0); + } + else + { + iter->getRefData().setCount (iter->getRefData().getCount()-count); + count = 0; + } + } + + // To be fully compatible with original Morrowind, we would need to check if + // count is >= 0 here and throw an exception. But let's be tollerant instead. + } + }; + const int opcodeAddItem = 0x2000076; const int opcodeAddItemExplicit = 0x2000077; const int opcodeGetItemCount = 0x2000078; const int opcodeGetItemCountExplicit = 0x2000079; + const int opcodeRemoveItem = 0x200007a; + const int opcodeRemoveItemExplicit = 0x200007b; void registerExtensions (Compiler::Extensions& extensions) { extensions.registerInstruction ("additem", "cl", opcodeAddItem, opcodeAddItemExplicit); extensions.registerFunction ("getitemcount", 'l', "c", opcodeGetItemCount, opcodeGetItemCountExplicit); + extensions.registerInstruction ("removeitem", "cl", opcodeRemoveItem, + opcodeRemoveItemExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -165,6 +266,8 @@ namespace MWScript interpreter.installSegment5 (opcodeAddItemExplicit, new OpAddItemExplicit); interpreter.installSegment5 (opcodeGetItemCount, new OpGetItemCount); interpreter.installSegment5 (opcodeGetItemCountExplicit, new OpGetItemCountExplicit); + interpreter.installSegment5 (opcodeRemoveItem, new OpRemoveItem); + interpreter.installSegment5 (opcodeRemoveItemExplicit, new OpRemoveItemExplicit); } } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 0b91bb8d5..70e5fe8c2 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -81,4 +81,6 @@ op 0x2000076: AddItem op 0x2000077: AddItem, explicit reference op 0x2000078: GetItemCount op 0x2000079: GetItemCount, explicit reference -opcodes 0x200007a-0x3ffffff unused +op 0x200007a: RemoveItem +op 0x200007b: RemoveItem, explicit reference +opcodes 0x200007c-0x3ffffff unused From a7fe28ecbe4d02aaaf11b32d38a89b272ff10fdf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 20:25:17 +0200 Subject: [PATCH 18/19] implemented take action --- apps/openmw/CMakeLists.txt | 2 ++ apps/openmw/mwclass/apparatus.cpp | 8 ++++++++ apps/openmw/mwclass/apparatus.hpp | 4 ++++ apps/openmw/mwclass/armor.cpp | 8 ++++++++ apps/openmw/mwclass/armor.hpp | 4 ++++ apps/openmw/mwclass/book.cpp | 10 ++++++++++ apps/openmw/mwclass/book.hpp | 4 ++++ apps/openmw/mwclass/clothing.cpp | 8 ++++++++ apps/openmw/mwclass/clothing.hpp | 4 ++++ apps/openmw/mwclass/ingredient.cpp | 8 ++++++++ apps/openmw/mwclass/ingredient.hpp | 4 ++++ apps/openmw/mwclass/light.cpp | 15 +++++++++++++++ apps/openmw/mwclass/light.hpp | 4 ++++ apps/openmw/mwclass/lockpick.cpp | 8 ++++++++ apps/openmw/mwclass/lockpick.hpp | 4 ++++ apps/openmw/mwclass/misc.cpp | 8 ++++++++ apps/openmw/mwclass/misc.hpp | 4 ++++ apps/openmw/mwclass/potion.cpp | 8 ++++++++ apps/openmw/mwclass/potion.hpp | 4 ++++ apps/openmw/mwclass/probe.cpp | 8 ++++++++ apps/openmw/mwclass/probe.hpp | 4 ++++ apps/openmw/mwclass/repair.cpp | 8 ++++++++ apps/openmw/mwclass/repair.hpp | 4 ++++ apps/openmw/mwclass/weapon.cpp | 8 ++++++++ apps/openmw/mwclass/weapon.hpp | 4 ++++ apps/openmw/mwrender/cell.hpp | 22 ++++++++++++---------- apps/openmw/mwrender/interior.cpp | 10 ++++++++++ apps/openmw/mwrender/interior.hpp | 8 +++++--- apps/openmw/mwworld/actiontake.cpp | 23 +++++++++++++++++++++++ apps/openmw/mwworld/actiontake.hpp | 21 +++++++++++++++++++++ apps/openmw/mwworld/world.cpp | 21 +++++++++++++++++++++ apps/openmw/mwworld/world.hpp | 2 ++ 32 files changed, 249 insertions(+), 13 deletions(-) create mode 100644 apps/openmw/mwworld/actiontake.cpp create mode 100644 apps/openmw/mwworld/actiontake.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 7e3532f41..359a83e4f 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -83,6 +83,7 @@ set(GAMEWORLD mwworld/globals.cpp mwworld/class.cpp mwworld/actionteleport.cpp + mwworld/actiontake.cpp mwworld/containerutil.cpp ) set(GAMEWORLD_HEADER @@ -95,6 +96,7 @@ set(GAMEWORLD_HEADER mwworld/action.hpp mwworld/nullaction.hpp mwworld/actionteleport.hpp + mwworld/actiontake.hpp mwworld/containerstore.hpp mwworld/manualref.hpp mwworld/containerutil.hpp diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index fb2080ded..4b94d78d1 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Apparatus::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 16d41a34a..4a514c94d 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 4c0550362..f4236b5f6 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + bool Armor::hasItemHealth (const MWWorld::Ptr& ptr) const { return true; diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 8b6c6e163..217a74a76 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const; ///< \return Item health data available? diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 8faef5494..3bea7d5b9 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,15 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Book::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + // TODO implement reading + + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Book::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index c79545d55..3f15e2278 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index f1c769cd4..c0e43bc3e 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Clothing::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index bd57f7849..ea358be68 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 7389ec5a7..9162384af 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Ingredient::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 8e1e14198..d742fae8b 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 405aa2745..7cb363bf8 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -6,6 +6,8 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" +#include "../mwworld/nullaction.hpp" #include "containerutil.hpp" @@ -22,6 +24,19 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Light::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + ESMS::LiveCellRef *ref = + ptr.get(); + + if (!(ref->base->data.flags & ESM::Light::Carry)) + return boost::shared_ptr (new MWWorld::NullAction); + + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Light::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 9627d5918..6d08d557c 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 7062a0367..ab1969480 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Lockpick::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index d9c8147e9..e15d9daee 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 2d6614776..f29a0be1f 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Misc::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Misc::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index ec61c5f3e..01542baed 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index b368f5cb2..0799b2031 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Potion::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index ff1408533..208c26c56 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 19f9ac8b2..08ec391a8 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Probe::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index cf77700c7..c17d53dab 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 463daedfd..9ed7f0e77 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + void Repair::insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const { diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index c9619fb74..52d045ebe 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual void insertIntoContainer (const MWWorld::Ptr& ptr, MWWorld::ContainerStore& containerStore) const; ///< Insert into a containe diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 471ae2634..c292c32dd 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -6,6 +6,7 @@ #include #include "../mwworld/ptr.hpp" +#include "../mwworld/actiontake.hpp" #include "containerutil.hpp" @@ -19,6 +20,13 @@ namespace MWClass return ref->base->name; } + boost::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const + { + return boost::shared_ptr ( + new MWWorld::ActionTake (ptr)); + } + bool Weapon::hasItemHealth (const MWWorld::Ptr& ptr) const { return true; diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 1321fc962..6bc96381c 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -13,6 +13,10 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual boost::shared_ptr activate (const MWWorld::Ptr& ptr, + const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const; + ///< Generate action for activation + virtual bool hasItemHealth (const MWWorld::Ptr& ptr) const; ///< \return Item health data available? diff --git a/apps/openmw/mwrender/cell.hpp b/apps/openmw/mwrender/cell.hpp index d6dd944ca..8fa3f9f0f 100644 --- a/apps/openmw/mwrender/cell.hpp +++ b/apps/openmw/mwrender/cell.hpp @@ -3,31 +3,33 @@ #include -namespace MWRender +namespace MWRender { class CellRender { - public: - + public: + virtual ~CellRender() {}; - + /// Make the cell visible. Load the cell if necessary. virtual void show() = 0; - + /// Remove the cell from rendering, but don't remove it from /// memory. - virtual void hide() = 0; - + virtual void hide() = 0; + /// Destroy all rendering objects connected with this cell. virtual void destroy() = 0; - + /// Make the reference with the given handle visible. virtual void enable (const std::string& handle) = 0; - + /// Make the reference with the given handle invisible. virtual void disable (const std::string& handle) = 0; + + /// Remove the reference with the given handle permanently from the scene. + virtual void deleteObject (const std::string& handle) = 0; }; } #endif - diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index c67bc8878..d559a1216 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -237,6 +237,16 @@ void InteriorCellRender::disable (const std::string& handle) scene.getMgr()->getSceneNode (handle)->setVisible (false); } +void InteriorCellRender::deleteObject (const std::string& handle) +{ + if (!handle.empty()) + { + Ogre::SceneNode *node = scene.getMgr()->getSceneNode (handle); + node->removeAndDestroyAllChildren(); + scene.getMgr()->destroySceneNode (node); + } +} + // Magic function from the internets. Might need this later. /* void Scene::DestroyAllAttachedMovableObjects( SceneNode* i_pSceneNode ) diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 0ef5ec85c..3d375f7f2 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -99,11 +99,13 @@ namespace MWRender /// Make the reference with the given handle visible. virtual void enable (const std::string& handle); - + /// Make the reference with the given handle invisible. - virtual void disable (const std::string& handle); + virtual void disable (const std::string& handle); + + /// Remove the reference with the given handle permanently from the scene. + virtual void deleteObject (const std::string& handle); }; } #endif - diff --git a/apps/openmw/mwworld/actiontake.cpp b/apps/openmw/mwworld/actiontake.cpp new file mode 100644 index 000000000..b318f0796 --- /dev/null +++ b/apps/openmw/mwworld/actiontake.cpp @@ -0,0 +1,23 @@ + +#include "actiontake.hpp" + +#include "class.hpp" +#include "environment.hpp" +#include "world.hpp" + +namespace MWWorld +{ + ActionTake::ActionTake (const MWWorld::Ptr& object) : mObject (object) {} + + void ActionTake::execute (Environment& environment) + { + // insert into player's inventory + MWWorld::Ptr player = environment.mWorld->getPtr ("player", true); + + MWWorld::Class::get (mObject).insertIntoContainer (mObject, + MWWorld::Class::get (player).getContainerStore (player)); + + // remove from world + environment.mWorld->deleteObject (mObject); + } +} diff --git a/apps/openmw/mwworld/actiontake.hpp b/apps/openmw/mwworld/actiontake.hpp new file mode 100644 index 000000000..509ebc6bb --- /dev/null +++ b/apps/openmw/mwworld/actiontake.hpp @@ -0,0 +1,21 @@ +#ifndef GAME_MWWORLD_ACTIONTAKE_H +#define GAME_MWWORLD_ACTIONTAKE_H + +#include "action.hpp" +#include "ptr.hpp" + +namespace MWWorld +{ + class ActionTake : public Action + { + MWWorld::Ptr mObject; + + public: + + ActionTake (const MWWorld::Ptr& object); + + virtual void execute (Environment& environment); + }; +} + +#endif diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 1293d2daa..9b53f8111 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -611,4 +611,25 @@ namespace MWWorld return result.first; } + + void World::deleteObject (Ptr ptr) + { + if (ptr.getRefData().getCount()>0) + { + ptr.getRefData().setCount (0); + + if (MWRender::CellRender *render = searchRender (ptr.getCell())) + { + render->deleteObject (ptr.getRefData().getHandle()); + ptr.getRefData().setHandle (""); + + if (mActiveCells.find (ptr.getCell())!=mActiveCells.end() && + (ptr.getType()==typeid (ESMS::LiveCellRef) || + ptr.getType()==typeid (ESMS::LiveCellRef))) + { + mEnvironment.mMechanicsManager->removeActor (ptr); + } + } + } + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index d20161698..2a7b8009a 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -134,6 +134,8 @@ namespace MWWorld std::string getFacedHandle(); ///< Return handle of the object the player is looking at + + void deleteObject (Ptr ptr); }; } From 2eee3d32f12dd8f0c510f6ef3954e0a5ba1c0943 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 20:29:10 +0200 Subject: [PATCH 19/19] fixed World::disable function --- apps/openmw/mwworld/world.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 581dcc586..296d1d0f2 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -384,9 +384,9 @@ namespace MWWorld void World::disable (Ptr reference) { - if (!reference.getRefData().isEnabled()) + if (reference.getRefData().isEnabled()) { - reference.getRefData().enable(); + reference.getRefData().disable(); if (MWRender::CellRender *render = searchRender (reference.getCell())) {