diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index f92e8a0bc1..c9bfa87648 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -103,7 +103,7 @@ add_openmw_dir (mwmechanics drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction summoning - character actors objects aistate trading weaponpriority spellpriority weapontype spellutil + character actors objects aistate weaponpriority spellpriority weapontype spellutil spelleffects ) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index c62d360412..ba752303d2 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -42,6 +43,75 @@ namespace return static_cast(price * count); } + bool 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.getType() != ESM::NPC::sRecordId) + { + return false; + } + + const MWWorld::Store& gmst + = MWBase::Environment::get().getESMStore()->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) / b); + + 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")->mValue.getFloat() * (clampedDisposition - 50); + float pcTerm = (dispositionTerm + a1 + b1 + c1) * playerStats.getFatigueTerm(); + float npcTerm = (d1 + e1 + f1) * merchantStats.getFatigueTerm(); + float x = gmst.find("fBargainOfferMulti")->mValue.getFloat() * d + + gmst.find("fBargainOfferBase")->mValue.getFloat() + int(pcTerm - npcTerm); + + auto& prng = MWBase::Environment::get().getWorld()->getPrng(); + int roll = Misc::Rng::rollDice(100, prng) + 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 = std::floor(100.f * (finalPrice - initialMerchantOffer) / finalPrice); + } + else if (buying && (finalPrice < initialMerchantOffer)) + { + skillGain = std::floor(100.f * (initialMerchantOffer - finalPrice) / initialMerchantOffer); + } + player.getClass().skillUsageSucceeded( + player, ESM::Skill::Mercantile, ESM::Skill::Mercantile_Success, skillGain); + + return true; + } } namespace MWGui @@ -328,7 +398,7 @@ namespace MWGui } } - bool offerAccepted = mTrading.haggle(player, mPtr, mCurrentBalance, mCurrentMerchantOffer); + bool offerAccepted = haggle(player, mPtr, mCurrentBalance, mCurrentMerchantOffer); // apply disposition change if merchant is NPC if (mPtr.getClass().isNpc()) diff --git a/apps/openmw/mwgui/tradewindow.hpp b/apps/openmw/mwgui/tradewindow.hpp index 7d5fd399df..33c39cb269 100644 --- a/apps/openmw/mwgui/tradewindow.hpp +++ b/apps/openmw/mwgui/tradewindow.hpp @@ -1,8 +1,6 @@ #ifndef MWGUI_TRADEWINDOW_H #define MWGUI_TRADEWINDOW_H -#include "../mwmechanics/trading.hpp" - #include "referenceinterface.hpp" #include "windowbase.hpp" @@ -53,7 +51,6 @@ 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 deleted file mode 100644 index b7e361c0b9..0000000000 --- a/apps/openmw/mwmechanics/trading.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "trading.hpp" - -#include - -#include "../mwbase/environment.hpp" -#include "../mwbase/mechanicsmanager.hpp" -#include "../mwbase/world.hpp" - -#include "../mwworld/class.hpp" -#include "../mwworld/esmstore.hpp" - -#include "creaturestats.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.getType() != ESM::NPC::sRecordId) - { - return false; - } - - const MWWorld::Store& gmst - = MWBase::Environment::get().getESMStore()->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) / b); - - 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")->mValue.getFloat() * (clampedDisposition - 50); - float pcTerm = (dispositionTerm + a1 + b1 + c1) * playerStats.getFatigueTerm(); - float npcTerm = (d1 + e1 + f1) * merchantStats.getFatigueTerm(); - float x = gmst.find("fBargainOfferMulti")->mValue.getFloat() * d - + gmst.find("fBargainOfferBase")->mValue.getFloat() + int(pcTerm - npcTerm); - - auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - int roll = Misc::Rng::rollDice(100, prng) + 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 = std::floor(100.f * (finalPrice - initialMerchantOffer) / finalPrice); - } - else if (buying && (finalPrice < initialMerchantOffer)) - { - skillGain = std::floor(100.f * (initialMerchantOffer - finalPrice) / initialMerchantOffer); - } - player.getClass().skillUsageSucceeded( - player, ESM::Skill::Mercantile, ESM::Skill::Mercantile_Success, skillGain); - - return true; - } -} diff --git a/apps/openmw/mwmechanics/trading.hpp b/apps/openmw/mwmechanics/trading.hpp deleted file mode 100644 index e30b82f5e8..0000000000 --- a/apps/openmw/mwmechanics/trading.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef OPENMW_MECHANICS_TRADING_H -#define OPENMW_MECHANICS_TRADING_H - -namespace MWWorld -{ - class Ptr; -} - -namespace MWMechanics -{ - class Trading - { - public: - Trading(); - - bool haggle(const MWWorld::Ptr& player, const MWWorld::Ptr& merchant, int playerOffer, int merchantOffer); - }; -} - -#endif