From 20774f8f8178ad6a4ee9aea47da09ae0f7b075b4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 22 Mar 2013 14:13:10 +0100 Subject: [PATCH] Added merchant repair feature --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 3 + apps/openmw/mwgui/dialogue.cpp | 8 ++ apps/openmw/mwgui/dialogue.hpp | 3 +- apps/openmw/mwgui/merchantrepair.cpp | 132 ++++++++++++++++++ apps/openmw/mwgui/merchantrepair.hpp | 37 +++++ apps/openmw/mwgui/mode.hpp | 2 + apps/openmw/mwgui/spellbuyingwindow.cpp | 11 -- apps/openmw/mwgui/spellbuyingwindow.hpp | 2 - apps/openmw/mwgui/windowmanagerimp.cpp | 13 ++ apps/openmw/mwgui/windowmanagerimp.hpp | 4 + apps/openmw/mwworld/containerstore.cpp | 4 +- files/mygui/CMakeLists.txt | 1 + files/mygui/openmw_merchantrepair.layout | 33 +++++ files/mygui/openmw_spell_buying_window.layout | 10 +- 16 files changed, 244 insertions(+), 21 deletions(-) create mode 100644 apps/openmw/mwgui/merchantrepair.cpp create mode 100644 apps/openmw/mwgui/merchantrepair.hpp create mode 100644 files/mygui/openmw_merchantrepair.layout diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 0edc18afb..11c6360e5 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -31,6 +31,7 @@ add_openmw_dir (mwgui confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog enchantingdialog trainingwindow travelwindow imagebutton exposedwindow cursor spellicons + merchantrepair ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index cd28bb47e..0a6de5e14 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -238,6 +238,7 @@ namespace MWBase virtual void startSpellMaking(MWWorld::Ptr actor) = 0; virtual void startEnchanting(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0; + virtual void startRepair(MWWorld::Ptr actor) = 0; virtual void changePointer (const std::string& name) = 0; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 162819995..b75c514a2 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -367,6 +367,9 @@ namespace MWDialogue if (services & ESM::NPC::Enchanting) windowServices |= MWGui::DialogueWindow::Service_Enchant; + if (services & ESM::NPC::Repair) + windowServices |= MWGui::DialogueWindow::Service_Repair; + MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow(); win->setServices (windowServices); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 0bbf7c7af..9a7e51874 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -280,6 +280,11 @@ void DialogueWindow::onSelectTopic(const std::string& topic, int id) mWindowManager.pushGuiMode(GM_Training); mWindowManager.startTraining (mPtr); } + else if (topic == gmst.find("sRepair")->getString()) + { + mWindowManager.pushGuiMode(GM_MerchantRepair); + mWindowManager.startRepair (mPtr); + } } } } @@ -327,6 +332,9 @@ void DialogueWindow::setKeywords(std::list keyWords) if (mServices & Service_Training) mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString()); + if (mServices & Service_Repair) + mTopicsList->addItem(gmst.find("sRepair")->getString()); + if (anyService || mPtr.getTypeName() == typeid(ESM::NPC).name()) mTopicsList->addSeparator(); diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index a8e0a6d17..187731fc7 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -81,7 +81,8 @@ namespace MWGui Service_CreateSpells = 0x04, Service_Enchant = 0x08, Service_Training = 0x10, - Service_Travel = 0x20 + Service_Travel = 0x20, + Service_Repair = 0x40 }; protected: diff --git a/apps/openmw/mwgui/merchantrepair.cpp b/apps/openmw/mwgui/merchantrepair.cpp new file mode 100644 index 000000000..0a6532605 --- /dev/null +++ b/apps/openmw/mwgui/merchantrepair.cpp @@ -0,0 +1,132 @@ +#include "merchantrepair.hpp" + +#include + +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" + +#include "../mwworld/player.hpp" +#include "../mwworld/containerstore.hpp" +#include "../mwworld/class.hpp" + +#include "list.hpp" +#include "inventorywindow.hpp" +#include "tradewindow.hpp" + +namespace MWGui +{ + +MerchantRepair::MerchantRepair(MWBase::WindowManager &parWindowManager) + : WindowBase("openmw_merchantrepair.layout", parWindowManager) +{ + getWidget(mList, "RepairView"); + getWidget(mOkButton, "OkButton"); + getWidget(mGoldLabel, "PlayerGold"); + + mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onOkButtonClick); +} + +void MerchantRepair::startRepair(const MWWorld::Ptr &actor) +{ + mActor = actor; + + while (mList->getChildCount()) + MyGUI::Gui::getInstance().destroyWidget(mList->getChildAt(0)); + + int currentY = 0; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player); + for (MWWorld::ContainerStoreIterator iter (store.begin()); + iter!=store.end(); ++iter) + { + if (MWWorld::Class::get(*iter).hasItemHealth(*iter)) + { + int maxDurability = MWWorld::Class::get(*iter).getItemMaxHealth(*iter); + int durability = (iter->getCellRef().mCharge == -1) ? maxDurability : iter->getCellRef().mCharge; + if (maxDurability == durability) + continue; + + int basePrice = MWWorld::Class::get(*iter).getValue(*iter); + float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get() + .find("fRepairMult")->getFloat(); + + float p = std::max(1, basePrice); + float r = std::max(1, static_cast(maxDurability / p)); + + int x = ((maxDurability - durability) / r); + x = (fRepairMult * x); + + int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true); + + + std::string name = MWWorld::Class::get(*iter).getName(*iter) + + " - " + boost::lexical_cast(price) + + MWBase::Environment::get().getWorld()->getStore().get() + .find("sgp")->getString();; + + + MyGUI::Button* button = + mList->createWidget( + (price>mWindowManager.getInventoryWindow()->getPlayerGold()) ? "SandTextGreyedOut" : "SandTextButton", + 0, + currentY, + 0, + 18, + MyGUI::Align::Default + ); + + currentY += 18; + + button->setEnabled(price<=mWindowManager.getInventoryWindow()->getPlayerGold()); + button->setUserString("Price", boost::lexical_cast(price)); + button->setUserData(*iter); + button->setCaptionWithReplacing(name); + button->setSize(button->getTextSize().width,18); + button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel); + button->setUserString("ToolTipType", "ItemPtr"); + button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick); + } + } + mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY))); + + mGoldLabel->setCaptionWithReplacing("#{sGold}: " + + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); +} + +void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel) +{ + if (mList->getViewOffset().top + _rel*0.3 > 0) + mList->setViewOffset(MyGUI::IntPoint(0, 0)); + else + mList->setViewOffset(MyGUI::IntPoint(0, mList->getViewOffset().top + _rel*0.3)); +} + +void MerchantRepair::open() +{ + center(); +} + +void MerchantRepair::onRepairButtonClick(MyGUI::Widget *sender) +{ + // repair + MWWorld::Ptr item = *sender->getUserData(); + item.getCellRef().mCharge = MWWorld::Class::get(item).getItemMaxHealth(item); + + MWBase::Environment::get().getSoundManager()->playSound("Repair",1,1); + + int price = boost::lexical_cast(sender->getUserString("Price")); + mWindowManager.getTradeWindow()->addOrRemoveGold(-price); + + startRepair(mActor); +} + +void MerchantRepair::onOkButtonClick(MyGUI::Widget *sender) +{ + mWindowManager.removeGuiMode(GM_MerchantRepair); +} + +} diff --git a/apps/openmw/mwgui/merchantrepair.hpp b/apps/openmw/mwgui/merchantrepair.hpp new file mode 100644 index 000000000..4b7e2b8fb --- /dev/null +++ b/apps/openmw/mwgui/merchantrepair.hpp @@ -0,0 +1,37 @@ +#ifndef OPENMW_MWGUI_MERCHANTREPAIR_H +#define OPENMW_MWGUI_MERCHANTREPAIR_H + +#include "window_base.hpp" +#include "../mwworld/ptr.hpp" + + + +namespace MWGui +{ + +class MerchantRepair : public WindowBase +{ +public: + MerchantRepair(MWBase::WindowManager &parWindowManager); + + virtual void open(); + + void startRepair(const MWWorld::Ptr& actor); + +private: + MyGUI::ScrollView* mList; + MyGUI::Button* mOkButton; + MyGUI::TextBox* mGoldLabel; + + MWWorld::Ptr mActor; + +protected: + void onMouseWheel(MyGUI::Widget* _sender, int _rel); + void onRepairButtonClick(MyGUI::Widget* sender); + void onOkButtonClick(MyGUI::Widget* sender); + +}; + +} + +#endif diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 319537297..4091f47ac 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -16,6 +16,7 @@ namespace MWGui GM_Scroll, // Read scroll GM_Book, // Read book GM_Alchemy, // Make potions + GM_Repair, GM_Dialogue, // NPC interaction GM_Barter, @@ -26,6 +27,7 @@ namespace MWGui GM_SpellCreation, GM_Enchanting, GM_Training, + GM_MerchantRepair, GM_Levelup, diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 40fcf2988..d39ad6a5a 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -32,20 +32,9 @@ namespace MWGui getWidget(mCancelButton, "CancelButton"); getWidget(mPlayerGold, "PlayerGold"); - getWidget(mSelect, "Select"); - getWidget(mSpells, "Spells"); getWidget(mSpellsView, "SpellsView"); mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellBuyingWindow::onCancelButtonClicked); - - mSpells->setCoord(450/2-mSpells->getTextSize().width/2, - mSpells->getTop(), - mSpells->getTextSize().width, - mSpells->getHeight()); - mSelect->setCoord(8, - mSelect->getTop(), - mSelect->getTextSize().width, - mSelect->getHeight()); } void SpellBuyingWindow::addSpell(const std::string& spellId) diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index c4988fff3..f9cda35df 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -28,8 +28,6 @@ namespace MWGui protected: MyGUI::Button* mCancelButton; MyGUI::TextBox* mPlayerGold; - MyGUI::TextBox* mSpells; - MyGUI::TextBox* mSelect; MyGUI::ScrollView* mSpellsView; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b7d6ed1c9..07ea72620 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -55,6 +55,7 @@ #include "exposedwindow.hpp" #include "cursor.hpp" #include "spellicons.hpp" +#include "merchantrepair.hpp" using namespace MWGui; @@ -90,6 +91,7 @@ WindowManager::WindowManager( , mSpellCreationDialog(NULL) , mEnchantingDialog(NULL) , mTrainingWindow(NULL) + , mMerchantRepair(NULL) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() @@ -180,6 +182,7 @@ WindowManager::WindowManager( mSpellCreationDialog = new SpellCreationDialog(*this); mEnchantingDialog = new EnchantingDialog(*this); mTrainingWindow = new TrainingWindow(*this); + mMerchantRepair = new MerchantRepair(*this); mLoadingScreen = new LoadingScreen(mRendering->getScene (), mRendering->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -245,6 +248,7 @@ WindowManager::~WindowManager() delete mTrainingWindow; delete mCountDialog; delete mQuickKeysMenu; + delete mMerchantRepair; delete mCursor; cleanupGarbage(); @@ -303,6 +307,7 @@ void WindowManager::updateVisible() mSpellCreationDialog->setVisible(false); mEnchantingDialog->setVisible(false); mTrainingWindow->setVisible(false); + mMerchantRepair->setVisible(false); mHud->setVisible(mHudEnabled); @@ -428,6 +433,9 @@ void WindowManager::updateVisible() case GM_Training: mTrainingWindow->setVisible(true); break; + case GM_MerchantRepair: + mMerchantRepair->setVisible(true); + break; case GM_InterMessageBox: break; case GM_Journal: @@ -1132,6 +1140,11 @@ void WindowManager::startTraining(MWWorld::Ptr actor) mTrainingWindow->startTraining(actor); } +void WindowManager::startRepair(MWWorld::Ptr actor) +{ + mMerchantRepair->startRepair(actor); +} + const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a7baf5207..2242a8467 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -74,6 +74,7 @@ namespace MWGui class TrainingWindow; class Cursor; class SpellIcons; + class MerchantRepair; class WindowManager : public MWBase::WindowManager { @@ -229,6 +230,7 @@ namespace MWGui virtual void startSpellMaking(MWWorld::Ptr actor); virtual void startEnchanting(MWWorld::Ptr actor); virtual void startTraining(MWWorld::Ptr actor); + virtual void startRepair(MWWorld::Ptr actor); virtual void changePointer (const std::string& name); @@ -266,6 +268,8 @@ namespace MWGui SpellCreationDialog* mSpellCreationDialog; EnchantingDialog* mEnchantingDialog; TrainingWindow* mTrainingWindow; + MerchantRepair* mMerchantRepair; + Translation::Storage& mTranslationDataStorage; Cursor* mCursor; diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 3dce049f4..223514e08 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -62,13 +62,13 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::end() bool MWWorld::ContainerStore::stacks(const Ptr& ptr1, const Ptr& ptr2) { - /// \todo add current weapon/armor health, remaining lockpick/repair uses, current enchantment charge here as soon as they are implemented + /// \todo add current enchantment charge here when it is implemented if ( ptr1.mCellRef->mRefID == ptr2.mCellRef->mRefID && MWWorld::Class::get(ptr1).getScript(ptr1) == "" // item with a script never stacks && MWWorld::Class::get(ptr1).getEnchantment(ptr1) == "" // item with enchantment never stacks (we could revisit this later, but for now it makes selecting items in the spell window much easier) && ptr1.mCellRef->mOwner == ptr2.mCellRef->mOwner && ptr1.mCellRef->mSoul == ptr2.mCellRef->mSoul - && ptr1.mCellRef->mCharge == ptr2.mCellRef->mCharge) + && ptr1.mCellRef->mCharge == -1) // item that is already partly used up never stacks return true; return false; diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index beace5b81..4adebf1df 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -78,6 +78,7 @@ set(MYGUI_FILES openmw_trainingwindow.layout openmw_travel_window.layout openmw_persuasion_dialog.layout + openmw_merchantrepair.layout smallbars.png DejaVuLGCSansMono.ttf markers.png diff --git a/files/mygui/openmw_merchantrepair.layout b/files/mygui/openmw_merchantrepair.layout new file mode 100644 index 000000000..360f5f4f0 --- /dev/null +++ b/files/mygui/openmw_merchantrepair.layout @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_spell_buying_window.layout b/files/mygui/openmw_spell_buying_window.layout index 1e18fda23..c55cd0e22 100644 --- a/files/mygui/openmw_spell_buying_window.layout +++ b/files/mygui/openmw_spell_buying_window.layout @@ -5,13 +5,13 @@ - - + + - - - + + +