From 1ff49cc637134e75e1101bbd14bcbffe2f4d3b24 Mon Sep 17 00:00:00 2001 From: Jordan Ayers Date: Mon, 18 Jan 2016 19:58:19 -0600 Subject: [PATCH] Improve Drop command behavior. (Fixes #1544) --- apps/openmw/mwscript/miscextensions.cpp | 35 +++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 593fdcca5..51f0c6c55 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -21,6 +21,7 @@ #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" #include "../mwworld/containerstore.hpp" +#include "../mwworld/inventorystore.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" @@ -509,13 +510,43 @@ namespace MWScript if (amount == 0) return; - MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); + // Prefer dropping unequipped items first; re-stack if possible by unequipping items before dropping them. + MWWorld::InventoryStore *invStorePtr = 0; + if (ptr.getClass().hasInventoryStore(ptr)) { + invStorePtr = &ptr.getClass().getInventoryStore(ptr); + + int numNotEquipped = invStorePtr->count(item); + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) + { + MWWorld::ContainerStoreIterator it = invStorePtr->getSlot (slot); + if (it != invStorePtr->end() && ::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item)) + { + numNotEquipped -= it->getRefData().getCount(); + } + } + for (int slot = 0; slot < MWWorld::InventoryStore::Slots && amount > numNotEquipped; ++slot) + { + MWWorld::ContainerStoreIterator it = invStorePtr->getSlot (slot); + if (it != invStorePtr->end() && ::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), item)) + { + int numToRemove = it->getRefData().getCount(); + if (numToRemove > amount - numNotEquipped) + { + numToRemove = amount - numNotEquipped; + } + invStorePtr->unequipItemQuantity(*it, ptr, numToRemove); + numNotEquipped += numToRemove; + } + } + } int toRemove = amount; + MWWorld::ContainerStore& store = ptr.getClass().getContainerStore (ptr); for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) { - if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) + if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item) + && (!invStorePtr || !invStorePtr->isEquipped(*iter))) { int removed = store.remove(*iter, toRemove, ptr); MWWorld::Ptr dropped = MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed);