mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
Moved mechanics code from MWGui::TradeWindow to MWMechanics::Trading
This commit is contained in:
parent
3645b3357e
commit
5085afa3d7
@ -84,7 +84,7 @@ add_openmw_dir (mwmechanics
|
|||||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
||||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
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
|
add_openmw_dir (mwstate
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
#include <MyGUI_InputManager.h>
|
#include <MyGUI_InputManager.h>
|
||||||
#include <MyGUI_ControllerManager.h>
|
#include <MyGUI_ControllerManager.h>
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
|
||||||
|
|
||||||
#include <components/widgets/numericeditbox.hpp>
|
#include <components/widgets/numericeditbox.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -19,8 +17,8 @@
|
|||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "inventorywindow.hpp"
|
#include "inventorywindow.hpp"
|
||||||
#include "itemview.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?
|
// apply disposition change if merchant is NPC
|
||||||
bool buying = (mCurrentMerchantOffer < 0);
|
if ( mPtr.getClass().isNpc() ) {
|
||||||
|
int dispositionDelta = offerAccepted
|
||||||
|
? gmst.find("iBarterSuccessDisposition")->getInt()
|
||||||
|
: gmst.find("iBarterFailDisposition")->getInt();
|
||||||
|
|
||||||
if(mCurrentBalance > mCurrentMerchantOffer)
|
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(dispositionDelta);
|
||||||
{
|
|
||||||
//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<float>(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<float>(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
|
// display message on haggle failure
|
||||||
if (mPtr.getClass().isNpc())
|
if ( !offerAccepted ) {
|
||||||
MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterSuccessDisposition);
|
MWBase::Environment::get().getWindowManager()->
|
||||||
|
messageBox("#{sNotifyMessage9}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// make the item transfer
|
// make the item transfer
|
||||||
mTradeModel->transferItems();
|
mTradeModel->transferItems();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef MWGUI_TRADEWINDOW_H
|
#ifndef MWGUI_TRADEWINDOW_H
|
||||||
#define MWGUI_TRADEWINDOW_H
|
#define MWGUI_TRADEWINDOW_H
|
||||||
|
|
||||||
|
#include "../mwmechanics/trading.hpp"
|
||||||
|
|
||||||
#include "referenceinterface.hpp"
|
#include "referenceinterface.hpp"
|
||||||
#include "windowbase.hpp"
|
#include "windowbase.hpp"
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ namespace MWGui
|
|||||||
ItemView* mItemView;
|
ItemView* mItemView;
|
||||||
SortFilterItemModel* mSortModel;
|
SortFilterItemModel* mSortModel;
|
||||||
TradeItemModel* mTradeModel;
|
TradeItemModel* mTradeModel;
|
||||||
|
MWMechanics::Trading mTrading;
|
||||||
|
|
||||||
static const float sBalanceChangeInitialPause; // in seconds
|
static const float sBalanceChangeInitialPause; // in seconds
|
||||||
static const float sBalanceChangeInterval; // in seconds
|
static const float sBalanceChangeInterval; // in seconds
|
||||||
|
84
apps/openmw/mwmechanics/trading.cpp
Normal file
84
apps/openmw/mwmechanics/trading.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "trading.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
|
||||||
|
#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<ESM::GameSetting> &gmst =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
// 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<float>(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<float>(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;
|
||||||
|
}
|
||||||
|
}
|
17
apps/openmw/mwmechanics/trading.hpp
Normal file
17
apps/openmw/mwmechanics/trading.hpp
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user