|
|
|
@ -147,16 +147,117 @@ namespace MWScript
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class OpRemoveItem : public Interpreter::Opcode0
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
virtual void execute (Interpreter::Runtime& runtime)
|
|
|
|
|
{
|
|
|
|
|
MWScript::InterpreterContext& context
|
|
|
|
|
= static_cast<MWScript::InterpreterContext&> (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<MWWorld::Ptr> list;
|
|
|
|
|
|
|
|
|
|
MWWorld::listItemsInContainer (item,
|
|
|
|
|
MWWorld::Class::get (ptr).getContainerStore (ptr),
|
|
|
|
|
context.getWorld().getStore(), list);
|
|
|
|
|
|
|
|
|
|
for (std::vector<MWWorld::Ptr>::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<MWScript::InterpreterContext&> (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<MWWorld::Ptr> list;
|
|
|
|
|
|
|
|
|
|
MWWorld::listItemsInContainer (item,
|
|
|
|
|
MWWorld::Class::get (ptr).getContainerStore (ptr),
|
|
|
|
|
context.getWorld().getStore(), list);
|
|
|
|
|
|
|
|
|
|
for (std::vector<MWWorld::Ptr>::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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|