1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 23:49:55 +00:00
openmw-tes3mp/apps/openmw/mwgui/tradewindow.cpp

560 lines
21 KiB
C++
Raw Normal View History

#include "tradewindow.hpp"
2015-01-10 01:50:43 +00:00
#include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
#include <MyGUI_ControllerManager.h>
#include <MyGUI_ControllerRepeatClick.h>
2014-09-25 18:28:00 +00:00
#include <components/widgets/numericeditbox.hpp>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/Networking.hpp"
#include "../mwmp/ObjectList.hpp"
/*
End of tes3mp addition
*/
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
2012-11-09 23:38:45 +00:00
#include "../mwbase/dialoguemanager.hpp"
2013-05-11 16:38:27 +00:00
#include "../mwworld/class.hpp"
#include "../mwworld/containerstore.hpp"
2015-02-09 14:01:49 +00:00
#include "../mwworld/esmstore.hpp"
2015-08-21 09:12:39 +00:00
#include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "inventorywindow.hpp"
2013-05-11 16:38:27 +00:00
#include "itemview.hpp"
#include "sortfilteritemmodel.hpp"
#include "containeritemmodel.hpp"
#include "tradeitemmodel.hpp"
#include "countdialog.hpp"
#include "tooltips.hpp"
2012-05-17 19:15:48 +00:00
namespace
{
int getEffectiveValue (MWWorld::Ptr item, int count)
{
float price = static_cast<float>(item.getClass().getValue(item));
if (item.getClass().hasItemHealth(item))
{
price *= item.getClass().getItemNormalizedHealth(item);
}
return static_cast<int>(price * count);
}
}
namespace MWGui
{
2013-05-11 16:38:27 +00:00
TradeWindow::TradeWindow()
2020-05-12 20:13:01 +00:00
#ifdef USE_OPENXR
: WindowBase("openmw_trade_window_vr.layout")
#else
2013-05-11 16:38:27 +00:00
: WindowBase("openmw_trade_window.layout")
2020-05-12 20:13:01 +00:00
#endif
2018-10-09 06:21:12 +00:00
, mSortModel(nullptr)
, mTradeModel(nullptr)
2015-04-25 18:37:42 +00:00
, mItemToSell(-1)
, mCurrentBalance(0)
2013-07-31 16:46:32 +00:00
, mCurrentMerchantOffer(0)
{
2012-05-17 19:15:48 +00:00
getWidget(mFilterAll, "AllButton");
getWidget(mFilterWeapon, "WeaponButton");
getWidget(mFilterApparel, "ApparelButton");
getWidget(mFilterMagic, "MagicButton");
getWidget(mFilterMisc, "MiscButton");
getWidget(mMaxSaleButton, "MaxSaleButton");
getWidget(mCancelButton, "CancelButton");
getWidget(mOfferButton, "OfferButton");
getWidget(mPlayerGold, "PlayerGold");
getWidget(mMerchantGold, "MerchantGold");
getWidget(mIncreaseButton, "IncreaseButton");
getWidget(mDecreaseButton, "DecreaseButton");
getWidget(mTotalBalance, "TotalBalance");
getWidget(mTotalBalanceLabel, "TotalBalanceLabel");
getWidget(mBottomPane, "BottomPane");
getWidget(mFilterEdit, "FilterEdit");
2012-05-17 19:15:48 +00:00
2013-05-11 16:38:27 +00:00
getWidget(mItemView, "ItemView");
mItemView->eventItemClicked += MyGUI::newDelegate(this, &TradeWindow::onItemSelected);
2012-05-17 19:15:48 +00:00
mFilterAll->setStateSelected(true);
mFilterAll->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterWeapon->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterApparel->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterMagic->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterMisc->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onFilterChanged);
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &TradeWindow::onNameFilterChanged);
2012-05-17 19:15:48 +00:00
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked);
mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked);
mMaxSaleButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onMaxSaleButtonClicked);
mIncreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonPressed);
mIncreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed);
mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
2012-05-17 19:15:48 +00:00
2014-09-25 18:28:00 +00:00
mTotalBalance->eventValueChanged += MyGUI::newDelegate(this, &TradeWindow::onBalanceValueChanged);
mTotalBalance->eventEditSelectAccept += MyGUI::newDelegate(this, &TradeWindow::onAccept);
2018-09-20 12:02:26 +00:00
mTotalBalance->setMinValue(std::numeric_limits<int>::min()+1); // disallow INT_MIN since abs(INT_MIN) is undefined
2014-05-31 11:53:36 +00:00
setCoord(400, 0, 400, 300);
}
2012-05-17 15:15:44 +00:00
void TradeWindow::setPtr(const MWWorld::Ptr& actor)
{
2013-05-11 16:38:27 +00:00
mPtr = actor;
mCurrentBalance = 0;
mCurrentMerchantOffer = 0;
2013-05-11 16:38:27 +00:00
std::vector<MWWorld::Ptr> itemSources;
// Important: actor goes first, so purchased items come out of the actor's pocket first
itemSources.push_back(actor);
2013-05-11 16:38:27 +00:00
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
2013-05-27 00:18:36 +00:00
std::vector<MWWorld::Ptr> worldItems;
MWBase::Environment::get().getWorld()->getItemsOwnedBy(actor, worldItems);
2013-05-27 00:18:36 +00:00
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr);
2013-05-11 16:38:27 +00:00
mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel (mSortModel);
mItemView->resetScrollBars();
updateLabels();
setTitle(actor.getClass().getName(actor));
2013-11-30 07:33:18 +00:00
onFilterChanged(mFilterAll);
mFilterEdit->setCaption("");
}
void TradeWindow::onFrame(float dt)
{
checkReferenceAvailable();
}
void TradeWindow::onNameFilterChanged(MyGUI::EditBox* _sender)
{
mSortModel->setNameFilter(_sender->getCaption());
mItemView->update();
}
void TradeWindow::onFilterChanged(MyGUI::Widget* _sender)
{
if (_sender == mFilterAll)
2013-05-11 16:38:27 +00:00
mSortModel->setCategory(SortFilterItemModel::Category_All);
else if (_sender == mFilterWeapon)
2013-05-11 16:38:27 +00:00
mSortModel->setCategory(SortFilterItemModel::Category_Weapon);
else if (_sender == mFilterApparel)
2013-05-11 16:38:27 +00:00
mSortModel->setCategory(SortFilterItemModel::Category_Apparel);
else if (_sender == mFilterMagic)
2013-05-11 16:38:27 +00:00
mSortModel->setCategory(SortFilterItemModel::Category_Magic);
else if (_sender == mFilterMisc)
2013-05-11 16:38:27 +00:00
mSortModel->setCategory(SortFilterItemModel::Category_Misc);
mFilterAll->setStateSelected(false);
mFilterWeapon->setStateSelected(false);
mFilterApparel->setStateSelected(false);
mFilterMagic->setStateSelected(false);
mFilterMisc->setStateSelected(false);
2014-09-13 02:07:40 +00:00
_sender->castType<MyGUI::Button>()->setStateSelected(true);
2013-05-11 16:38:27 +00:00
mItemView->update();
2012-05-17 15:15:44 +00:00
}
2012-05-17 19:15:48 +00:00
2013-05-11 16:38:27 +00:00
int TradeWindow::getMerchantServices()
2012-05-17 19:15:48 +00:00
{
return mPtr.getClass().getServices(mPtr);
2013-05-11 16:38:27 +00:00
}
2017-09-23 10:18:39 +00:00
bool TradeWindow::exit()
{
mTradeModel->abort();
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel()->abort();
2017-09-23 10:18:39 +00:00
return true;
}
2013-05-11 16:38:27 +00:00
void TradeWindow::onItemSelected (int index)
{
const ItemStack& item = mSortModel->getItem(index);
MWWorld::Ptr object = item.mBase;
int count = item.mCount;
bool shift = MyGUI::InputManager::getInstance().isShiftPressed();
if (MyGUI::InputManager::getInstance().isControlPressed())
count = 1;
if (count > 1 && !shift)
{
CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog();
std::string message = "#{sQuanityMenuMessage02}";
std::string name = object.getClass().getName(object) + MWGui::ToolTips::getSoulString(object.getCellRef());
dialog->openCountDialog(name, message, count);
2013-05-11 16:38:27 +00:00
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &TradeWindow::sellItem);
mItemToSell = mSortModel->mapToSource(index);
}
else
{
mItemToSell = mSortModel->mapToSource(index);
2018-10-09 06:21:12 +00:00
sellItem (nullptr, count);
2013-05-11 16:38:27 +00:00
}
}
void TradeWindow::sellItem(MyGUI::Widget* sender, int count)
{
const ItemStack& item = mTradeModel->getItem(mItemToSell);
std::string sound = item.mBase.getClass().getUpSoundId(item.mBase);
MWBase::Environment::get().getWindowManager()->playSound(sound);
2013-05-11 16:38:27 +00:00
TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
if (item.mType == ItemStack::Type_Barter)
{
// this was an item borrowed to us by the player
mTradeModel->returnItemBorrowedToUs(mItemToSell, count);
playerTradeModel->returnItemBorrowedFromUs(mItemToSell, mTradeModel, count);
buyFromNpc(item.mBase, count, true);
}
else
{
// borrow item to player
playerTradeModel->borrowItemToUs(mItemToSell, mTradeModel, count);
mTradeModel->borrowItemFromUs(mItemToSell, count);
buyFromNpc(item.mBase, count, false);
}
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->updateItemView();
mItemView->update();
}
void TradeWindow::borrowItem (int index, size_t count)
{
TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
mTradeModel->borrowItemToUs(index, playerTradeModel, count);
mItemView->update();
sellToNpc(playerTradeModel->getItem(index).mBase, count, false);
}
void TradeWindow::returnItem (int index, size_t count)
{
TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
const ItemStack& item = playerTradeModel->getItem(index);
mTradeModel->returnItemBorrowedFromUs(index, playerTradeModel, count);
mItemView->update();
sellToNpc(item.mBase, count, true);
2012-05-17 19:15:48 +00:00
}
void TradeWindow::addOrRemoveGold(int amount, const MWWorld::Ptr& actor)
2012-09-08 22:17:03 +00:00
{
MWWorld::ContainerStore& store = actor.getClass().getContainerStore(actor);
if (amount > 0)
2012-09-08 22:17:03 +00:00
{
store.add(MWWorld::ContainerStore::sGoldId, amount, actor);
2012-09-08 22:17:03 +00:00
}
else
{
store.remove(MWWorld::ContainerStore::sGoldId, - amount, actor);
}
2012-09-08 22:17:03 +00:00
}
2012-05-17 19:15:48 +00:00
void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
{
2013-05-11 16:38:27 +00:00
TradeItemModel* playerItemModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
// were there any items traded at all?
const std::vector<ItemStack>& playerBought = playerItemModel->getItemsBorrowedToUs();
const std::vector<ItemStack>& merchantBought = mTradeModel->getItemsBorrowedToUs();
if (playerBought.empty() && merchantBought.empty())
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox("#{sBarterDialog11}");
return;
}
2015-08-21 09:12:39 +00:00
MWWorld::Ptr player = MWMechanics::getPlayer();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
// check if the player can afford this
if (mCurrentBalance < 0 && playerGold < std::abs(mCurrentBalance))
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox("#{sBarterDialog1}");
return;
}
// check if the merchant can afford this
if (mCurrentBalance > 0 && getMerchantGold() < mCurrentBalance)
{
// user notification
MWBase::Environment::get().getWindowManager()->
messageBox("#{sBarterDialog2}");
return;
}
// check if the player is attempting to sell back an item stolen from this actor
for (const ItemStack& itemStack : merchantBought)
{
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(itemStack.mBase.getCellRef().getRefId(), mPtr))
{
2018-08-29 15:38:12 +00:00
std::string msg = gmst.find("sNotifyMessage49")->mValue.getString();
msg = Misc::StringUtils::format(msg, itemStack.mBase.getClass().getName(itemStack.mBase));
MWBase::Environment::get().getWindowManager()->messageBox(msg);
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, itemStack.mBase, mPtr, itemStack.mCount);
onCancelButtonClicked(mCancelButton);
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
return;
}
}
bool offerAccepted = mTrading.haggle(player, mPtr, mCurrentBalance, mCurrentMerchantOffer);
// apply disposition change if merchant is NPC
if ( mPtr.getClass().isNpc() ) {
int dispositionDelta = offerAccepted
2018-08-29 15:38:12 +00:00
? gmst.find("iBarterSuccessDisposition")->mValue.getInteger()
: gmst.find("iBarterFailDisposition")->mValue.getInteger();
MWBase::Environment::get().getDialogueManager()->applyBarterDispositionChange(dispositionDelta);
2013-05-11 16:38:27 +00:00
}
// display message on haggle failure
if ( !offerAccepted ) {
MWBase::Environment::get().getWindowManager()->
messageBox("#{sNotifyMessage9}");
return;
}
2013-05-11 16:38:27 +00:00
// make the item transfer
mTradeModel->transferItems();
playerItemModel->transferItems();
// transfer the gold
if (mCurrentBalance != 0)
{
addOrRemoveGold(mCurrentBalance, player);
/*
Start of tes3mp change (major)
Don't unilaterally change the merchant's gold pool on our client and instead let the server do it
*/
//mPtr.getClass().getCreatureStats(mPtr).setGoldPool(
// mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance);
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
MWMechanics::CreatureStats& merchantCreatureStats = mPtr.getClass().getCreatureStats(mPtr);
objectList->addObjectMiscellaneous(mPtr, merchantCreatureStats.getGoldPool() - mCurrentBalance, merchantCreatureStats.getLastRestockTime().getHour(),
merchantCreatureStats.getLastRestockTime().getDay());
objectList->sendObjectMiscellaneous();
/*
End of tes3mp change (major)
*/
}
eventTradeDone();
MWBase::Environment::get().getWindowManager()->playSound("Item Gold Up");
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter);
2012-05-17 19:15:48 +00:00
}
void TradeWindow::onAccept(MyGUI::EditBox *sender)
{
onOfferButtonClicked(sender);
2018-09-10 08:55:00 +00:00
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
}
2012-05-17 19:15:48 +00:00
void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender)
{
exit();
2017-09-23 10:18:39 +00:00
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter);
2012-05-17 19:15:48 +00:00
}
void TradeWindow::onMaxSaleButtonClicked(MyGUI::Widget* _sender)
{
mCurrentBalance = getMerchantGold();
updateLabels();
}
void TradeWindow::addRepeatController(MyGUI::Widget *widget)
{
MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerRepeatClick::getClassTypeName());
MyGUI::ControllerRepeatClick* controller = static_cast<MyGUI::ControllerRepeatClick*>(item);
controller->eventRepeatClick += newDelegate(this, &TradeWindow::onRepeatClick);
MyGUI::ControllerManager::getInstance().addItem(widget, controller);
}
void TradeWindow::onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
addRepeatController(_sender);
onIncreaseButtonTriggered();
}
void TradeWindow::onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
addRepeatController(_sender);
onDecreaseButtonTriggered();
}
void TradeWindow::onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller)
{
if (widget == mIncreaseButton)
onIncreaseButtonTriggered();
else if (widget == mDecreaseButton)
onDecreaseButtonTriggered();
}
void TradeWindow::onBalanceButtonReleased(MyGUI::Widget *_sender, int _left, int _top, MyGUI::MouseButton _id)
{
MyGUI::ControllerManager::getInstance().removeItem(_sender);
}
2014-09-25 18:28:00 +00:00
void TradeWindow::onBalanceValueChanged(int value)
2014-05-31 11:53:36 +00:00
{
2014-09-25 18:28:00 +00:00
// Entering a "-" sign inverts the buying/selling state
mCurrentBalance = (mCurrentBalance >= 0 ? 1 : -1) * value;
updateLabels();
if (value != std::abs(value))
mTotalBalance->setValue(std::abs(value));
2014-05-31 11:53:36 +00:00
}
void TradeWindow::onIncreaseButtonTriggered()
{
// prevent overflows, and prevent entering INT_MIN since abs(INT_MIN) is undefined
2018-09-20 12:02:26 +00:00
if (mCurrentBalance == std::numeric_limits<int>::max() || mCurrentBalance == std::numeric_limits<int>::min()+1)
return;
if (mCurrentBalance < 0) mCurrentBalance -= 1;
else mCurrentBalance += 1;
updateLabels();
}
void TradeWindow::onDecreaseButtonTriggered()
{
if (mCurrentBalance < 0) mCurrentBalance += 1;
else mCurrentBalance -= 1;
updateLabels();
}
void TradeWindow::updateLabels()
{
2015-08-21 09:12:39 +00:00
MWWorld::Ptr player = MWMechanics::getPlayer();
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
2015-01-10 01:50:43 +00:00
mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + MyGUI::utility::toString(playerGold));
if (mCurrentBalance < 0)
{
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalCost}");
}
else
{
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalSold}");
}
2014-09-25 18:28:00 +00:00
mTotalBalance->setValue(std::abs(mCurrentBalance));
2015-01-10 01:50:43 +00:00
mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + MyGUI::utility::toString(getMerchantGold()));
2012-05-17 20:24:47 +00:00
}
void TradeWindow::updateOffer()
{
TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
int merchantOffer = 0;
// The offered price must be capped at 75% of the base price to avoid exploits
// connected to buying and selling the same item.
// This value has been determined by researching the limitations of the vanilla formula
// and may not be sufficient if getBarterOffer behavior has been changed.
const std::vector<ItemStack>& playerBorrowed = playerTradeModel->getItemsBorrowedToUs();
for (const ItemStack& itemStack : playerBorrowed)
{
const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount);
const int cap = static_cast<int>(std::max(1.f, 0.75f * basePrice)); // Minimum buying price -- 75% of the base
const int buyingPrice = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, basePrice, true);
merchantOffer -= std::max(cap, buyingPrice);
}
const std::vector<ItemStack>& merchantBorrowed = mTradeModel->getItemsBorrowedToUs();
for (const ItemStack& itemStack : merchantBorrowed)
{
const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount);
2019-05-13 06:50:32 +00:00
const int cap = static_cast<int>(std::max(1.f, 0.75f * basePrice)); // Maximum selling price -- 75% of the base
const int sellingPrice = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, basePrice, false);
merchantOffer += mPtr.getClass().isNpc() ? std::min(cap, sellingPrice) : sellingPrice;
}
int diff = merchantOffer - mCurrentMerchantOffer;
mCurrentMerchantOffer = merchantOffer;
mCurrentBalance += diff;
updateLabels();
}
void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem)
{
updateOffer();
}
void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem)
{
updateOffer();
}
void TradeWindow::onReferenceUnavailable()
{
// remove both Trade and Dialogue (since you always trade with the NPC/creature that you have previously talked to)
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter);
MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode();
}
int TradeWindow::getMerchantGold()
{
int merchantGold = mPtr.getClass().getCreatureStats(mPtr).getGoldPool();
return merchantGold;
}
void TradeWindow::resetReference()
{
ReferenceInterface::resetReference();
2018-10-09 06:21:12 +00:00
mItemView->setModel(nullptr);
mTradeModel = nullptr;
mSortModel = nullptr;
}
void TradeWindow::onClose()
{
2020-10-27 15:08:14 +00:00
// Make sure the window was actually closed and not temporarily hidden.
if (MWBase::Environment::get().getWindowManager()->containsMode(GM_Barter))
return;
resetReference();
}
}