Sell owned items in the cell

This commit is contained in:
scrawl 2013-05-27 02:18:36 +02:00
parent de5a08a07d
commit 3a6e54c4f5
8 changed files with 131 additions and 14 deletions

View file

@ -342,6 +342,8 @@ namespace MWBase
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
///< get all containers in active cells owned by this Npc
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out) = 0;
///< get all items in active cells owned by this Npc
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0;

View file

@ -3,11 +3,39 @@
#include "../mwworld/containerstore.hpp"
#include "../mwworld/class.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace
{
bool stacks (const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
if (left == right)
return true;
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (left.getContainerStore() && right.getContainerStore())
return left.getContainerStore()->stacks(left, right)
&& right.getContainerStore()->stacks(left, right);
if (left.getContainerStore())
return left.getContainerStore()->stacks(left, right);
if (right.getContainerStore())
return right.getContainerStore()->stacks(left, right);
MWWorld::ContainerStore store;
return store.stacks(left, right);
}
}
namespace MWGui
{
ContainerItemModel::ContainerItemModel(const std::vector<MWWorld::Ptr>& itemSources)
ContainerItemModel::ContainerItemModel(const std::vector<MWWorld::Ptr>& itemSources, const std::vector<MWWorld::Ptr>& worldItems)
: mItemSources(itemSources)
, mWorldItems(worldItems)
{
assert (mItemSources.size());
}
@ -65,8 +93,7 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (*it == item.mBase || (store.stacks(*it, item.mBase) && item.mBase.getContainerStore()->stacks(*it, item.mBase)))
if (stacks(*it, item.mBase))
{
int refCount = it->getRefData().getCount();
it->getRefData().setCount(std::max(0, refCount - toRemove));
@ -76,6 +103,21 @@ void ContainerItemModel::removeItem (const ItemStack& item, size_t count)
}
}
}
for (std::vector<MWWorld::Ptr>::iterator source = mWorldItems.begin(); source != mWorldItems.end(); ++source)
{
if (stacks(*source, item.mBase))
{
int refCount = source->getRefData().getCount();
if (refCount - toRemove <= 0)
MWBase::Environment::get().getWorld()->deleteObject(*source);
else
source->getRefData().setCount(std::max(0, refCount - toRemove));
toRemove -= refCount;
if (toRemove <= 0)
return;
}
}
throw std::runtime_error("Not enough items to remove could be found");
}
@ -91,8 +133,7 @@ void ContainerItemModel::update()
std::vector<ItemStack>::iterator itemStack = mItems.begin();
for (; itemStack != mItems.end(); ++itemStack)
{
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (store.stacks(itemStack->mBase, *it) && it->getContainerStore()->stacks(itemStack->mBase, *it))
if (stacks(*it, itemStack->mBase))
{
// we already have an item stack of this kind, add to it
itemStack->mCount += it->getRefData().getCount();
@ -108,6 +149,26 @@ void ContainerItemModel::update()
}
}
}
for (std::vector<MWWorld::Ptr>::iterator source = mWorldItems.begin(); source != mWorldItems.end(); ++source)
{
std::vector<ItemStack>::iterator itemStack = mItems.begin();
for (; itemStack != mItems.end(); ++itemStack)
{
if (stacks(*source, itemStack->mBase))
{
// we already have an item stack of this kind, add to it
itemStack->mCount += source->getRefData().getCount();
break;
}
}
if (itemStack == mItems.end())
{
// no stack yet, create one
ItemStack newItem (*source, this, source->getRefData().getCount());
mItems.push_back(newItem);
}
}
}
}

View file

@ -11,7 +11,7 @@ namespace MWGui
class ContainerItemModel : public ItemModel
{
public:
ContainerItemModel (const std::vector<MWWorld::Ptr>& itemSources);
ContainerItemModel (const std::vector<MWWorld::Ptr>& itemSources, const std::vector<MWWorld::Ptr>& worldItems);
///< @note The order of elements \a itemSources matters here. The first element has the highest priority for removal,
/// while the last element will be used to add new items to.
@ -28,6 +28,7 @@ namespace MWGui
private:
std::vector<MWWorld::Ptr> mItemSources;
std::vector<MWWorld::Ptr> mWorldItems;
std::vector<ItemStack> mItems;
};

View file

@ -13,8 +13,6 @@ namespace MWGui
, mType(Type_Normal)
, mBase(base)
{
assert(base.getContainerStore());
if (MWWorld::Class::get(base).getEnchantment(base) != "")
mFlags |= Flag_Enchanted;
}
@ -31,18 +29,42 @@ namespace MWGui
{
if(mBase == other.mBase)
return true;
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (mBase.getContainerStore() && other.mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase)
&& other.mBase.getContainerStore()->stacks(mBase, other.mBase);
if (mBase.getContainerStore())
return mBase.getContainerStore()->stacks(mBase, other.mBase);
if (other.mBase.getContainerStore())
return other.mBase.getContainerStore()->stacks(mBase, other.mBase);
MWWorld::ContainerStore store;
return store.stacks(mBase, other.mBase);
}
bool operator == (const ItemStack& left, const ItemStack& right)
{
if (left.mType != right.mType)
return false;
if(left.mBase == right.mBase)
return true;
// If one of the items is in an inventory and currently equipped, we need to check stacking both ways to be sure
if (left.mBase.getContainerStore() && right.mBase.getContainerStore())
return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase)
&& right.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
if (left.mBase.getContainerStore())
return left.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
if (right.mBase.getContainerStore())
return right.mBase.getContainerStore()->stacks(left.mBase, right.mBase);
MWWorld::ContainerStore store;
return store.stacks(left.mBase, right.mBase);
}
ItemModel::ItemModel()

View file

@ -71,7 +71,7 @@ namespace MWGui
if (item.mType == ItemStack::Type_Equipped && !mShowEquipped)
return false;
int category;
int category = 0;
if (base.getTypeName() == typeid(ESM::Armor).name()
|| base.getTypeName() == typeid(ESM::Clothing).name())
category = Category_Apparel;

View file

@ -88,8 +88,10 @@ namespace MWGui
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
// Important: actor goes last, so that items purchased by the merchant go into his inventory
itemSources.push_back(actor);
std::vector<MWWorld::Ptr> worldItems;
MWBase::Environment::get().getWorld()->getItemsOwnedBy(actor, worldItems);
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources), mPtr);
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr);
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel (mSortModel);

View file

@ -1724,4 +1724,31 @@ namespace MWWorld
}
}
}
struct ListHandlesFunctor
{
std::vector<std::string> mHandles;
bool operator() (ESM::CellRef& ref, RefData& data)
{
Ogre::SceneNode* handle = data.getBaseNode();
if (handle)
mHandles.push_back(handle->getName());
return true;
}
};
void World::getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out)
{
const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells();
for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt)
{
ListHandlesFunctor functor;
(*cellIt)->forEach<ListHandlesFunctor>(functor);
for (std::vector<std::string>::iterator it = functor.mHandles.begin(); it != functor.mHandles.end(); ++it)
if (Misc::StringUtils::ciEqual(searchPtrViaHandle(*it).mCellRef->mOwner, npc.getCellRef().mRefID))
out.push_back(searchPtrViaHandle(*it));
}
}
}

View file

@ -391,6 +391,8 @@ namespace MWWorld
virtual void getContainersOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
///< get all containers in active cells owned by this Npc
virtual void getItemsOwnedBy (const MWWorld::Ptr& npc, std::vector<MWWorld::Ptr>& out);
///< get all items in active cells owned by this Npc
virtual void setupExternalRendering (MWRender::ExternalRendering& rendering);