diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a4883b77d4..7e3532f418 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 73111145bb..dad88a7e17 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 e2de2cbc1d..0b91bb8d52 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 0000000000..7c7e5e5e87 --- /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 0000000000..21e770404b --- /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