mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-01 04:45:36 +00:00
Merge remote-tracking branch 'scrawl/persuasion' into next
This commit is contained in:
commit
0ab4068fbd
15 changed files with 438 additions and 16 deletions
|
@ -40,6 +40,10 @@ namespace MWBase
|
||||||
virtual void keywordSelected (const std::string& keyword) = 0;
|
virtual void keywordSelected (const std::string& keyword) = 0;
|
||||||
virtual void goodbyeSelected() = 0;
|
virtual void goodbyeSelected() = 0;
|
||||||
virtual void questionAnswered (const std::string& answer) = 0;
|
virtual void questionAnswered (const std::string& answer) = 0;
|
||||||
|
|
||||||
|
virtual void persuade (int type) = 0;
|
||||||
|
virtual int getTemporaryDispositionChange () const = 0;
|
||||||
|
virtual void applyTemporaryDispositionChange (int delta) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,19 @@ namespace MWBase
|
||||||
|
|
||||||
virtual int countDeaths (const std::string& id) const = 0;
|
virtual int countDeaths (const std::string& id) const = 0;
|
||||||
///< Return the number of deaths for actors with the given ID.
|
///< Return the number of deaths for actors with the given ID.
|
||||||
|
|
||||||
|
enum PersuasionType
|
||||||
|
{
|
||||||
|
PT_Admire,
|
||||||
|
PT_Intimidate,
|
||||||
|
PT_Taunt,
|
||||||
|
PT_Bribe10,
|
||||||
|
PT_Bribe100,
|
||||||
|
PT_Bribe1000
|
||||||
|
};
|
||||||
|
virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
|
||||||
|
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange) = 0;
|
||||||
|
///< Perform a persuasion action on NPC
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,8 @@ namespace MWClass
|
||||||
data->mCreatureStats.setFatigue (ref->mBase->mNpdt52.mFatigue);
|
data->mCreatureStats.setFatigue (ref->mBase->mNpdt52.mFatigue);
|
||||||
|
|
||||||
data->mCreatureStats.setLevel(ref->mBase->mNpdt52.mLevel);
|
data->mCreatureStats.setLevel(ref->mBase->mNpdt52.mLevel);
|
||||||
data->mNpcStats.setDisposition(ref->mBase->mNpdt52.mDisposition);
|
data->mNpcStats.setBaseDisposition(ref->mBase->mNpdt52.mDisposition);
|
||||||
|
data->mNpcStats.setReputation(ref->mBase->mNpdt52.mReputation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../mwbase/scriptmanager.hpp"
|
#include "../mwbase/scriptmanager.hpp"
|
||||||
#include "../mwbase/journal.hpp"
|
#include "../mwbase/journal.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/refdata.hpp"
|
#include "../mwworld/refdata.hpp"
|
||||||
|
@ -584,6 +585,8 @@ namespace MWDialogue
|
||||||
DialogueManager::DialogueManager (const Compiler::Extensions& extensions) :
|
DialogueManager::DialogueManager (const Compiler::Extensions& extensions) :
|
||||||
mCompilerContext (MWScript::CompilerContext::Type_Dialgoue),
|
mCompilerContext (MWScript::CompilerContext::Type_Dialgoue),
|
||||||
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
|
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
|
||||||
|
, mTemporaryDispositionChange(0.f)
|
||||||
|
, mPermanentDispositionChange(0.f)
|
||||||
{
|
{
|
||||||
mChoice = -1;
|
mChoice = -1;
|
||||||
mIsInChoice = false;
|
mIsInChoice = false;
|
||||||
|
@ -868,6 +871,15 @@ namespace MWDialogue
|
||||||
void DialogueManager::goodbyeSelected()
|
void DialogueManager::goodbyeSelected()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||||
|
|
||||||
|
// Apply disposition change to NPC's base disposition
|
||||||
|
if (mActor.getTypeName() == typeid(ESM::NPC).name())
|
||||||
|
{
|
||||||
|
MWMechanics::NpcStats npcStats = MWWorld::Class::get(mActor).getNpcStats(mActor);
|
||||||
|
npcStats.setBaseDisposition(npcStats.getBaseDisposition() + mPermanentDispositionChange);
|
||||||
|
}
|
||||||
|
mPermanentDispositionChange = 0;
|
||||||
|
mTemporaryDispositionChange = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::questionAnswered (const std::string& answer)
|
void DialogueManager::questionAnswered (const std::string& answer)
|
||||||
|
@ -944,4 +956,57 @@ namespace MWDialogue
|
||||||
|
|
||||||
win->goodbye();
|
win->goodbye();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogueManager::persuade(int type)
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
float temp, perm;
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->getPersuasionDispositionChange(
|
||||||
|
mActor, MWBase::MechanicsManager::PersuasionType(type), mTemporaryDispositionChange,
|
||||||
|
success, temp, perm);
|
||||||
|
mTemporaryDispositionChange += temp;
|
||||||
|
mPermanentDispositionChange += perm;
|
||||||
|
|
||||||
|
// change temp disposition so that final disposition is between 0...100
|
||||||
|
int curDisp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor);
|
||||||
|
if (curDisp + mTemporaryDispositionChange < 0)
|
||||||
|
mTemporaryDispositionChange = -curDisp;
|
||||||
|
else if (curDisp + mTemporaryDispositionChange > 100)
|
||||||
|
mTemporaryDispositionChange = 100 - curDisp;
|
||||||
|
|
||||||
|
// practice skill
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
|
|
||||||
|
MWWorld::Class::get(player).skillUsageSucceeded(player, ESM::Skill::Speechcraft, 0);
|
||||||
|
|
||||||
|
|
||||||
|
// add status message to dialogue window
|
||||||
|
std::string text;
|
||||||
|
|
||||||
|
if (type == MWBase::MechanicsManager::PT_Admire)
|
||||||
|
text = "sAdmire";
|
||||||
|
else if (type == MWBase::MechanicsManager::PT_Taunt)
|
||||||
|
text = "sTaunt";
|
||||||
|
else if (type == MWBase::MechanicsManager::PT_Intimidate)
|
||||||
|
text = "sIntimidate";
|
||||||
|
else
|
||||||
|
text = "sBribe";
|
||||||
|
|
||||||
|
text += (success ? "Success" : "Fail");
|
||||||
|
|
||||||
|
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||||
|
win->addTitle(MyGUI::LanguageManager::getInstance().replaceTags("#{"+text+"}"));
|
||||||
|
|
||||||
|
/// \todo text from INFO record, how to get the ID?
|
||||||
|
}
|
||||||
|
|
||||||
|
int DialogueManager::getTemporaryDispositionChange() const
|
||||||
|
{
|
||||||
|
return mTemporaryDispositionChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogueManager::applyTemporaryDispositionChange(int delta)
|
||||||
|
{
|
||||||
|
mTemporaryDispositionChange += delta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ namespace MWDialogue
|
||||||
ESM::DialInfo mLastDialogue;
|
ESM::DialInfo mLastDialogue;
|
||||||
bool mIsInChoice;
|
bool mIsInChoice;
|
||||||
|
|
||||||
|
float mTemporaryDispositionChange;
|
||||||
|
float mPermanentDispositionChange;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DialogueManager (const Compiler::Extensions& extensions);
|
DialogueManager (const Compiler::Extensions& extensions);
|
||||||
|
@ -69,6 +72,9 @@ namespace MWDialogue
|
||||||
virtual void goodbyeSelected();
|
virtual void goodbyeSelected();
|
||||||
virtual void questionAnswered (const std::string& answer);
|
virtual void questionAnswered (const std::string& answer);
|
||||||
|
|
||||||
|
virtual void persuade (int type);
|
||||||
|
virtual int getTemporaryDispositionChange () const;
|
||||||
|
virtual void applyTemporaryDispositionChange (int delta);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
#include "dialogue_history.hpp"
|
#include "dialogue_history.hpp"
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
#include "list.hpp"
|
#include "list.hpp"
|
||||||
|
@ -49,14 +51,87 @@ std::string::size_type find_str_ci(const std::string& str, const std::string& su
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PersuasionDialog::PersuasionDialog(MWBase::WindowManager &parWindowManager)
|
||||||
|
: WindowModal("openmw_persuasion_dialog.layout", parWindowManager)
|
||||||
|
{
|
||||||
|
getWidget(mCancelButton, "CancelButton");
|
||||||
|
getWidget(mAdmireButton, "AdmireButton");
|
||||||
|
getWidget(mIntimidateButton, "IntimidateButton");
|
||||||
|
getWidget(mTauntButton, "TauntButton");
|
||||||
|
getWidget(mBribe10Button, "Bribe10Button");
|
||||||
|
getWidget(mBribe100Button, "Bribe100Button");
|
||||||
|
getWidget(mBribe1000Button, "Bribe1000Button");
|
||||||
|
getWidget(mGoldLabel, "GoldLabel");
|
||||||
|
|
||||||
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onCancel);
|
||||||
|
mAdmireButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
mIntimidateButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
mTauntButton->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
mBribe10Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
mBribe100Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
mBribe1000Button->eventMouseButtonClick += MyGUI::newDelegate(this, &PersuasionDialog::onPersuade);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersuasionDialog::onCancel(MyGUI::Widget *sender)
|
||||||
|
{
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersuasionDialog::onPersuade(MyGUI::Widget *sender)
|
||||||
|
{
|
||||||
|
MWBase::MechanicsManager::PersuasionType type;
|
||||||
|
if (sender == mAdmireButton) type = MWBase::MechanicsManager::PT_Admire;
|
||||||
|
else if (sender == mIntimidateButton) type = MWBase::MechanicsManager::PT_Intimidate;
|
||||||
|
else if (sender == mTauntButton) type = MWBase::MechanicsManager::PT_Taunt;
|
||||||
|
else if (sender == mBribe10Button)
|
||||||
|
{
|
||||||
|
mWindowManager.getTradeWindow()->addOrRemoveGold(-10);
|
||||||
|
type = MWBase::MechanicsManager::PT_Bribe10;
|
||||||
|
}
|
||||||
|
else if (sender == mBribe100Button)
|
||||||
|
{
|
||||||
|
mWindowManager.getTradeWindow()->addOrRemoveGold(-100);
|
||||||
|
type = MWBase::MechanicsManager::PT_Bribe100;
|
||||||
|
}
|
||||||
|
else /*if (sender == mBribe1000Button)*/
|
||||||
|
{
|
||||||
|
mWindowManager.getTradeWindow()->addOrRemoveGold(-1000);
|
||||||
|
type = MWBase::MechanicsManager::PT_Bribe1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getDialogueManager()->persuade(type);
|
||||||
|
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PersuasionDialog::open()
|
||||||
|
{
|
||||||
|
WindowModal::open();
|
||||||
|
center();
|
||||||
|
|
||||||
|
int playerGold = mWindowManager.getInventoryWindow()->getPlayerGold();
|
||||||
|
|
||||||
|
mBribe10Button->setEnabled (playerGold >= 10);
|
||||||
|
mBribe100Button->setEnabled (playerGold >= 100);
|
||||||
|
mBribe1000Button->setEnabled (playerGold >= 1000);
|
||||||
|
|
||||||
|
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + boost::lexical_cast<std::string>(playerGold));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
|
DialogueWindow::DialogueWindow(MWBase::WindowManager& parWindowManager)
|
||||||
: WindowBase("openmw_dialogue_window.layout", parWindowManager)
|
: WindowBase("openmw_dialogue_window.layout", parWindowManager)
|
||||||
|
, mPersuasionDialog(parWindowManager)
|
||||||
, mEnabled(false)
|
, mEnabled(false)
|
||||||
, mServices(0)
|
, mServices(0)
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
center();
|
center();
|
||||||
|
|
||||||
|
mPersuasionDialog.setVisible(false);
|
||||||
|
|
||||||
//History view
|
//History view
|
||||||
getWidget(mHistory, "History");
|
getWidget(mHistory, "History");
|
||||||
mHistory->setOverflowToTheLeft(true);
|
mHistory->setOverflowToTheLeft(true);
|
||||||
|
@ -137,6 +212,10 @@ void DialogueWindow::onSelectTopic(std::string topic)
|
||||||
mWindowManager.pushGuiMode(GM_Barter);
|
mWindowManager.pushGuiMode(GM_Barter);
|
||||||
mWindowManager.getTradeWindow()->startTrade(mPtr);
|
mWindowManager.getTradeWindow()->startTrade(mPtr);
|
||||||
}
|
}
|
||||||
|
if (topic == gmst.find("sPersuasion")->getString())
|
||||||
|
{
|
||||||
|
mPersuasionDialog.setVisible(true);
|
||||||
|
}
|
||||||
else if (topic == gmst.find("sSpells")->getString())
|
else if (topic == gmst.find("sSpells")->getString())
|
||||||
{
|
{
|
||||||
mWindowManager.pushGuiMode(GM_SpellBuying);
|
mWindowManager.pushGuiMode(GM_SpellBuying);
|
||||||
|
@ -187,6 +266,9 @@ void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
|
mTopicsList->addItem(gmst.find("sPersuasion")->getString());
|
||||||
|
|
||||||
if (mServices & Service_Trade)
|
if (mServices & Service_Trade)
|
||||||
mTopicsList->addItem(gmst.find("sBarter")->getString());
|
mTopicsList->addItem(gmst.find("sBarter")->getString());
|
||||||
|
|
||||||
|
@ -325,9 +407,12 @@ void DialogueWindow::onFrame()
|
||||||
{
|
{
|
||||||
if(mEnabled && mPtr.getTypeName() == typeid(ESM::NPC).name())
|
if(mEnabled && mPtr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
{
|
{
|
||||||
|
int disp = std::max(0, std::min(100,
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)
|
||||||
|
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()));
|
||||||
mDispositionBar->setProgressRange(100);
|
mDispositionBar->setProgressRange(100);
|
||||||
mDispositionBar->setProgressPosition(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr));
|
mDispositionBar->setProgressPosition(disp);
|
||||||
mDispositionText->eraseText(0, mDispositionText->getTextLength());
|
mDispositionText->eraseText(0, mDispositionText->getTextLength());
|
||||||
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr))+std::string("/100")+"#B29154");
|
mDispositionText->addText("#B29154"+boost::lexical_cast<std::string>(disp)+std::string("/100")+"#B29154");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,27 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
class DialogueHistory;
|
class DialogueHistory;
|
||||||
|
|
||||||
|
class PersuasionDialog : public WindowModal
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PersuasionDialog(MWBase::WindowManager& parWindowManager);
|
||||||
|
|
||||||
|
virtual void open();
|
||||||
|
|
||||||
|
private:
|
||||||
|
MyGUI::Button* mCancelButton;
|
||||||
|
MyGUI::Button* mAdmireButton;
|
||||||
|
MyGUI::Button* mIntimidateButton;
|
||||||
|
MyGUI::Button* mTauntButton;
|
||||||
|
MyGUI::Button* mBribe10Button;
|
||||||
|
MyGUI::Button* mBribe100Button;
|
||||||
|
MyGUI::Button* mBribe1000Button;
|
||||||
|
MyGUI::TextBox* mGoldLabel;
|
||||||
|
|
||||||
|
void onCancel (MyGUI::Widget* sender);
|
||||||
|
void onPersuade (MyGUI::Widget* sender);
|
||||||
|
};
|
||||||
|
|
||||||
class DialogueWindow: public WindowBase, public ReferenceInterface
|
class DialogueWindow: public WindowBase, public ReferenceInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -86,6 +107,8 @@ namespace MWGui
|
||||||
Widgets::MWList* mTopicsList;
|
Widgets::MWList* mTopicsList;
|
||||||
MyGUI::ProgressPtr mDispositionBar;
|
MyGUI::ProgressPtr mDispositionBar;
|
||||||
MyGUI::EditPtr mDispositionText;
|
MyGUI::EditPtr mDispositionText;
|
||||||
|
|
||||||
|
PersuasionDialog mPersuasionDialog;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/mechanicsmanager.hpp"
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
|
@ -206,7 +207,8 @@ namespace MWGui
|
||||||
if (mCurrentMerchantOffer<0) d = int(100 * (a - b) / a);
|
if (mCurrentMerchantOffer<0) d = int(100 * (a - b) / a);
|
||||||
else d = int(100 * (b - a) / a);
|
else d = int(100 * (b - a) / a);
|
||||||
|
|
||||||
float clampedDisposition = std::max<int>(0,std::min<int>(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)),100));
|
float clampedDisposition = std::max<int>(0,std::min<int>(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)
|
||||||
|
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100));
|
||||||
|
|
||||||
MWMechanics::NpcStats sellerSkill = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
MWMechanics::NpcStats sellerSkill = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
||||||
MWMechanics::CreatureStats sellerStats = MWWorld::Class::get(mPtr).getCreatureStats(mPtr);
|
MWMechanics::CreatureStats sellerStats = MWWorld::Class::get(mPtr).getCreatureStats(mPtr);
|
||||||
|
@ -232,13 +234,15 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->
|
MWBase::Environment::get().getWindowManager()->
|
||||||
messageBox("#{sNotifyMessage9}", std::vector<std::string>());
|
messageBox("#{sNotifyMessage9}", std::vector<std::string>());
|
||||||
/// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition
|
|
||||||
return ;
|
int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt();
|
||||||
|
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterFailDisposition);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
|
||||||
/// \todo adjust npc temporary disposition by iBarterSuccessDisposition or iBarterFailDisposition
|
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition);
|
||||||
|
|
||||||
// success! make the item transfer.
|
// success! make the item transfer.
|
||||||
transferBoughtItems();
|
transferBoughtItems();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/dialoguemanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/player.hpp"
|
#include "../mwworld/player.hpp"
|
||||||
|
@ -389,7 +390,7 @@ namespace MWMechanics
|
||||||
int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr)
|
int MechanicsManager::getDerivedDisposition(const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
MWMechanics::NpcStats npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr);
|
MWMechanics::NpcStats npcSkill = MWWorld::Class::get(ptr).getNpcStats(ptr);
|
||||||
float x = npcSkill.getDisposition();
|
float x = npcSkill.getBaseDisposition();
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::NPC>* npc = ptr.get<ESM::NPC>();
|
MWWorld::LiveCellRef<ESM::NPC>* npc = ptr.get<ESM::NPC>();
|
||||||
MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
|
@ -460,7 +461,10 @@ namespace MWMechanics
|
||||||
MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
MWMechanics::NpcStats playerSkill = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
||||||
MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr);
|
MWMechanics::CreatureStats playerStats = MWWorld::Class::get(playerPtr).getCreatureStats(playerPtr);
|
||||||
|
|
||||||
int clampedDisposition = std::min(getDerivedDisposition(ptr),100);
|
// I suppose the temporary disposition change _has_ to be considered here,
|
||||||
|
// otherwise one would get different prices when exiting and re-entering the dialogue window...
|
||||||
|
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
||||||
|
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100));
|
||||||
float a = std::min(playerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
float a = std::min(playerSkill.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||||
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||||
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||||
|
@ -487,4 +491,152 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
return mActors.countDeaths (id);
|
return mActors.countDeaths (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MechanicsManager::getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
|
||||||
|
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange)
|
||||||
|
{
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
MWMechanics::NpcStats npcSkill = MWWorld::Class::get(npc).getNpcStats(npc);
|
||||||
|
MWMechanics::CreatureStats npcStats = MWWorld::Class::get(npc).getCreatureStats(npc);
|
||||||
|
|
||||||
|
|
||||||
|
float persTerm = playerStats.getAttribute(ESM::Attribute::Personality).getModified()
|
||||||
|
/ gmst.find("fPersonalityMod")->getFloat();
|
||||||
|
|
||||||
|
float luckTerm = playerStats.getAttribute(ESM::Attribute::Luck).getModified()
|
||||||
|
/ gmst.find("fLuckMod")->getFloat();
|
||||||
|
|
||||||
|
float repTerm = playerSkill.getReputation() * gmst.find("fReputationMod")->getFloat();
|
||||||
|
|
||||||
|
float levelTerm = playerStats.getLevel() * gmst.find("fLevelMod")->getFloat();
|
||||||
|
|
||||||
|
float fatigueTerm = playerStats.getFatigueTerm();
|
||||||
|
|
||||||
|
float playerRating1 = (repTerm + luckTerm + persTerm + playerSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm;
|
||||||
|
float playerRating2 = playerRating1 + levelTerm;
|
||||||
|
float playerRating3 = (playerSkill.getSkill(ESM::Skill::Mercantile).getModified() + luckTerm + persTerm) * fatigueTerm;
|
||||||
|
|
||||||
|
float npcRating1 = (repTerm + luckTerm + persTerm + playerSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm;
|
||||||
|
float npcRating2 = (levelTerm + repTerm + luckTerm + persTerm + npcSkill.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm;
|
||||||
|
float npcRating3 = (playerSkill.getSkill(ESM::Skill::Mercantile).getModified() + repTerm + luckTerm + persTerm) * fatigueTerm;
|
||||||
|
|
||||||
|
int currentDisposition = std::min(100, std::max(0, int(getDerivedDisposition(npc) + currentTemporaryDispositionDelta)));
|
||||||
|
|
||||||
|
float d = 1 - 0.02 * abs(currentDisposition - 50);
|
||||||
|
float target1 = d * (playerRating1 - npcRating1 + 50);
|
||||||
|
float target2 = d * (playerRating2 - npcRating2 + 50);
|
||||||
|
|
||||||
|
float bribeMod;
|
||||||
|
if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->getFloat();
|
||||||
|
if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->getFloat();
|
||||||
|
else bribeMod = gmst.find("fBribe1000Mod")->getFloat();
|
||||||
|
|
||||||
|
float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod;
|
||||||
|
|
||||||
|
float iPerMinChance = gmst.find("iPerMinChance")->getInt();
|
||||||
|
float iPerMinChange = gmst.find("iPerMinChange")->getInt();
|
||||||
|
float fPerDieRollMult = gmst.find("fPerDieRollMult")->getFloat();
|
||||||
|
float fPerTempMult = gmst.find("fPerTempMult")->getFloat();
|
||||||
|
|
||||||
|
float x,y;
|
||||||
|
|
||||||
|
float roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
|
||||||
|
|
||||||
|
if (type == PT_Admire)
|
||||||
|
{
|
||||||
|
target1 = std::max(iPerMinChance, target1);
|
||||||
|
success = (roll <= target1);
|
||||||
|
float c = int(fPerDieRollMult * (target1 - roll));
|
||||||
|
x = success ? std::max(iPerMinChange, c) : c;
|
||||||
|
}
|
||||||
|
else if (type == PT_Intimidate)
|
||||||
|
{
|
||||||
|
target2 = std::max(iPerMinChance, target2);
|
||||||
|
|
||||||
|
success = (roll <= target2);
|
||||||
|
|
||||||
|
float r;
|
||||||
|
if (roll != target2)
|
||||||
|
r = int(target2 - roll);
|
||||||
|
else
|
||||||
|
r = 1;
|
||||||
|
|
||||||
|
if (roll <= target2)
|
||||||
|
{
|
||||||
|
float s = int(r * fPerDieRollMult * fPerTempMult);
|
||||||
|
|
||||||
|
npcStats.setFlee ( std::max(0, std::min(100, npcStats.getFlee() + int(std::max(iPerMinChange, s)))));
|
||||||
|
npcStats.setFight ( std::max(0, std::min(100, npcStats.getFight() + int(std::min(-iPerMinChange, -s)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
float c = -std::abs(int(r * fPerDieRollMult));
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
if (std::abs(c) < iPerMinChange)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = -iPerMinChange;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = -int(c * fPerTempMult);
|
||||||
|
y = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = int(c * fPerTempMult);
|
||||||
|
y = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == PT_Taunt)
|
||||||
|
{
|
||||||
|
target1 = std::max(iPerMinChance, target1);
|
||||||
|
success = (roll <= target1);
|
||||||
|
|
||||||
|
float c = std::abs(int(target1 - roll));
|
||||||
|
|
||||||
|
if (roll <= target1)
|
||||||
|
{
|
||||||
|
float s = c * fPerDieRollMult * fPerTempMult;
|
||||||
|
|
||||||
|
npcStats.setFlee ( std::max(0, std::min(100, npcStats.getFlee() + std::min(-int(iPerMinChange), int(-s)))));
|
||||||
|
npcStats.setFight ( std::max(0, std::min(100, npcStats.getFight() + std::max(int(iPerMinChange), int(s)))));
|
||||||
|
}
|
||||||
|
x = int(-c * fPerDieRollMult);
|
||||||
|
|
||||||
|
if (success && std::abs(x) < iPerMinChange)
|
||||||
|
x = -iPerMinChange;
|
||||||
|
}
|
||||||
|
else // Bribe
|
||||||
|
{
|
||||||
|
target3 = std::max(iPerMinChance, target3);
|
||||||
|
success = (roll <= target3);
|
||||||
|
float c = int((target3 - roll) * fPerDieRollMult);
|
||||||
|
|
||||||
|
x = success ? std::max(iPerMinChange, c) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
tempChange = type == PT_Intimidate ? x : int(x * fPerTempMult);
|
||||||
|
|
||||||
|
|
||||||
|
float cappedDispositionChange = tempChange;
|
||||||
|
if (currentDisposition + tempChange > 100.f)
|
||||||
|
cappedDispositionChange = 100 - currentDisposition;
|
||||||
|
if (currentDisposition + tempChange < 0.f)
|
||||||
|
cappedDispositionChange = -currentDisposition;
|
||||||
|
|
||||||
|
permChange = int(cappedDispositionChange / fPerTempMult);
|
||||||
|
if (type == PT_Intimidate)
|
||||||
|
{
|
||||||
|
permChange = success ? -int(cappedDispositionChange/ fPerTempMult) : y;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,9 @@ namespace MWMechanics
|
||||||
virtual int countDeaths (const std::string& id) const;
|
virtual int countDeaths (const std::string& id) const;
|
||||||
///< Return the number of deaths for actors with the given ID.
|
///< Return the number of deaths for actors with the given ID.
|
||||||
|
|
||||||
|
virtual void getPersuasionDispositionChange (const MWWorld::Ptr& npc, PersuasionType type,
|
||||||
|
float currentTemporaryDispositionDelta, bool& success, float& tempChange, float& permChange);
|
||||||
|
///< Perform a persuasion action on NPC
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
MWMechanics::NpcStats::NpcStats()
|
MWMechanics::NpcStats::NpcStats()
|
||||||
: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0)
|
: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0)
|
||||||
, mLevelProgress(0), mDisposition(0)
|
, mLevelProgress(0), mDisposition(0), mReputation(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
mSkillIncreases.resize (ESM::Attribute::Length);
|
mSkillIncreases.resize (ESM::Attribute::Length);
|
||||||
|
@ -37,12 +37,12 @@ void MWMechanics::NpcStats::setDrawState (DrawState_ state)
|
||||||
mDrawState = state;
|
mDrawState = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MWMechanics::NpcStats::getDisposition() const
|
int MWMechanics::NpcStats::getBaseDisposition() const
|
||||||
{
|
{
|
||||||
return mDisposition;
|
return mDisposition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::setDisposition(int disposition)
|
void MWMechanics::NpcStats::setBaseDisposition(int disposition)
|
||||||
{
|
{
|
||||||
mDisposition = disposition;
|
mDisposition = disposition;
|
||||||
}
|
}
|
||||||
|
@ -259,3 +259,13 @@ void MWMechanics::NpcStats::setBounty (int bounty)
|
||||||
{
|
{
|
||||||
mBounty = bounty;
|
mBounty = bounty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MWMechanics::NpcStats::getReputation() const
|
||||||
|
{
|
||||||
|
return mReputation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWMechanics::NpcStats::setReputation(int reputation)
|
||||||
|
{
|
||||||
|
mReputation = reputation;
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace MWMechanics
|
||||||
unsigned int mMovementFlags;
|
unsigned int mMovementFlags;
|
||||||
Stat<float> mSkill[27];
|
Stat<float> mSkill[27];
|
||||||
int mBounty;
|
int mBounty;
|
||||||
|
int mReputation;
|
||||||
|
|
||||||
int mLevelProgress; // 0-10
|
int mLevelProgress; // 0-10
|
||||||
|
|
||||||
|
@ -62,9 +63,13 @@ namespace MWMechanics
|
||||||
|
|
||||||
void setDrawState (DrawState_ state);
|
void setDrawState (DrawState_ state);
|
||||||
|
|
||||||
int getDisposition() const;
|
int getBaseDisposition() const;
|
||||||
|
|
||||||
void setDisposition(int disposition);
|
void setBaseDisposition(int disposition);
|
||||||
|
|
||||||
|
int getReputation() const;
|
||||||
|
|
||||||
|
void setReputation(int reputation);
|
||||||
|
|
||||||
bool getMovementFlag (Flag flag) const;
|
bool getMovementFlag (Flag flag) const;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ namespace MWRender
|
||||||
mFreeLook(true),
|
mFreeLook(true),
|
||||||
mHeight(128.f),
|
mHeight(128.f),
|
||||||
mCameraDistance(300.f),
|
mCameraDistance(300.f),
|
||||||
mDistanceAdjusted(false)
|
mDistanceAdjusted(false),
|
||||||
|
mAnimation(NULL)
|
||||||
{
|
{
|
||||||
mVanity.enabled = false;
|
mVanity.enabled = false;
|
||||||
mVanity.allowed = true;
|
mVanity.allowed = true;
|
||||||
|
|
|
@ -80,6 +80,7 @@ set(MYGUI_FILES
|
||||||
openmw_enchanting_dialog.layout
|
openmw_enchanting_dialog.layout
|
||||||
openmw_trainingwindow.layout
|
openmw_trainingwindow.layout
|
||||||
openmw_travel_window.layout
|
openmw_travel_window.layout
|
||||||
|
openmw_persuasion_dialog.layout
|
||||||
smallbars.png
|
smallbars.png
|
||||||
VeraMono.ttf
|
VeraMono.ttf
|
||||||
markers.png
|
markers.png
|
||||||
|
|
49
files/mygui/openmw_persuasion_dialog.layout
Normal file
49
files/mygui/openmw_persuasion_dialog.layout
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<MyGUI type="Layout">
|
||||||
|
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 220 194" name="_Main">
|
||||||
|
|
||||||
|
<Widget type="TextBox" skin="NormalText" position="0 6 220 24">
|
||||||
|
<Property key="Caption" value="#{sPersuasionMenuTitle}"/>
|
||||||
|
<Property key="TextAlign" value="Center"/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
<Widget type="TextBox" skin="SandText" position="8 156 208 24" name="GoldLabel">
|
||||||
|
<Property key="TextAlign" value="Left VCenter"/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
<Widget type="Widget" skin="MW_Box" position="8 32 196 115">
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 0 0 18" name="AdmireButton">
|
||||||
|
<Property key="Caption" value="#{sAdmire}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 18 0 18" name="IntimidateButton">
|
||||||
|
<Property key="Caption" value="#{sIntimidate}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 36 0 18" name="TauntButton">
|
||||||
|
<Property key="Caption" value="#{sTaunt}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 54 0 18" name="Bribe10Button">
|
||||||
|
<Property key="Caption" value="#{sBribe 10 Gold}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 72 0 18" name="Bribe100Button">
|
||||||
|
<Property key="Caption" value="#{sBribe 100 Gold}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="AutoSizedButton" skin="SandTextButton" position="4 90 0 18" name="Bribe1000Button">
|
||||||
|
<Property key="Caption" value="#{sBribe 1000 Gold}"/>
|
||||||
|
<Property key="TextAlign" value="Left"/>
|
||||||
|
</Widget>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
<Widget type="AutoSizedButton" skin="MW_Button" position="204 156 0 24" name="CancelButton">
|
||||||
|
<Property key="ExpandDirection" value="Left"/>
|
||||||
|
<Property key="Caption" value="#{sCancel}"/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
</Widget>
|
||||||
|
|
||||||
|
</MyGUI>
|
Loading…
Reference in a new issue