From aa637cb9d4258a46af233b106b9d9c3f85e9b524 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 7 Aug 2010 17:00:04 +0200 Subject: [PATCH] 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 c9601e5944..1121d8eff4 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 0b91bb8d52..70e5fe8c2b 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