diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index c9be21322..0ba4839e7 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -11,6 +11,7 @@ #include "../mwmechanics/actorutil.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwmechanics/pickpocket.hpp" #include "../mwmechanics/creaturestats.hpp" @@ -211,31 +212,48 @@ namespace MWGui void ContainerWindow::onTakeAllButtonClicked(MyGUI::Widget* _sender) { - if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) + if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop) + return; + + // transfer everything into the player's inventory + ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); + mModel->update(); + + // unequip all items to avoid unequipping/reequipping + if (mPtr.getClass().hasInventoryStore(mPtr)) { - // transfer everything into the player's inventory - ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel(); - mModel->update(); + MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); for (size_t i=0; igetItemCount(); ++i) { - if (i==0) - { - // play the sound of the first object - MWWorld::Ptr item = mModel->getItem(i).mBase; - std::string sound = item.getClass().getUpSoundId(item); - MWBase::Environment::get().getWindowManager()->playSound(sound); - } - const ItemStack& item = mModel->getItem(i); + if (invStore.isEquipped(item.mBase) == false) + continue; + + invStore.unequipItem(item.mBase, mPtr); + } + } - if (!onTakeItem(item, item.mCount)) - break; + mModel->update(); - mModel->moveItem(item, item.mCount, playerModel); + for (size_t i=0; igetItemCount(); ++i) + { + if (i==0) + { + // play the sound of the first object + MWWorld::Ptr item = mModel->getItem(i).mBase; + std::string sound = item.getClass().getUpSoundId(item); + MWBase::Environment::get().getWindowManager()->playSound(sound); } - MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); + const ItemStack& item = mModel->getItem(i); + + if (!onTakeItem(item, item.mCount)) + break; + + mModel->moveItem(item, item.mCount, playerModel); } + + MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container); } void ContainerWindow::onDisposeCorpseButtonClicked(MyGUI::Widget *sender) diff --git a/apps/openmw/mwgui/inventoryitemmodel.cpp b/apps/openmw/mwgui/inventoryitemmodel.cpp index 2fe540f22..222243ec1 100644 --- a/apps/openmw/mwgui/inventoryitemmodel.cpp +++ b/apps/openmw/mwgui/inventoryitemmodel.cpp @@ -1,5 +1,10 @@ #include "inventoryitemmodel.hpp" +#include + +#include "../mwmechanics/actorutil.hpp" +#include "../mwmechanics/npcstats.hpp" + #include "../mwworld/containerstore.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" @@ -45,16 +50,33 @@ MWWorld::Ptr InventoryItemModel::copyItem (const ItemStack& item, size_t count, return *mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner); } - void InventoryItemModel::removeItem (const ItemStack& item, size_t count) { - MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor); - int removed = store.remove(item.mBase, count, mActor); + 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, mActor, true); + } + else + { + MWWorld::ContainerStore& store = mActor.getClass().getContainerStore(mActor); + removed = store.remove(item.mBase, count, mActor); + } + + std::stringstream error; if (removed == 0) - throw std::runtime_error("Item to remove not found in container store"); + { + 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)) - throw std::runtime_error("Not enough items in the stack to remove"); + { + 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) diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index dfc066bcd..8457b33cb 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -143,8 +143,7 @@ namespace MWScript if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) itemName = iter->getClass().getName(*iter); - // Actors should not equip a replacement when items are removed with RemoveItem - int numRemoved = store.remove(item, count, ptr, false); + int numRemoved = store.remove(item, count, ptr); // Spawn a messagebox (only for items removed from player's inventory) if ((numRemoved > 0) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index eef10b905..cd04a425b 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -408,13 +408,13 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addNewStack (const Cons return it; } -int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement) +int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const Ptr& actor) { int toRemove = count; for (ContainerStoreIterator iter(begin()); iter != end() && toRemove > 0; ++iter) if (Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), itemId)) - toRemove -= remove(*iter, toRemove, actor, equipReplacement); + toRemove -= remove(*iter, toRemove, actor); flagAsModified(); @@ -422,7 +422,7 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const return count - toRemove; } -int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement) +int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor) { assert(this == item.getContainerStore()); diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index f27ff1db9..dbb82cbda 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -142,12 +142,12 @@ namespace MWWorld ContainerStoreIterator add(const std::string& id, int count, const Ptr& actorPtr); ///< Utility to construct a ManualRef and call add(ptr, count, actorPtr, true) - int remove(const std::string& itemId, int count, const Ptr& actor, bool equipReplacement = true); + int remove(const std::string& itemId, int count, const Ptr& actor); ///< Remove \a count item(s) designated by \a itemId from this container. /// /// @return the number of items actually removed - virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = true); + virtual int remove(const Ptr& item, int count, const Ptr& actor); ///< Remove \a count item(s) designated by \a item from this inventory. /// /// @return the number of items actually removed diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index a6394757f..b599b3583 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -654,6 +654,11 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSelectedEnchantItem( return mSelectedEnchantItem; } +int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor) +{ + return remove(item, count, actor, false); +} + int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement) { int retCount = ContainerStore::remove(item, count, actor); diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 90f7f7788..851abf408 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -177,7 +177,8 @@ namespace MWWorld virtual bool stacks (const ConstPtr& ptr1, const ConstPtr& ptr2) const; ///< @return true if the two specified objects can stack with each other - virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement = true); + virtual int remove(const Ptr& item, int count, const Ptr& actor); + virtual int remove(const Ptr& item, int count, const Ptr& actor, bool equipReplacement); ///< Remove \a count item(s) designated by \a item from this inventory. /// /// @return the number of items actually removed