Unequip all items from dead corpse when take all items (bug #4095)

pull/296/head^2
Andrei Kortunov 7 years ago
parent 335ecd1162
commit 4580024d76

@ -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; i<mModel->getItemCount(); ++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; i<mModel->getItemCount(); ++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)

@ -1,5 +1,10 @@
#include "inventoryitemmodel.hpp"
#include <sstream>
#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<int>(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<int>(count) << " requested, " << removed << " found)";
throw std::runtime_error(error.str());
}
}
MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel)

@ -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)

@ -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());

@ -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

@ -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);

@ -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

Loading…
Cancel
Save