From 50a8eb05d96d975f702a4d3cfced0a0b37929acb Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 18 May 2012 17:27:55 +0200 Subject: [PATCH] transfering items between player and merchant works and shows a red frame for bought/sold items. --- apps/openmw/mwgui/container.cpp | 162 ++++++++++++++++++++++++-- apps/openmw/mwgui/container.hpp | 22 +++- apps/openmw/mwgui/dialogue.cpp | 8 +- apps/openmw/mwgui/inventorywindow.cpp | 10 ++ apps/openmw/mwgui/inventorywindow.hpp | 6 + apps/openmw/mwgui/map_window.cpp | 3 +- apps/openmw/mwgui/stats_window.cpp | 3 +- apps/openmw/mwgui/tradewindow.cpp | 10 +- apps/openmw/mwgui/tradewindow.hpp | 3 + 9 files changed, 201 insertions(+), 26 deletions(-) diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 9ff4b8d4a..e51e22ecd 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -21,6 +21,8 @@ #include "window_manager.hpp" #include "widgets.hpp" #include "countdialog.hpp" +#include "tradewindow.hpp" +#include "inventorywindow.hpp" using namespace MWGui; using namespace Widgets; @@ -88,37 +90,120 @@ ContainerBase::~ContainerBase() void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) { - if (mDragAndDrop) + mSelectedItem = _sender; + + if (mDragAndDrop && !isTrading()) { if(!mDragAndDrop->mIsOnDragAndDrop) { - mSelectedItem = _sender; - MWWorld::Ptr object = (*_sender->getUserData()); int count = object.getRefData().getCount(); if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) { - onSelectedItemImpl(_sender, count); + startDragItem(_sender, count); } else if (MyGUI::InputManager::getInstance().isControlPressed()) { - onSelectedItemImpl(_sender, 1); + startDragItem(_sender, 1); } else { CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); dialog->open(MWWorld::Class::get(object).getName(object), count); dialog->eventOkClicked.clear(); - dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::onSelectedItemImpl); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::startDragItem); } } else onContainerClicked(mContainerWidget); } + else + { + MWWorld::Ptr object = (*_sender->getUserData()); + int count = object.getRefData().getCount(); + + if (std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end()) + { + if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) + { + sellAlreadyBoughtItem(NULL, count); + } + else if (MyGUI::InputManager::getInstance().isControlPressed()) + { + sellAlreadyBoughtItem(NULL, 1); + } + else + { + CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); + dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellAlreadyBoughtItem); + } + } + else + { + if (MyGUI::InputManager::getInstance().isShiftPressed() || count == 1) + { + sellItem(NULL, count); + } + else if (MyGUI::InputManager::getInstance().isControlPressed()) + { + sellItem(NULL, 1); + } + else + { + CountDialog* dialog = MWBase::Environment::get().getWindowManager()->getCountDialog(); + dialog->open(MWWorld::Class::get(object).getName(object), count); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &ContainerBase::sellItem); + } + } + } } -void ContainerBase::onSelectedItemImpl(MyGUI::Widget* _sender, int count) +void ContainerBase::sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count) +{ + MWWorld::Ptr object = *mSelectedItem->getUserData(); + assert( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) != mBoughtItems.end() ); + + if (count == object.getRefData().getCount()) + mBoughtItems.erase( std::find(mBoughtItems.begin(), mBoughtItems.end(), object) ); + + if (isInventory()) + { + MWBase::Environment::get().getWindowManager()->getTradeWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); + } + else + { + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->readdBarteredItem(*mSelectedItem->getUserData(), count); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); + } + + drawItems(); +} + +void ContainerBase::sellItem(MyGUI::Widget* _sender, int count) +{ + MWWorld::Ptr newPtr; + if (isInventory()) + { + newPtr = MWBase::Environment::get().getWindowManager()->getTradeWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getTradeWindow()->drawItems(); + } + else + { + newPtr = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->addBarteredItem(*mSelectedItem->getUserData(), count); + mSoldItems.push_back(newPtr); + MWBase::Environment::get().getWindowManager()->getInventoryWindow()->drawItems(); + } + + drawItems(); +} + +void ContainerBase::startDragItem(MyGUI::Widget* _sender, int count) { mDragAndDrop->mIsOnDragAndDrop = true; mSelectedItem->detachFromWidget(); @@ -281,6 +366,14 @@ void ContainerBase::drawItems() std::vector equippedItems = getEquippedItems(); + // add bartered items (always at the beginning) + std::sort(mBoughtItems.begin(), mBoughtItems.end(), sortItems); + for (std::vector::iterator it=mBoughtItems.begin(); + it != mBoughtItems.end(); ++it) + { + items.push_back( std::make_pair(*it, ItemState_Barter) ); + } + // filter out the equipped items of categories we don't want std::vector unwantedItems = equippedItems; for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) @@ -316,7 +409,8 @@ void ContainerBase::drawItems() for (MWWorld::ContainerStoreIterator iter (containerStore.begin(categories)); iter!=containerStore.end(); ++iter) { if (std::find(equippedItems.begin(), equippedItems.end(), *iter) == equippedItems.end() - && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end()) + && std::find(ignoreItems.begin(), ignoreItems.end(), *iter) == ignoreItems.end() + && std::find(mBoughtItems.begin(), mBoughtItems.end(), *iter) == mBoughtItems.end()) regularItems.push_back(*iter); } @@ -338,7 +432,7 @@ void ContainerBase::drawItems() { displayCount -= mDragAndDrop->mDraggedCount; } - if(displayCount > 0 && !(onlyMagic && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) + if(displayCount > 0 && !(onlyMagic && it->second != ItemState_Barter && MWWorld::Class::get(*iter).getEnchantment(*iter) == "" && iter->getTypeName() != typeid(ESM::Potion).name())) { std::string path = std::string("icons\\"); path+=MWWorld::Class::get(*iter).getInventoryIcon(*iter); @@ -361,10 +455,17 @@ void ContainerBase::drawItems() { backgroundTex += "_equip"; } + else if (it->second == ItemState_Barter) + { + backgroundTex += "_barter"; + } backgroundTex += ".dds"; backgroundWidget->setImageTexture(backgroundTex); - backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); + if (it->second == ItemState_Barter && !isMagic) + backgroundWidget->setProperty("ImageCoord", "2 2 42 42"); + else + backgroundWidget->setProperty("ImageCoord", "0 0 42 42"); backgroundWidget->eventMouseButtonClick += MyGUI::newDelegate(this, &ContainerBase::onSelectedItem); backgroundWidget->eventMouseWheel += MyGUI::newDelegate(this, &ContainerBase::onMouseWheel); @@ -421,6 +522,47 @@ void ContainerBase::Update() } } +MWWorld::Ptr ContainerBase::readdBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + int origCount = item.getRefData().getCount(); + item.getRefData().setCount(count); + MWWorld::ContainerStoreIterator it = containerStore.add(item); + item.getRefData().setCount(origCount - count); + + if (origCount - count == 0) + mSoldItems.erase( std::find(mSoldItems.begin(), mSoldItems.end(), item) ); + + return *it; +} + +MWWorld::Ptr ContainerBase::addBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + int origCount = item.getRefData().getCount(); + item.getRefData().setCount(count); + MWWorld::ContainerStoreIterator it = containerStore.add(item); + item.getRefData().setCount(origCount - count); + + mBoughtItems.push_back(*it); + return *it; +} + +void ContainerBase::removeBarteredItem(MWWorld::Ptr item, int count) +{ + MWWorld::ContainerStore& containerStore = MWWorld::Class::get(mContainer).getContainerStore(mContainer); + + for (MWWorld::ContainerStoreIterator it(containerStore.begin()); it != containerStore.end(); ++it) + { + if (*it == item) + { + item.getRefData().setCount(item.getRefData().getCount() - count); + } + } +} + // ------------------------------------------------------------------------------------------------ ContainerWindow::ContainerWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) diff --git a/apps/openmw/mwgui/container.hpp b/apps/openmw/mwgui/container.hpp index 563b22bc3..43a04ae70 100644 --- a/apps/openmw/mwgui/container.hpp +++ b/apps/openmw/mwgui/container.hpp @@ -62,13 +62,15 @@ namespace MWGui { ItemState_Normal = 0x01, ItemState_Equipped = 0x02, - - // unimplemented ItemState_Barter = 0x03 }; void setWidgets(MyGUI::Widget* containerWidget, MyGUI::ScrollView* itemView); ///< only call once + MWWorld::Ptr addBarteredItem(MWWorld::Ptr item, int count); + MWWorld::Ptr readdBarteredItem(MWWorld::Ptr item, int count); + void removeBarteredItem(MWWorld::Ptr item, int count); + void openContainer(MWWorld::Ptr container); void setFilter(Filter filter); ///< set category filter virtual void Update(); @@ -87,17 +89,31 @@ namespace MWGui Filter mFilter; + std::vector mBoughtItems; + std::vector mSoldItems; + void onSelectedItem(MyGUI::Widget* _sender); - void onSelectedItemImpl(MyGUI::Widget* _sender, int count); void onContainerClicked(MyGUI::Widget* _sender); void onMouseWheel(MyGUI::Widget* _sender, int _rel); + /// start dragging an item (drag & drop) + void startDragItem(MyGUI::Widget* _sender, int count); + + /// sell an item from this container + void sellItem(MyGUI::Widget* _sender, int count); + + /// sell an item from this container, that was previously just bought + void sellAlreadyBoughtItem(MyGUI::Widget* _sender, int count); + std::string getCountString(const int count); + virtual bool isTradeWindow() { return false; } virtual bool isInventory() { return false; } virtual std::vector getEquippedItems() { return std::vector(); } virtual void _unequipItem(MWWorld::Ptr item) { ; } + virtual bool isTrading() { return false; } + virtual bool ignoreEquippedItems() { return false; } virtual std::vector itemsToIgnore() { return std::vector(); } }; diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index e8db4b6d1..9f5e252fd 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -120,9 +120,6 @@ void DialogueWindow::open() history->eraseText(0,history->getTextLength()); updateOptions(); setVisible(true); - - // hide all sub-dialogues of the dialog window (trade window, persuasion, etc) - mWindowManager.getTradeWindow()->setVisible(false); } void DialogueWindow::onByeClicked(MyGUI::Widget* _sender) @@ -137,8 +134,8 @@ void DialogueWindow::onSelectTopic(std::string topic) if (topic == MWBase::Environment::get().getWorld()->getStore().gameSettings.search("sBarter")->str) { /// \todo check if the player is allowed to trade with this actor (e.g. faction rank high enough)? - mWindowManager.getTradeWindow()->startTrade(mActor); mWindowManager.setGuiMode(GM_Barter); + mWindowManager.getTradeWindow()->startTrade(mActor); } else @@ -150,8 +147,7 @@ void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName) mEnabled = true; mActor = actor; topicsList->setEnabled(true); - static_cast(mMainWidget)->setCaption(npcName); - adjustWindowCaption(); + setTitle(npcName); } void DialogueWindow::setKeywords(std::list keyWords) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ebba395ff..856ff1896 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -27,6 +27,7 @@ namespace MWGui InventoryWindow::InventoryWindow(WindowManager& parWindowManager,DragAndDrop* dragAndDrop) : ContainerBase(dragAndDrop) , WindowPinnableBase("openmw_inventory_window_layout.xml", parWindowManager) + , mTrading(false) { static_cast(mMainWidget)->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); @@ -94,6 +95,8 @@ namespace MWGui onWindowResize(static_cast(mMainWidget)); updateEncumbranceBar(); + + mTrading = false; } void InventoryWindow::onWindowResize(MyGUI::Window* _sender) @@ -245,4 +248,11 @@ namespace MWGui } return 0; } + + void InventoryWindow::startTrade() + { + mTrading = true; + mBoughtItems.clear(); + mSoldItems.clear(); + } } diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index e53402bbd..e544b788a 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -13,6 +13,9 @@ namespace MWGui void openInventory(); + /// start trading, disables item drag&drop + void startTrade(); + virtual void Update(); virtual void notifyContentChanged(); @@ -33,6 +36,8 @@ namespace MWGui MyGUI::Button* mFilterMagic; MyGUI::Button* mFilterMisc; + bool mTrading; + void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); void onAvatarClicked(MyGUI::Widget* _sender); @@ -40,6 +45,7 @@ namespace MWGui void updateEncumbranceBar(); + virtual bool isTrading() { return mTrading; } virtual bool isInventory() { return true; } virtual std::vector getEquippedItems(); virtual void _unequipItem(MWWorld::Ptr item); diff --git a/apps/openmw/mwgui/map_window.cpp b/apps/openmw/mwgui/map_window.cpp index d3541f774..9000d2fcb 100644 --- a/apps/openmw/mwgui/map_window.cpp +++ b/apps/openmw/mwgui/map_window.cpp @@ -121,8 +121,7 @@ MapWindow::MapWindow(WindowManager& parWindowManager) : void MapWindow::setCellName(const std::string& cellName) { - static_cast(mMainWidget)->setCaption(cellName); - adjustWindowCaption(); + setTitle(cellName); } void MapWindow::setPlayerPos(const float x, const float y) diff --git a/apps/openmw/mwgui/stats_window.cpp b/apps/openmw/mwgui/stats_window.cpp index 186668222..43099e936 100644 --- a/apps/openmw/mwgui/stats_window.cpp +++ b/apps/openmw/mwgui/stats_window.cpp @@ -128,8 +128,7 @@ void StatsWindow::setBar(const std::string& name, const std::string& tname, int void StatsWindow::setPlayerName(const std::string& playerName) { - static_cast(mMainWidget)->setCaption(playerName); - adjustWindowCaption(); + setTitle(playerName); } void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat& value) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index e5fc47764..9f491242b 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -103,13 +103,17 @@ namespace MWGui void TradeWindow::startTrade(MWWorld::Ptr actor) { - ContainerBase::openContainer(actor); - setTitle(MWWorld::Class::get(actor).getName(actor)); - adjustWindowCaption(); mCurrentBalance = 0; + mWindowManager.getInventoryWindow()->startTrade(); + + mBoughtItems.clear(); + mSoldItems.clear(); + + ContainerBase::openContainer(actor); + updateLabels(); } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 5e762cbe5..5ab2d0d79 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -63,6 +63,9 @@ namespace MWGui virtual bool ignoreEquippedItems() { return true; } virtual std::vector getEquippedItems(); + virtual bool isTrading() { return true; } + virtual bool isTradeWindow() { return true; } + virtual std::vector itemsToIgnore(); void updateLabels();