2010-08-07 13:11:31 +00:00
|
|
|
#include "containerextensions.hpp"
|
|
|
|
|
2010-08-07 14:34:49 +00:00
|
|
|
#include <stdexcept>
|
|
|
|
|
2012-12-27 15:28:13 +00:00
|
|
|
#include <MyGUI_LanguageManager.h>
|
|
|
|
|
2018-08-14 19:05:43 +00:00
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
|
2013-08-07 00:38:41 +00:00
|
|
|
#include <components/compiler/opcodes.hpp>
|
2010-08-07 13:11:31 +00:00
|
|
|
|
|
|
|
#include <components/interpreter/interpreter.hpp>
|
|
|
|
#include <components/interpreter/opcodes.hpp>
|
|
|
|
|
2015-02-09 15:23:41 +00:00
|
|
|
#include <components/misc/stringops.hpp>
|
|
|
|
|
2014-02-23 19:11:05 +00:00
|
|
|
#include <components/esm/loadskil.hpp>
|
|
|
|
|
2012-04-23 13:27:03 +00:00
|
|
|
#include "../mwbase/environment.hpp"
|
2012-12-26 22:57:53 +00:00
|
|
|
#include "../mwbase/windowmanager.hpp"
|
2015-02-09 16:45:48 +00:00
|
|
|
#include "../mwbase/world.hpp"
|
2012-04-23 13:27:03 +00:00
|
|
|
|
2020-10-20 09:22:43 +00:00
|
|
|
#include "../mwclass/container.hpp"
|
|
|
|
|
2019-02-22 19:16:47 +00:00
|
|
|
#include "../mwworld/action.hpp"
|
2010-08-07 13:11:31 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
2012-02-23 11:34:51 +00:00
|
|
|
#include "../mwworld/containerstore.hpp"
|
2012-11-23 19:48:59 +00:00
|
|
|
#include "../mwworld/inventorystore.hpp"
|
2020-10-20 09:22:43 +00:00
|
|
|
#include "../mwworld/manualref.hpp"
|
2010-08-07 13:11:31 +00:00
|
|
|
|
2015-08-21 09:12:39 +00:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
2020-10-21 15:21:28 +00:00
|
|
|
#include "../mwmechanics/levelledlist.hpp"
|
2015-08-21 09:12:39 +00:00
|
|
|
|
2010-12-31 18:09:25 +00:00
|
|
|
#include "ref.hpp"
|
2010-08-07 13:11:31 +00:00
|
|
|
|
2020-10-20 09:22:43 +00:00
|
|
|
namespace
|
|
|
|
{
|
2020-10-21 15:21:28 +00:00
|
|
|
void addToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& ptr, MWWorld::ContainerStore& store, bool resolve = true)
|
2020-10-20 09:22:43 +00:00
|
|
|
{
|
|
|
|
if (itemPtr.getClass().getScript(itemPtr).empty())
|
|
|
|
{
|
|
|
|
store.add (itemPtr, count, ptr, true, resolve);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Adding just one item per time to make sure there isn't a stack of scripted items
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
store.add (itemPtr, 1, ptr, true, resolve);
|
|
|
|
}
|
|
|
|
}
|
2020-10-21 15:21:28 +00:00
|
|
|
|
|
|
|
void addRandomToStore(const MWWorld::Ptr& itemPtr, int count, MWWorld::Ptr& owner, MWWorld::ContainerStore& store, bool topLevel = true)
|
|
|
|
{
|
|
|
|
if(itemPtr.getTypeName() == typeid(ESM::ItemLevList).name())
|
|
|
|
{
|
|
|
|
const ESM::ItemLevList* levItemList = itemPtr.get<ESM::ItemLevList>()->mBase;
|
|
|
|
|
|
|
|
if(topLevel && count > 1 && levItemList->mFlags & ESM::ItemLevList::Each)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < count; i++)
|
|
|
|
addRandomToStore(itemPtr, 1, owner, store, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string itemId = MWMechanics::getLevelledItem(itemPtr.get<ESM::ItemLevList>()->mBase, false);
|
|
|
|
if (itemId.empty())
|
|
|
|
return;
|
|
|
|
MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), itemId, 1);
|
|
|
|
addRandomToStore(manualRef.getPtr(), count, owner, store, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
addToStore(itemPtr, count, owner, store);
|
|
|
|
}
|
2020-10-20 09:22:43 +00:00
|
|
|
}
|
|
|
|
|
2010-08-07 13:11:31 +00:00
|
|
|
namespace MWScript
|
|
|
|
{
|
|
|
|
namespace Container
|
|
|
|
{
|
2010-12-31 18:09:25 +00:00
|
|
|
template<class R>
|
2010-08-07 13:11:31 +00:00
|
|
|
class OpAddItem : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute (Interpreter::Runtime& runtime) override
|
2010-08-07 13:11:31 +00:00
|
|
|
{
|
2010-12-31 18:09:25 +00:00
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
2010-08-07 13:11:31 +00:00
|
|
|
|
|
|
|
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
|
|
|
runtime.pop();
|
|
|
|
|
|
|
|
Interpreter::Type_Integer count = runtime[0].mInteger;
|
|
|
|
runtime.pop();
|
|
|
|
|
2010-08-07 14:34:49 +00:00
|
|
|
if (count<0)
|
2021-04-05 07:43:37 +00:00
|
|
|
count = static_cast<uint16_t>(count);
|
2010-08-07 14:34:49 +00:00
|
|
|
|
2013-02-17 18:44:00 +00:00
|
|
|
// no-op
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
|
2015-09-24 13:21:42 +00:00
|
|
|
if(::Misc::StringUtils::ciEqual(item, "gold_005")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_010")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_025")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_100"))
|
2015-07-20 03:48:19 +00:00
|
|
|
item = "gold_001";
|
|
|
|
|
2020-10-20 09:22:43 +00:00
|
|
|
// Check if "item" can be placed in a container
|
|
|
|
MWWorld::ManualRef manualRef(MWBase::Environment::get().getWorld()->getStore(), item, 1);
|
|
|
|
MWWorld::Ptr itemPtr = manualRef.getPtr();
|
|
|
|
bool isLevelledList = itemPtr.getClass().getTypeName() == typeid(ESM::ItemLevList).name();
|
|
|
|
if(!isLevelledList)
|
|
|
|
MWWorld::ContainerStore::getType(itemPtr);
|
|
|
|
|
2020-07-26 09:07:18 +00:00
|
|
|
// Explicit calls to non-unique actors affect the base record
|
|
|
|
if(!R::implicit && ptr.getClass().isActor() && MWBase::Environment::get().getWorld()->getStore().getRefCount(ptr.getCellRef().getRefId()) > 1)
|
|
|
|
{
|
|
|
|
ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-20 09:22:43 +00:00
|
|
|
// Calls to unresolved containers affect the base record
|
|
|
|
if(ptr.getClass().getTypeName() == typeid(ESM::Container).name() && (!ptr.getRefData().getCustomData() ||
|
|
|
|
!ptr.getClass().getContainerStore(ptr).isResolved()))
|
2018-12-06 15:31:47 +00:00
|
|
|
{
|
2020-10-20 09:22:43 +00:00
|
|
|
ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, count);
|
|
|
|
const ESM::Container* baseRecord = MWBase::Environment::get().getWorld()->getStore().get<ESM::Container>().find(ptr.getCellRef().getRefId());
|
|
|
|
const auto& ptrs = MWBase::Environment::get().getWorld()->getAll(ptr.getCellRef().getRefId());
|
|
|
|
for(const auto& container : ptrs)
|
|
|
|
{
|
|
|
|
// use the new base record
|
|
|
|
container.get<ESM::Container>()->mBase = baseRecord;
|
|
|
|
if(container.getRefData().getCustomData())
|
|
|
|
{
|
|
|
|
auto& store = container.getClass().getContainerStore(container);
|
|
|
|
if(isLevelledList)
|
|
|
|
{
|
|
|
|
if(store.isResolved())
|
|
|
|
{
|
2020-10-21 15:21:28 +00:00
|
|
|
addRandomToStore(itemPtr, count, ptr, store);
|
2020-10-20 09:22:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
addToStore(itemPtr, count, ptr, store, store.isResolved());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
2018-12-06 15:31:47 +00:00
|
|
|
}
|
2020-10-20 09:22:43 +00:00
|
|
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
2020-10-21 15:21:28 +00:00
|
|
|
if(isLevelledList)
|
|
|
|
addRandomToStore(itemPtr, count, ptr, store);
|
|
|
|
else
|
|
|
|
addToStore(itemPtr, count, ptr, store);
|
2010-08-07 13:11:31 +00:00
|
|
|
|
2013-05-09 21:19:04 +00:00
|
|
|
// Spawn a messagebox (only for items added to player's inventory and if player is talking to someone)
|
2014-01-08 17:39:44 +00:00
|
|
|
if (ptr == MWBase::Environment::get().getWorld ()->getPlayerPtr() )
|
2013-02-17 17:58:54 +00:00
|
|
|
{
|
2013-02-17 18:44:00 +00:00
|
|
|
// The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory
|
|
|
|
std::string msgBox;
|
2013-11-21 03:11:06 +00:00
|
|
|
std::string itemName = itemPtr.getClass().getName(itemPtr);
|
2013-02-17 18:44:00 +00:00
|
|
|
if (count == 1)
|
|
|
|
{
|
|
|
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}");
|
2019-05-19 08:33:57 +00:00
|
|
|
msgBox = ::Misc::StringUtils::format(msgBox, itemName);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}");
|
2019-05-19 08:33:57 +00:00
|
|
|
msgBox = ::Misc::StringUtils::format(msgBox, count, itemName);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
2015-01-10 22:21:39 +00:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
2010-08-07 13:11:31 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-12-31 18:09:25 +00:00
|
|
|
template<class R>
|
2010-08-07 14:21:07 +00:00
|
|
|
class OpGetItemCount : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute (Interpreter::Runtime& runtime) override
|
2010-08-07 14:21:07 +00:00
|
|
|
{
|
2010-12-31 18:09:25 +00:00
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
2010-08-07 14:21:07 +00:00
|
|
|
|
|
|
|
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
|
|
|
runtime.pop();
|
|
|
|
|
2015-09-24 13:21:42 +00:00
|
|
|
if(::Misc::StringUtils::ciEqual(item, "gold_005")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_010")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_025")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_100"))
|
2015-07-20 03:48:19 +00:00
|
|
|
item = "gold_001";
|
2016-09-06 14:33:26 +00:00
|
|
|
|
2014-01-08 21:58:36 +00:00
|
|
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr);
|
2010-08-07 14:21:07 +00:00
|
|
|
|
2014-01-08 21:58:36 +00:00
|
|
|
runtime.push (store.count(item));
|
2010-08-07 14:21:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-12-31 18:09:25 +00:00
|
|
|
template<class R>
|
2010-08-07 15:00:04 +00:00
|
|
|
class OpRemoveItem : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute (Interpreter::Runtime& runtime) override
|
2010-08-07 15:00:04 +00:00
|
|
|
{
|
2010-12-31 18:09:25 +00:00
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
2010-08-07 15:00:04 +00:00
|
|
|
|
|
|
|
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
|
|
|
runtime.pop();
|
|
|
|
|
|
|
|
Interpreter::Type_Integer count = runtime[0].mInteger;
|
|
|
|
runtime.pop();
|
2013-02-17 18:44:00 +00:00
|
|
|
|
2010-08-07 15:00:04 +00:00
|
|
|
if (count<0)
|
|
|
|
throw std::runtime_error ("second argument for RemoveItem must be non-negative");
|
|
|
|
|
2013-02-17 18:44:00 +00:00
|
|
|
// no-op
|
|
|
|
if (count == 0)
|
|
|
|
return;
|
|
|
|
|
2015-09-24 13:21:42 +00:00
|
|
|
if(::Misc::StringUtils::ciEqual(item, "gold_005")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_010")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_025")
|
|
|
|
|| ::Misc::StringUtils::ciEqual(item, "gold_100"))
|
2015-07-20 12:53:20 +00:00
|
|
|
item = "gold_001";
|
2016-09-06 14:33:26 +00:00
|
|
|
|
2020-07-26 09:07:18 +00:00
|
|
|
// Explicit calls to non-unique actors affect the base record
|
|
|
|
if(!R::implicit && ptr.getClass().isActor() && MWBase::Environment::get().getWorld()->getStore().getRefCount(ptr.getCellRef().getRefId()) > 1)
|
|
|
|
{
|
|
|
|
ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, -count);
|
|
|
|
return;
|
|
|
|
}
|
2020-10-20 09:22:43 +00:00
|
|
|
// Calls to unresolved containers affect the base record instead
|
|
|
|
else if(ptr.getClass().getTypeName() == typeid(ESM::Container).name() &&
|
|
|
|
(!ptr.getRefData().getCustomData() || !ptr.getClass().getContainerStore(ptr).isResolved()))
|
|
|
|
{
|
|
|
|
ptr.getClass().modifyBaseInventory(ptr.getCellRef().getRefId(), item, -count);
|
|
|
|
const ESM::Container* baseRecord = MWBase::Environment::get().getWorld()->getStore().get<ESM::Container>().find(ptr.getCellRef().getRefId());
|
|
|
|
const auto& ptrs = MWBase::Environment::get().getWorld()->getAll(ptr.getCellRef().getRefId());
|
|
|
|
for(const auto& container : ptrs)
|
|
|
|
{
|
|
|
|
container.get<ESM::Container>()->mBase = baseRecord;
|
|
|
|
if(container.getRefData().getCustomData())
|
|
|
|
{
|
|
|
|
auto& store = container.getClass().getContainerStore(container);
|
|
|
|
// Note that unlike AddItem, RemoveItem only removes from unresolved containers
|
|
|
|
if(!store.isResolved())
|
2020-10-26 19:13:24 +00:00
|
|
|
store.remove(item, count, ptr, false, false);
|
2020-10-20 09:22:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2014-05-22 18:37:22 +00:00
|
|
|
MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr);
|
2013-08-12 23:19:33 +00:00
|
|
|
|
2013-11-15 01:08:36 +00:00
|
|
|
std::string itemName;
|
2017-02-19 14:30:26 +00:00
|
|
|
for (MWWorld::ConstContainerStoreIterator iter(store.cbegin()); iter != store.cend(); ++iter)
|
2018-12-06 15:31:47 +00:00
|
|
|
{
|
2014-05-25 12:13:07 +00:00
|
|
|
if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item))
|
2018-12-06 15:31:47 +00:00
|
|
|
{
|
2013-11-15 01:08:36 +00:00
|
|
|
itemName = iter->getClass().getName(*iter);
|
2018-12-06 15:31:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-02-17 18:44:00 +00:00
|
|
|
|
2017-09-11 10:49:55 +00:00
|
|
|
int numRemoved = store.remove(item, count, ptr);
|
2010-08-07 15:00:04 +00:00
|
|
|
|
2013-05-09 21:19:04 +00:00
|
|
|
// Spawn a messagebox (only for items removed from player's inventory)
|
2013-08-12 23:19:33 +00:00
|
|
|
if ((numRemoved > 0)
|
2015-08-21 09:12:39 +00:00
|
|
|
&& (ptr == MWMechanics::getPlayer()))
|
2012-12-27 15:28:13 +00:00
|
|
|
{
|
2013-02-17 18:44:00 +00:00
|
|
|
// The two GMST entries below expand to strings informing the player of what, and how many of it has been removed from their inventory
|
|
|
|
std::string msgBox;
|
2013-08-12 23:19:33 +00:00
|
|
|
|
2019-02-22 21:14:07 +00:00
|
|
|
if (numRemoved > 1)
|
2013-02-17 18:44:00 +00:00
|
|
|
{
|
|
|
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}");
|
2019-05-19 08:33:57 +00:00
|
|
|
msgBox = ::Misc::StringUtils::format(msgBox, numRemoved, itemName);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}");
|
2019-05-19 08:33:57 +00:00
|
|
|
msgBox = ::Misc::StringUtils::format(msgBox, itemName);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
2015-01-10 22:21:39 +00:00
|
|
|
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
|
2013-02-17 18:44:00 +00:00
|
|
|
}
|
2010-08-07 15:00:04 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-23 19:48:59 +00:00
|
|
|
template <class R>
|
|
|
|
class OpEquip : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute(Interpreter::Runtime &runtime) override
|
2012-11-23 19:48:59 +00:00
|
|
|
{
|
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
|
|
|
|
|
|
|
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
|
|
|
runtime.pop();
|
|
|
|
|
2014-01-19 10:42:58 +00:00
|
|
|
MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
|
2012-11-23 19:48:59 +00:00
|
|
|
MWWorld::ContainerStoreIterator it = invStore.begin();
|
|
|
|
for (; it != invStore.end(); ++it)
|
|
|
|
{
|
2014-05-25 12:13:07 +00:00
|
|
|
if (::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item))
|
2012-11-23 19:48:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (it == invStore.end())
|
2016-09-06 14:33:26 +00:00
|
|
|
{
|
|
|
|
it = ptr.getClass().getContainerStore (ptr).add (item, 1, ptr);
|
2018-08-17 00:32:33 +00:00
|
|
|
Log(Debug::Warning) << "Implicitly adding one " << item <<
|
|
|
|
" to the inventory store of " << ptr.getCellRef().getRefId() <<
|
|
|
|
" to fulfill the requirements of Equip instruction";
|
2016-09-06 14:33:26 +00:00
|
|
|
}
|
2012-11-23 19:48:59 +00:00
|
|
|
|
2018-07-09 15:31:40 +00:00
|
|
|
if (ptr == MWMechanics::getPlayer())
|
|
|
|
MWBase::Environment::get().getWindowManager()->useItem(*it, true);
|
2015-09-07 19:32:28 +00:00
|
|
|
else
|
|
|
|
{
|
2018-07-09 15:31:40 +00:00
|
|
|
std::shared_ptr<MWWorld::Action> action = it->getClass().use(*it, true);
|
2017-04-13 13:18:03 +00:00
|
|
|
action->execute(ptr, true);
|
2015-09-07 19:32:28 +00:00
|
|
|
}
|
2012-11-23 19:48:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-24 01:38:10 +00:00
|
|
|
template <class R>
|
|
|
|
class OpGetArmorType : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute(Interpreter::Runtime &runtime) override
|
2012-11-24 01:38:10 +00:00
|
|
|
{
|
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
|
|
|
|
|
|
|
Interpreter::Type_Integer location = runtime[0].mInteger;
|
|
|
|
runtime.pop();
|
|
|
|
|
|
|
|
int slot;
|
|
|
|
switch (location)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_Helmet;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_Cuirass;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_LeftPauldron;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_RightPauldron;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_Greaves;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_Boots;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_LeftGauntlet;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_RightGauntlet;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_CarriedLeft; // shield
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_LeftGauntlet;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
slot = MWWorld::InventoryStore::Slot_RightGauntlet;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw std::runtime_error ("armor index out of range");
|
|
|
|
}
|
|
|
|
|
2017-02-28 14:43:20 +00:00
|
|
|
const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
|
|
|
|
MWWorld::ConstContainerStoreIterator it = invStore.getSlot (slot);
|
|
|
|
|
2012-11-28 01:48:21 +00:00
|
|
|
if (it == invStore.end() || it->getTypeName () != typeid(ESM::Armor).name())
|
2012-11-24 01:38:10 +00:00
|
|
|
{
|
|
|
|
runtime.push(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-22 18:37:22 +00:00
|
|
|
int skill = it->getClass().getEquipmentSkill (*it) ;
|
2012-11-24 01:38:10 +00:00
|
|
|
if (skill == ESM::Skill::HeavyArmor)
|
|
|
|
runtime.push(2);
|
|
|
|
else if (skill == ESM::Skill::MediumArmor)
|
|
|
|
runtime.push(1);
|
|
|
|
else if (skill == ESM::Skill::LightArmor)
|
|
|
|
runtime.push(0);
|
|
|
|
else
|
|
|
|
runtime.push(-1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-24 01:59:44 +00:00
|
|
|
template <class R>
|
|
|
|
class OpHasItemEquipped : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute(Interpreter::Runtime &runtime) override
|
2012-11-24 01:59:44 +00:00
|
|
|
{
|
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
|
|
|
|
|
|
|
std::string item = runtime.getStringLiteral (runtime[0].mInteger);
|
|
|
|
runtime.pop();
|
|
|
|
|
2017-02-28 14:43:20 +00:00
|
|
|
const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
|
2012-11-24 01:59:44 +00:00
|
|
|
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot)
|
|
|
|
{
|
2017-02-28 14:43:20 +00:00
|
|
|
MWWorld::ConstContainerStoreIterator it = invStore.getSlot (slot);
|
2014-05-25 12:13:07 +00:00
|
|
|
if (it != invStore.end() && ::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item))
|
2012-11-24 01:59:44 +00:00
|
|
|
{
|
|
|
|
runtime.push(1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
runtime.push(0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-25 00:54:37 +00:00
|
|
|
template <class R>
|
|
|
|
class OpHasSoulGem : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute(Interpreter::Runtime &runtime) override
|
2012-11-25 00:54:37 +00:00
|
|
|
{
|
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
2014-02-23 19:11:05 +00:00
|
|
|
|
2014-01-14 05:13:30 +00:00
|
|
|
const std::string &name = runtime.getStringLiteral (runtime[0].mInteger);
|
2012-11-25 00:54:37 +00:00
|
|
|
runtime.pop();
|
|
|
|
|
2014-10-06 12:36:29 +00:00
|
|
|
int count = 0;
|
2017-02-19 14:30:26 +00:00
|
|
|
const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
|
|
|
|
for (MWWorld::ConstContainerStoreIterator it = invStore.cbegin(MWWorld::ContainerStore::Type_Miscellaneous);
|
|
|
|
it != invStore.cend(); ++it)
|
2012-11-25 00:54:37 +00:00
|
|
|
{
|
2014-05-25 12:13:07 +00:00
|
|
|
if (::Misc::StringUtils::ciEqual(it->getCellRef().getSoul(), name))
|
2016-04-11 15:15:02 +00:00
|
|
|
count += it->getRefData().getCount();
|
2012-11-25 00:54:37 +00:00
|
|
|
}
|
2014-10-06 12:36:29 +00:00
|
|
|
runtime.push(count);
|
2012-11-25 00:54:37 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-25 01:06:43 +00:00
|
|
|
template <class R>
|
|
|
|
class OpGetWeaponType : public Interpreter::Opcode0
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2020-10-16 18:18:54 +00:00
|
|
|
void execute(Interpreter::Runtime &runtime) override
|
2012-11-25 01:06:43 +00:00
|
|
|
{
|
|
|
|
MWWorld::Ptr ptr = R()(runtime);
|
|
|
|
|
2017-02-28 14:43:20 +00:00
|
|
|
const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
|
|
|
|
MWWorld::ConstContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight);
|
2019-05-11 00:38:06 +00:00
|
|
|
if (it == invStore.end())
|
2012-11-25 01:06:43 +00:00
|
|
|
{
|
|
|
|
runtime.push(-1);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-11 00:38:06 +00:00
|
|
|
else if (it->getTypeName() != typeid(ESM::Weapon).name())
|
|
|
|
{
|
|
|
|
if (it->getTypeName() == typeid(ESM::Lockpick).name())
|
|
|
|
{
|
|
|
|
runtime.push(-2);
|
|
|
|
}
|
|
|
|
else if (it->getTypeName() == typeid(ESM::Probe).name())
|
|
|
|
{
|
|
|
|
runtime.push(-3);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runtime.push(-1);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2012-11-25 01:06:43 +00:00
|
|
|
|
|
|
|
runtime.push(it->get<ESM::Weapon>()->mBase->mData.mType);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-08-07 13:11:31 +00:00
|
|
|
|
|
|
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
|
|
|
{
|
2013-08-07 00:38:41 +00:00
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeAddItem, new OpAddItem<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeAddItemExplicit, new OpAddItem<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetItemCount, new OpGetItemCount<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetItemCountExplicit, new OpGetItemCount<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeRemoveItem, new OpRemoveItem<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeRemoveItemExplicit, new OpRemoveItem<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeEquip, new OpEquip<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeEquipExplicit, new OpEquip<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetArmorType, new OpGetArmorType<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetArmorTypeExplicit, new OpGetArmorType<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeHasItemEquipped, new OpHasItemEquipped<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeHasItemEquippedExplicit, new OpHasItemEquipped<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeHasSoulGem, new OpHasSoulGem<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeHasSoulGemExplicit, new OpHasSoulGem<ExplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetWeaponType, new OpGetWeaponType<ImplicitRef>);
|
|
|
|
interpreter.installSegment5 (Compiler::Container::opcodeGetWeaponTypeExplicit, new OpGetWeaponType<ExplicitRef>);
|
2010-08-07 13:11:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|