From e0a3b1b1db7521b7e1cf0f3f52a5d321b925791d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 4 Aug 2010 14:04:22 +0200 Subject: [PATCH 1/8] 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 2/8] 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 0a60bde83406b7dbbf34a24b57f066ecbb834511 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 6 Aug 2010 22:20:20 +0200 Subject: [PATCH 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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); }; }