2013-05-11 16:38:27 +00:00
|
|
|
#include "tradeitemmodel.hpp"
|
|
|
|
|
2022-08-02 22:00:54 +00:00
|
|
|
#include <components/misc/strings/algorithm.hpp>
|
2023-06-27 21:41:06 +00:00
|
|
|
#include <components/settings/values.hpp>
|
2014-02-23 19:11:05 +00:00
|
|
|
|
2013-05-11 16:38:27 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
#include "../mwworld/containerstore.hpp"
|
|
|
|
#include "../mwworld/inventorystore.hpp"
|
|
|
|
|
|
|
|
namespace MWGui
|
|
|
|
{
|
|
|
|
|
2022-08-31 16:49:50 +00:00
|
|
|
TradeItemModel::TradeItemModel(std::unique_ptr<ItemModel> sourceModel, const MWWorld::Ptr& merchant)
|
2013-05-11 16:38:27 +00:00
|
|
|
: mMerchant(merchant)
|
|
|
|
{
|
2022-08-31 16:49:50 +00:00
|
|
|
mSourceModel = std::move(sourceModel);
|
2013-05-11 16:38:27 +00:00
|
|
|
}
|
|
|
|
|
2017-10-03 05:59:31 +00:00
|
|
|
bool TradeItemModel::allowedToUseItems() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-11 16:38:27 +00:00
|
|
|
ItemStack TradeItemModel::getItem(ModelIndex index)
|
|
|
|
{
|
|
|
|
if (index < 0)
|
|
|
|
throw std::runtime_error("Invalid index supplied");
|
|
|
|
if (mItems.size() <= static_cast<size_t>(index))
|
|
|
|
throw std::runtime_error("Item index out of range");
|
|
|
|
return mItems[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t TradeItemModel::getItemCount()
|
|
|
|
{
|
|
|
|
return mItems.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::borrowImpl(const ItemStack& item, std::vector<ItemStack>& out)
|
|
|
|
{
|
|
|
|
bool found = false;
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : out)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
if (itemStack.mBase == item.mBase)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
itemStack.mCount += item.mCount;
|
2013-05-11 16:38:27 +00:00
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
out.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::unborrowImpl(const ItemStack& item, size_t count, std::vector<ItemStack>& out)
|
|
|
|
{
|
|
|
|
std::vector<ItemStack>::iterator it = out.begin();
|
|
|
|
bool found = false;
|
|
|
|
for (; it != out.end(); ++it)
|
|
|
|
{
|
2014-05-31 11:24:13 +00:00
|
|
|
if (it->mBase == item.mBase)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
|
|
|
if (it->mCount < count)
|
|
|
|
throw std::runtime_error("Not enough borrowed items to return");
|
|
|
|
it->mCount -= count;
|
|
|
|
if (it->mCount == 0)
|
|
|
|
out.erase(it);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
throw std::runtime_error("Can't find borrowed item to return");
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::borrowItemFromUs(ModelIndex itemIndex, size_t count)
|
|
|
|
{
|
|
|
|
ItemStack item = getItem(itemIndex);
|
|
|
|
item.mCount = count;
|
|
|
|
borrowImpl(item, mBorrowedFromUs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::borrowItemToUs(ModelIndex itemIndex, ItemModel* source, size_t count)
|
|
|
|
{
|
|
|
|
ItemStack item = source->getItem(itemIndex);
|
|
|
|
item.mCount = count;
|
|
|
|
borrowImpl(item, mBorrowedToUs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::returnItemBorrowedToUs(ModelIndex itemIndex, size_t count)
|
|
|
|
{
|
|
|
|
ItemStack item = getItem(itemIndex);
|
|
|
|
unborrowImpl(item, count, mBorrowedToUs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::returnItemBorrowedFromUs(ModelIndex itemIndex, ItemModel* source, size_t count)
|
|
|
|
{
|
|
|
|
ItemStack item = source->getItem(itemIndex);
|
|
|
|
unborrowImpl(item, count, mBorrowedFromUs);
|
|
|
|
}
|
|
|
|
|
2014-08-24 17:15:02 +00:00
|
|
|
void TradeItemModel::adjustEncumbrance(float& encumbrance)
|
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : mBorrowedToUs)
|
2014-08-24 17:15:02 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
MWWorld::Ptr& item = itemStack.mBase;
|
|
|
|
encumbrance += item.getClass().getWeight(item) * itemStack.mCount;
|
2014-08-24 17:15:02 +00:00
|
|
|
}
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : mBorrowedFromUs)
|
2014-08-24 17:15:02 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
MWWorld::Ptr& item = itemStack.mBase;
|
|
|
|
encumbrance -= item.getClass().getWeight(item) * itemStack.mCount;
|
2014-08-24 17:15:02 +00:00
|
|
|
}
|
|
|
|
encumbrance = std::max(0.f, encumbrance);
|
|
|
|
}
|
|
|
|
|
2013-05-11 16:38:27 +00:00
|
|
|
void TradeItemModel::abort()
|
|
|
|
{
|
|
|
|
mBorrowedFromUs.clear();
|
|
|
|
mBorrowedToUs.clear();
|
|
|
|
}
|
|
|
|
|
2020-10-13 15:46:32 +00:00
|
|
|
const std::vector<ItemStack> TradeItemModel::getItemsBorrowedToUs() const
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
|
|
|
return mBorrowedToUs;
|
|
|
|
}
|
|
|
|
|
2014-09-28 10:18:46 +00:00
|
|
|
void TradeItemModel::transferItems()
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : mBorrowedToUs)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
|
|
|
// get index in the source model
|
2019-03-02 09:27:59 +00:00
|
|
|
ItemModel* sourceModel = itemStack.mCreator;
|
2013-05-11 16:38:27 +00:00
|
|
|
size_t i = 0;
|
|
|
|
for (; i < sourceModel->getItemCount(); ++i)
|
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
if (itemStack.mBase == sourceModel->getItem(i).mBase)
|
2013-05-11 16:38:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == sourceModel->getItemCount())
|
|
|
|
throw std::runtime_error("The borrowed item disappeared");
|
|
|
|
|
2023-07-15 16:19:52 +00:00
|
|
|
sourceModel->moveItem(
|
|
|
|
sourceModel->getItem(i), itemStack.mCount, this, !Settings::game().mPreventMerchantEquipping);
|
2013-05-11 16:38:27 +00:00
|
|
|
}
|
|
|
|
mBorrowedToUs.clear();
|
|
|
|
mBorrowedFromUs.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TradeItemModel::update()
|
|
|
|
{
|
|
|
|
mSourceModel->update();
|
|
|
|
|
|
|
|
int services = 0;
|
|
|
|
if (!mMerchant.isEmpty())
|
2014-05-22 18:37:22 +00:00
|
|
|
services = mMerchant.getClass().getServices(mMerchant);
|
2013-05-11 16:38:27 +00:00
|
|
|
|
|
|
|
mItems.clear();
|
|
|
|
// add regular items
|
|
|
|
for (size_t i = 0; i < mSourceModel->getItemCount(); ++i)
|
|
|
|
{
|
|
|
|
ItemStack item = mSourceModel->getItem(i);
|
2013-08-15 11:52:01 +00:00
|
|
|
if (!mMerchant.isEmpty())
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2013-08-15 11:52:01 +00:00
|
|
|
MWWorld::Ptr base = item.mBase;
|
2022-10-18 07:26:55 +00:00
|
|
|
if (base.getCellRef().getRefId() == MWWorld::ContainerStore::sGoldId)
|
2013-08-15 11:52:01 +00:00
|
|
|
continue;
|
2016-09-24 16:01:31 +00:00
|
|
|
|
|
|
|
if (!base.getClass().showsInInventory(base))
|
|
|
|
return;
|
|
|
|
|
2014-05-22 18:37:22 +00:00
|
|
|
if (!base.getClass().canSell(base, services))
|
2013-08-15 11:52:01 +00:00
|
|
|
continue;
|
|
|
|
|
2014-01-02 00:31:06 +00:00
|
|
|
// Bound items may not be bought
|
2014-09-13 22:59:13 +00:00
|
|
|
if (item.mFlags & ItemStack::Flag_Bound)
|
2014-01-02 00:31:06 +00:00
|
|
|
continue;
|
|
|
|
|
2013-08-15 11:52:01 +00:00
|
|
|
// don't show equipped items
|
2014-01-19 10:42:58 +00:00
|
|
|
if (mMerchant.getClass().hasInventoryStore(mMerchant))
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2014-05-22 18:37:22 +00:00
|
|
|
MWWorld::InventoryStore& store = mMerchant.getClass().getInventoryStore(mMerchant);
|
2014-12-15 12:47:34 +00:00
|
|
|
if (store.isEquipped(base))
|
2013-05-11 16:38:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't show items that we borrowed to someone else
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : mBorrowedFromUs)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
if (itemStack.mBase == item.mBase)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
if (item.mCount < itemStack.mCount)
|
2013-05-11 16:38:27 +00:00
|
|
|
throw std::runtime_error("Lent more items than present");
|
2019-03-02 09:27:59 +00:00
|
|
|
item.mCount -= itemStack.mCount;
|
2013-05-11 16:38:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item.mCount > 0)
|
|
|
|
mItems.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add items borrowed to us
|
2019-03-02 09:27:59 +00:00
|
|
|
for (ItemStack& itemStack : mBorrowedToUs)
|
2013-05-11 16:38:27 +00:00
|
|
|
{
|
2019-03-02 09:27:59 +00:00
|
|
|
itemStack.mType = ItemStack::Type_Barter;
|
|
|
|
mItems.push_back(itemStack);
|
2013-05-11 16:38:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|