forked from teamnwah/openmw-tes3coop
Sell owned items in the cell
This commit is contained in:
parent
de5a08a07d
commit
3a6e54c4f5
8 changed files with 131 additions and 14 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue