From 0a883f4492247dfb7e80ebcf000b9aa8c679a8f2 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 8 Nov 2012 13:38:20 +0100 Subject: [PATCH] The player can now barter with merchants --- apps/openmw/mwgui/tradewindow.cpp | 76 +++++++++++++++++-- apps/openmw/mwgui/tradewindow.hpp | 3 + .../mwmechanics/mechanicsmanagerimp.cpp | 2 + 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index cd66b46f5..91247a886 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -11,6 +11,11 @@ #include "../mwworld/inventorystore.hpp" #include "../mwworld/manualref.hpp" +#include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" + +#include "../mwworld/player.hpp" + #include "inventorywindow.hpp" namespace MWGui @@ -53,6 +58,8 @@ namespace MWGui mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onCancelButtonClicked); mOfferButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onOfferButtonClicked); + mIncreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onIncreaseButtonClicked); + mDecreaseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonClicked); setCoord(400, 0, 400, 300); @@ -64,6 +71,7 @@ namespace MWGui setTitle(MWWorld::Class::get(actor).getName(actor)); mCurrentBalance = 0; + mCurrentMerchantOffer = 0; mWindowManager.getInventoryWindow()->startTrade(); @@ -175,6 +183,49 @@ namespace MWGui return; } + if(mCurrentBalance > mCurrentMerchantOffer) + { + /// \todo : if creature.... + //if npc is a creature: reject (no haggle) + + int a = abs(mCurrentMerchantOffer); + int b = abs(mCurrentBalance); + int d = 0; + if (mCurrentMerchantOffer<0) d = int(100 * (a - b) / a); + else d = int(100 * (b - a) / a); + + float clampedDisposition = std::max(0,std::min(int(MWBase::Environment::get().getMechanicsManager()->disposition(mPtr)),100)); + + MWMechanics::NpcStats sellerSkill = MWWorld::Class::get(mPtr).getNpcStats(mPtr); + MWMechanics::CreatureStats sellerStats = MWWorld::Class::get(mPtr).getCreatureStats(mPtr); + MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr); + MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr); + + float a1 = std::min(playerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float b1 = std::min(0.1 * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10); + float c1 = std::min(0.2 * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10); + float d1 = std::min(sellerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float e1 = std::min(0.1 * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10); + float f1 = std::min(0.2 * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10); + + float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); + float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); + float x = MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fBargainOfferMulti")->getFloat() * d + MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fBargainOfferBase")->getFloat(); + if (mCurrentMerchantOffer<0) x += abs(int(pcTerm - npcTerm)); + else x += abs(int(npcTerm - pcTerm)); + + int roll = std::rand()%100 + 1; + if(roll > x) //trade refused + { + /// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition + return ; + } + } + + +/// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition + // success! make the item transfer. transferBoughtItems(); mWindowManager.getInventoryWindow()->transferBoughtItems(); @@ -199,6 +250,20 @@ namespace MWGui mWindowManager.removeGuiMode(GM_Barter); } + void TradeWindow::onIncreaseButtonClicked(MyGUI::Widget* _sender) + { + if(mCurrentBalance<=-1) mCurrentBalance -= 1; + if(mCurrentBalance>=1) mCurrentBalance += 1; + updateLabels(); + } + + void TradeWindow::onDecreaseButtonClicked(MyGUI::Widget* _sender) + { + if(mCurrentBalance<-1) mCurrentBalance += 1; + if(mCurrentBalance>1) mCurrentBalance -= 1; + updateLabels(); + } + void TradeWindow::updateLabels() { mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast(mWindowManager.getInventoryWindow()->getPlayerGold())); @@ -317,20 +382,17 @@ namespace MWGui void TradeWindow::sellToNpc(MWWorld::Ptr item, int count) { - /// \todo price adjustment depending on merchantile skill - - mCurrentBalance -= MWWorld::Class::get(item).getValue(item) * count - + MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); + mCurrentBalance -= MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); + mCurrentMerchantOffer -= MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); updateLabels(); } void TradeWindow::buyFromNpc(MWWorld::Ptr item, int count) { - mCurrentBalance += MWWorld::Class::get(item).getValue(item) * count - - MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,true); - + mCurrentBalance += MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); + mCurrentMerchantOffer += MWBase::Environment::get().getMechanicsManager()->barterOffer(mPtr, MWWorld::Class::get(item).getValue(item) * count,false); updateLabels(); } diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 4ec55045c..db386d8b6 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -55,11 +55,14 @@ namespace MWGui MyGUI::TextBox* mMerchantGold; int mCurrentBalance; + int mCurrentMerchantOffer; void onWindowResize(MyGUI::Window* _sender); void onFilterChanged(MyGUI::Widget* _sender); void onOfferButtonClicked(MyGUI::Widget* _sender); void onCancelButtonClicked(MyGUI::Widget* _sender); + void onIncreaseButtonClicked(MyGUI::Widget* _sender); + void onDecreaseButtonClicked(MyGUI::Widget* _sender); // don't show items that the NPC has equipped in his trade-window. virtual bool ignoreEquippedItems() { return true; } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index b65b7573b..240937b7c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -384,6 +384,8 @@ namespace MWMechanics x += (MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispFactionRankMult")->getFloat() * rank + MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispFactionRankBase")->getFloat()) * MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispFactionMod")->getFloat() * reaction; + + /// \todo implement bounty and disease //x -= MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispCrimeMod") * pcBounty; //if (pc has a disease) x += MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispDiseaseMod"); if (playerSkill.getDrawState() == MWMechanics::DrawState_::DrawState_Weapon) x += MWBase::Environment::get().getWorld()->getStore().gameSettings.find("fDispWeaponDrawn")->getFloat();