#include "inventoryitemmodel.hpp" #include #include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwworld/class.hpp" #include "../mwworld/containerstore.hpp" #include "../mwworld/inventorystore.hpp" #include "../mwworld/manualref.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(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!"); MWWorld::ManualRef newRef(*MWBase::Environment::get().getESMStore(), item.mBase, count); return *mActor.getClass().getContainerStore(mActor).add(newRef.getPtr(), 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(count)) { error << "Not enough items '" << item.mBase.getCellRef().getRefId() << "' in the stack to remove (" << static_cast(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; } }