From 5085afa3d775906d1ccae4004cc1fd2a0e7944b9 Mon Sep 17 00:00:00 2001 From: Ben Shealy Date: Sat, 4 Jun 2016 12:28:47 -0400 Subject: [PATCH] Moved mechanics code from MWGui::TradeWindow to MWMechanics::Trading --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwgui/tradewindow.cpp | 84 +++++------------------------ apps/openmw/mwgui/tradewindow.hpp | 3 ++ apps/openmw/mwmechanics/trading.cpp | 84 +++++++++++++++++++++++++++++ apps/openmw/mwmechanics/trading.hpp | 17 ++++++ 5 files changed, 119 insertions(+), 71 deletions(-) create mode 100644 apps/openmw/mwmechanics/trading.cpp create mode 100644 apps/openmw/mwmechanics/trading.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 5e84f6086..fc480d255 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -84,7 +84,7 @@ add_openmw_dir (mwmechanics drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning - character actors objects aistate coordinateconverter + character actors objects aistate coordinateconverter trading ) add_openmw_dir (mwstate diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index ed81677e4..e191c16bb 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -4,8 +4,6 @@ #include #include -#include - #include #include "../mwbase/environment.hpp" @@ -19,8 +17,8 @@ #include "../mwworld/containerstore.hpp" #include "../mwworld/esmstore.hpp" -#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/actorutil.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "inventorywindow.hpp" #include "itemview.hpp" @@ -323,77 +321,23 @@ namespace MWGui } } - // TODO: move to mwmechanics + bool offerAccepted = mTrading.haggle(player, mPtr, mCurrentBalance, mCurrentMerchantOffer); - // Is the player buying? - bool buying = (mCurrentMerchantOffer < 0); + // apply disposition change if merchant is NPC + if ( mPtr.getClass().isNpc() ) { + int dispositionDelta = offerAccepted + ? gmst.find("iBarterSuccessDisposition")->getInt() + : gmst.find("iBarterFailDisposition")->getInt(); - if(mCurrentBalance > mCurrentMerchantOffer) - { - //if npc is a creature: reject (no haggle) - if (mPtr.getTypeName() != typeid(ESM::NPC).name()) - { - MWBase::Environment::get().getWindowManager()-> - messageBox("#{sNotifyMessage9}"); - return; - } - - int a = abs(mCurrentMerchantOffer); - int b = abs(mCurrentBalance); - int d = 0; - if (buying) - d = int(100 * (a - b) / a); - else - d = int(100 * (b - a) / a); - - int clampedDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr); - - const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); - const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player); - - float a1 = static_cast(player.getClass().getSkill(player, ESM::Skill::Mercantile)); - float b1 = 0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(); - float c1 = 0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(); - float d1 = static_cast(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile)); - float e1 = 0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(); - float f1 = 0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(); - - float dispositionTerm = gmst.find("fDispositionMod")->getFloat() * (clampedDisposition - 50); - float pcTerm = (dispositionTerm - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); - float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm(); - float x = gmst.find("fBargainOfferMulti")->getFloat() * d + gmst.find("fBargainOfferBase")->getFloat(); - if (buying) - x += abs(int(pcTerm - npcTerm)); - else - x += abs(int(npcTerm - pcTerm)); - - int roll = Misc::Rng::rollDice(100) + 1; - if(roll > x || (mCurrentMerchantOffer < 0) != (mCurrentBalance < 0)) //trade refused - { - MWBase::Environment::get().getWindowManager()-> - messageBox("#{sNotifyMessage9}"); - - int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt(); - if (mPtr.getClass().isNpc()) - MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterFailDisposition); - return; - } - - //skill use! - float skillGain = 0.f; - int finalPrice = std::abs(mCurrentBalance); - int initialMerchantOffer = std::abs(mCurrentMerchantOffer); - if (!buying && (finalPrice > initialMerchantOffer) && finalPrice > 0) - skillGain = floor(100 * (finalPrice - initialMerchantOffer) / float(finalPrice)); - else if (buying && (finalPrice < initialMerchantOffer) && initialMerchantOffer > 0) - skillGain = floor(100 * (initialMerchantOffer - finalPrice) / float(initialMerchantOffer)); - - player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0, skillGain); + MWBase::Environment::get().getDialogueManager()->applyDispositionChange(dispositionDelta); } - int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt(); - if (mPtr.getClass().isNpc()) - MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterSuccessDisposition); + // display message on haggle failure + if ( !offerAccepted ) { + MWBase::Environment::get().getWindowManager()-> + messageBox("#{sNotifyMessage9}"); + return; + } // make the item transfer mTradeModel->transferItems(); diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index a23196d70..4b03c8d90 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -1,6 +1,8 @@ #ifndef MWGUI_TRADEWINDOW_H #define MWGUI_TRADEWINDOW_H +#include "../mwmechanics/trading.hpp" + #include "referenceinterface.hpp" #include "windowbase.hpp" @@ -40,6 +42,7 @@ namespace MWGui ItemView* mItemView; SortFilterItemModel* mSortModel; TradeItemModel* mTradeModel; + MWMechanics::Trading mTrading; static const float sBalanceChangeInitialPause; // in seconds static const float sBalanceChangeInterval; // in seconds diff --git a/apps/openmw/mwmechanics/trading.cpp b/apps/openmw/mwmechanics/trading.cpp new file mode 100644 index 000000000..c4ef5103e --- /dev/null +++ b/apps/openmw/mwmechanics/trading.cpp @@ -0,0 +1,84 @@ +#include "trading.hpp" + +#include + +#include "../mwbase/environment.hpp" +#include "../mwbase/mechanicsmanager.hpp" +#include "../mwbase/world.hpp" + +#include "../mwmechanics/creaturestats.hpp" + +#include "../mwworld/class.hpp" +#include "../mwworld/esmstore.hpp" + +namespace MWMechanics +{ + Trading::Trading() {} + + bool Trading::haggle(const MWWorld::Ptr& player, const MWWorld::Ptr& merchant, int playerOffer, int merchantOffer) + { + // accept if merchant offer is better than player offer + if ( playerOffer <= merchantOffer ) { + return true; + } + + // reject if npc is a creature + if ( merchant.getTypeName() != typeid(ESM::NPC).name() ) { + return false; + } + + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + // Is the player buying? + bool buying = (merchantOffer < 0); + + int a = std::abs(merchantOffer); + int b = std::abs(playerOffer); + int d = (buying) + ? int(100 * (a - b) / a) + : int(100 * (b - a) / a); + + int clampedDisposition = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(merchant); + + const MWMechanics::CreatureStats &merchantStats = merchant.getClass().getCreatureStats(merchant); + const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player); + + float a1 = static_cast(player.getClass().getSkill(player, ESM::Skill::Mercantile)); + float b1 = 0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(); + float c1 = 0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(); + float d1 = static_cast(merchant.getClass().getSkill(merchant, ESM::Skill::Mercantile)); + float e1 = 0.1f * merchantStats.getAttribute(ESM::Attribute::Luck).getModified(); + float f1 = 0.2f * merchantStats.getAttribute(ESM::Attribute::Personality).getModified(); + + float dispositionTerm = gmst.find("fDispositionMod")->getFloat() * (clampedDisposition - 50); + float pcTerm = (dispositionTerm - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm(); + float npcTerm = (d1 + e1 + f1) * merchantStats.getFatigueTerm(); + float x = gmst.find("fBargainOfferMulti")->getFloat() * d + + gmst.find("fBargainOfferBase")->getFloat() + + std::abs(int(pcTerm - npcTerm)); + + int roll = Misc::Rng::rollDice(100) + 1; + + // reject if roll fails + // (or if player tries to buy things and get money) + if ( roll > x || (merchantOffer < 0 && 0 < playerOffer) ) { + return false; + } + + // apply skill gain on successful barter + float skillGain = 0.f; + int finalPrice = std::abs(playerOffer); + int initialMerchantOffer = std::abs(merchantOffer); + + if ( !buying && (finalPrice > initialMerchantOffer) ) { + skillGain = floor(100.f * (finalPrice - initialMerchantOffer) / finalPrice); + } + else if ( buying && (finalPrice < initialMerchantOffer) ) { + skillGain = floor(100.f * (initialMerchantOffer - finalPrice) / initialMerchantOffer); + } + player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0, skillGain); + + return true; + } +} diff --git a/apps/openmw/mwmechanics/trading.hpp b/apps/openmw/mwmechanics/trading.hpp new file mode 100644 index 000000000..e006370dd --- /dev/null +++ b/apps/openmw/mwmechanics/trading.hpp @@ -0,0 +1,17 @@ +#ifndef OPENMW_MECHANICS_TRADING_H +#define OPENMW_MECHANICS_TRADING_H + +#include "../mwworld/ptr.hpp" + +namespace MWMechanics +{ + class Trading + { + public: + Trading(); + + bool haggle(const MWWorld::Ptr& player, const MWWorld::Ptr& merchant, int playerOffer, int merchantOffer); + }; +} + +#endif