You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/openmw/mwgui/inventoryitemmodel.cpp

149 lines
4.9 KiB
C++

#include "inventoryitemmodel.hpp"
#include <sstream>
#include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
namespace MWGui
{
InventoryItemModel::InventoryItemModel(const MWWorld::Ptr& actor)
: mActor(actor)
{
}
ItemStack InventoryItemModel::getItem(ModelIndex index)
{
if (index < 0)
throw std::runtime_error("Invalid index supplied");
if (mItems.size() <= static_cast<size_t>(index))
throw std::runtime_error("Item index out of range");
return mItems[index];
}
size_t InventoryItemModel::getItemCount()
{
return mItems.size();
}
ItemModel::ModelIndex InventoryItemModel::getIndex(const ItemStack& item)
{
size_t i = 0;
for (ItemStack& itemStack : mItems)
{
if (itemStack == item)
return i;
++i;
}
return -1;
}
MWWorld::Ptr InventoryItemModel::addItem(const ItemStack& item, size_t count, bool allowAutoEquip)
{
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
throw std::runtime_error("Item to add needs to be from a different container!");
return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, allowAutoEquip);
}
MWWorld::Ptr InventoryItemModel::copyItem(const ItemStack& item, size_t count, bool allowAutoEquip)
{
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
throw std::runtime_error("Item to copy needs to be from a different container!");
return *mActor.getClass().getContainerStore(mActor).add(
item.mBase.getCellRef().getRefId(), count, allowAutoEquip);
}
void InventoryItemModel::removeItem(const ItemStack& item, size_t count)
{
int removed = 0;
// Re-equipping makes sense only if a target has inventory
if (mActor.getClass().hasInventoryStore(mActor))
{
MWWorld::InventoryStore& store = mActor.getClass().getInventoryStore(mActor);
removed = store.remove(item.mBase, count, true);
}
else
{
MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor);
removed = store.remove(item.mBase, count);
}
std::stringstream error;
if (removed == 0)
{
error << "Item '" << item.mBase.getCellRef().getRefId() << "' was not found in container store to remove";
throw std::runtime_error(error.str());
}
else if (removed < static_cast<int>(count))
{
error << "Not enough items '" << item.mBase.getCellRef().getRefId() << "' in the stack to remove ("
<< static_cast<int>(count) << " requested, " << removed << " found)";
throw std::runtime_error(error.str());
}
}
MWWorld::Ptr InventoryItemModel::moveItem(
const ItemStack& item, size_t count, ItemModel* otherModel, bool allowAutoEquip)
{
// Can't move conjured items: This is a general fix that also takes care of issues with taking conjured items
// via the 'Take All' button.
if (item.mFlags & ItemStack::Flag_Bound)
return MWWorld::Ptr();
return ItemModel::moveItem(item, count, otherModel, allowAutoEquip);
}
void InventoryItemModel::update()
{
MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor);
mItems.clear();
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
MWWorld::Ptr item = *it;
if (!item.getClass().showsInInventory(item))
continue;
ItemStack newItem(item, this, item.getCellRef().getCount());
if (mActor.getClass().hasInventoryStore(mActor))
{
MWWorld::InventoryStore& invStore = mActor.getClass().getInventoryStore(mActor);
if (invStore.isEquipped(newItem.mBase))
newItem.mType = ItemStack::Type_Equipped;
}
mItems.push_back(newItem);
}
}
bool InventoryItemModel::onTakeItem(const MWWorld::Ptr& item, int count)
{
// Looting a dead corpse is considered OK
if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead())
return true;
MWWorld::Ptr player = MWMechanics::getPlayer();
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item, mActor, count);
return true;
}
bool InventoryItemModel::usesContainer(const MWWorld::Ptr& container)
{
return mActor == container;
}
}