forked from mirror/openmw-tes3mp
Refactor dialogue GUI to talk to the dialogue manager, not the other way around and not both ways.
- Fix memory leaks in DialogueWindow - Fix Link objects being deleted from their own event handler
This commit is contained in:
parent
476bec41c5
commit
2ce79e07a4
14 changed files with 231 additions and 150 deletions
|
@ -2,6 +2,8 @@
|
|||
#define GAME_MWBASE_DIALOGUEMANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -42,24 +44,29 @@ namespace MWBase
|
|||
|
||||
virtual bool isInChoice() const = 0;
|
||||
|
||||
virtual void startDialogue (const MWWorld::Ptr& actor) = 0;
|
||||
typedef std::pair<std::string, std::string> Response; // title, text
|
||||
virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response) = 0;
|
||||
|
||||
virtual void addTopic (const std::string& topic) = 0;
|
||||
|
||||
virtual void askQuestion (const std::string& question,int choice) = 0;
|
||||
virtual void addChoice (const std::string& text,int choice) = 0;
|
||||
virtual const std::vector<std::pair<std::string, int> >& getChoices() = 0;
|
||||
|
||||
virtual bool isGoodbye() = 0;
|
||||
|
||||
virtual void goodbye() = 0;
|
||||
|
||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) = 0;
|
||||
|
||||
//calbacks for the GUI
|
||||
virtual void keywordSelected (const std::string& keyword) = 0;
|
||||
virtual Response keywordSelected (const std::string& keyword) = 0;
|
||||
virtual void goodbyeSelected() = 0;
|
||||
virtual void questionAnswered (int answer) = 0;
|
||||
virtual Response questionAnswered (int answer) = 0;
|
||||
|
||||
virtual bool checkServiceRefused () = 0;
|
||||
virtual std::list<std::string> getAvailableTopics() = 0;
|
||||
|
||||
virtual void persuade (int type) = 0;
|
||||
virtual bool checkServiceRefused (Response& response) = 0;
|
||||
|
||||
virtual Response persuade (int type) = 0;
|
||||
virtual int getTemporaryDispositionChange () const = 0;
|
||||
|
||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
||||
|
|
|
@ -140,7 +140,6 @@ namespace MWBase
|
|||
virtual bool isAllowed (MWGui::GuiWindow wnd) const = 0;
|
||||
|
||||
/// \todo investigate, if we really need to expose every single lousy UI element to the outside world
|
||||
virtual MWGui::DialogueWindow* getDialogueWindow() = 0;
|
||||
virtual MWGui::InventoryWindow* getInventoryWindow() = 0;
|
||||
virtual MWGui::CountDialog* getCountDialog() = 0;
|
||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog() = 0;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
|
||||
#include <components/esm/loaddial.hpp>
|
||||
#include <components/esm/loadinfo.hpp>
|
||||
|
@ -33,8 +34,6 @@
|
|||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "../mwgui/dialogue.hpp"
|
||||
|
||||
#include "../mwscript/compilercontext.hpp"
|
||||
#include "../mwscript/interpretercontext.hpp"
|
||||
#include "../mwscript/extensions.hpp"
|
||||
|
@ -59,6 +58,7 @@ namespace MWDialogue
|
|||
{
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
mGoodbye = false;
|
||||
mCompilerContext.setExtensions (&extensions);
|
||||
}
|
||||
|
||||
|
@ -99,17 +99,15 @@ namespace MWDialogue
|
|||
if (mActorKnownTopics.count( topicId ))
|
||||
mKnownTopics.insert( topicId );
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
}
|
||||
|
||||
void DialogueManager::startDialogue (const MWWorld::Ptr& actor)
|
||||
bool DialogueManager::startDialogue (const MWWorld::Ptr& actor, Response& response)
|
||||
{
|
||||
updateGlobals();
|
||||
|
||||
// Dialogue with dead actor (e.g. through script) should not be allowed.
|
||||
if (actor.getClass().getCreatureStats(actor).isDead())
|
||||
return;
|
||||
return false;
|
||||
|
||||
mLastTopic = "";
|
||||
mPermanentDispositionChange = 0;
|
||||
|
@ -117,6 +115,8 @@ namespace MWDialogue
|
|||
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
mGoodbye = false;
|
||||
mChoices.clear();
|
||||
|
||||
mActor = actor;
|
||||
|
||||
|
@ -125,8 +125,6 @@ namespace MWDialogue
|
|||
|
||||
mActorKnownTopics.clear();
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
//greeting
|
||||
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||
|
@ -140,10 +138,6 @@ namespace MWDialogue
|
|||
// Search a response (we do not accept a fallback to "Info refusal" here)
|
||||
if (const ESM::DialInfo *info = filter.search (*it, false))
|
||||
{
|
||||
//initialise the GUI
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue);
|
||||
win->startDialogue(actor, actor.getClass().getName (actor));
|
||||
|
||||
creatureStats.talkedToPlayer();
|
||||
|
||||
if (!info->mSound.empty())
|
||||
|
@ -152,29 +146,23 @@ namespace MWDialogue
|
|||
}
|
||||
|
||||
// first topics update so that parseText knows the keywords to highlight
|
||||
updateTopics();
|
||||
updateActorKnownTopics();
|
||||
|
||||
parseText (info->mResponse);
|
||||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), "", false);
|
||||
response = Response ("", Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
executeScript (info->mResultScript, mActor);
|
||||
mLastTopic = it->mId;
|
||||
|
||||
// update topics again to accommodate changes resulting from executeScript
|
||||
updateTopics();
|
||||
updateActorKnownTopics();
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No greetings found. The dialogue window should not be shown.
|
||||
// If this is a companion, we must show the companion window directly (used by BM_bear_be_unique).
|
||||
bool isCompanion = !mActor.getClass().getScript(mActor).empty()
|
||||
&& mActor.getRefData().getLocals().getIntVar(mActor.getClass().getScript(mActor), "companion");
|
||||
if (isCompanion)
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion, mActor);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DialogueManager::compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor)
|
||||
|
@ -252,8 +240,9 @@ namespace MWDialogue
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueManager::executeTopic (const std::string& topic)
|
||||
DialogueManager::Response DialogueManager::executeTopic (const std::string& topic)
|
||||
{
|
||||
DialogueManager::Response response;
|
||||
Filter filter (mActor, mChoice, mTalkedTo);
|
||||
|
||||
const MWWorld::Store<ESM::Dialogue> &dialogues =
|
||||
|
@ -261,8 +250,6 @@ namespace MWDialogue
|
|||
|
||||
const ESM::Dialogue& dialogue = *dialogues.find (topic);
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
const ESM::DialInfo* info = filter.search(dialogue, true);
|
||||
if (info)
|
||||
{
|
||||
|
@ -287,7 +274,7 @@ namespace MWDialogue
|
|||
title = topic;
|
||||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext), title);
|
||||
response = Response(title, Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
|
||||
if (dialogue.mType == ESM::Dialogue::Topic)
|
||||
{
|
||||
|
@ -308,11 +295,7 @@ namespace MWDialogue
|
|||
|
||||
mLastTopic = topic;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no response found, print a fallback text
|
||||
win->addResponse ("…", topic);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
const ESM::Dialogue *DialogueManager::searchDialogue(const std::string& id)
|
||||
|
@ -325,11 +308,10 @@ namespace MWDialogue
|
|||
MWBase::Environment::get().getWorld()->updateDialogueGlobals();
|
||||
}
|
||||
|
||||
void DialogueManager::updateTopics()
|
||||
void DialogueManager::updateActorKnownTopics()
|
||||
{
|
||||
updateGlobals();
|
||||
|
||||
std::list<std::string> keywordList;
|
||||
mActorKnownTopics.clear();
|
||||
|
||||
const MWWorld::Store<ESM::Dialogue> &dialogs =
|
||||
|
@ -345,35 +327,42 @@ namespace MWDialogue
|
|||
{
|
||||
std::string lower = Misc::StringUtils::lowerCase(iter->mId);
|
||||
mActorKnownTopics.insert (lower);
|
||||
|
||||
//does the player know the topic?
|
||||
if (mKnownTopics.count(lower))
|
||||
{
|
||||
keywordList.push_back (iter->mId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
}
|
||||
|
||||
std::list<std::string> DialogueManager::getAvailableTopics()
|
||||
{
|
||||
updateActorKnownTopics();
|
||||
|
||||
std::list<std::string> keywordList;
|
||||
|
||||
for (const std::string& topic : mActorKnownTopics)
|
||||
{
|
||||
//does the player know the topic?
|
||||
if (mKnownTopics.count(Misc::StringUtils::lowerCase(topic)))
|
||||
keywordList.push_back(topic);
|
||||
}
|
||||
|
||||
// sort again, because the previous sort was case-sensitive
|
||||
keywordList.sort(Misc::StringUtils::ciLess);
|
||||
win->setKeywords(keywordList);
|
||||
return keywordList;
|
||||
}
|
||||
|
||||
void DialogueManager::keywordSelected (const std::string& keyword)
|
||||
DialogueManager::Response DialogueManager::keywordSelected (const std::string& keyword)
|
||||
{
|
||||
Response response;
|
||||
if(!mIsInChoice)
|
||||
{
|
||||
const ESM::Dialogue* dialogue = searchDialogue(keyword);
|
||||
if (dialogue && dialogue->mType == ESM::Dialogue::Topic)
|
||||
{
|
||||
executeTopic (keyword);
|
||||
response = executeTopic (keyword);
|
||||
}
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
return response;
|
||||
}
|
||||
|
||||
bool DialogueManager::isInChoice() const
|
||||
|
@ -383,8 +372,6 @@ namespace MWDialogue
|
|||
|
||||
void DialogueManager::goodbyeSelected()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||
|
||||
// Apply disposition change to NPC's base disposition
|
||||
if (mActor.getClass().isNpc())
|
||||
{
|
||||
|
@ -400,9 +387,10 @@ namespace MWDialogue
|
|||
mTemporaryDispositionChange = 0;
|
||||
}
|
||||
|
||||
void DialogueManager::questionAnswered (int answer)
|
||||
DialogueManager::Response DialogueManager::questionAnswered (int answer)
|
||||
{
|
||||
mChoice = answer;
|
||||
DialogueManager::Response response;
|
||||
|
||||
const ESM::Dialogue* dialogue = searchDialogue(mLastTopic);
|
||||
if (dialogue)
|
||||
|
@ -418,10 +406,10 @@ namespace MWDialogue
|
|||
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->clearChoices();
|
||||
mChoices.clear();
|
||||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse (Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||
response = Response("", Interpreter::fixDefinesDialog(text, interpreterContext));
|
||||
|
||||
// Make sure the returned DialInfo is from the Dialogue we supplied. If could also be from the Info refusal group,
|
||||
// in which case it should not be added to the journal.
|
||||
|
@ -441,32 +429,39 @@ namespace MWDialogue
|
|||
{
|
||||
mChoice = -1;
|
||||
mIsInChoice = false;
|
||||
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->clearChoices();
|
||||
mChoices.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
updateActorKnownTopics();
|
||||
return response;
|
||||
}
|
||||
|
||||
void DialogueManager::askQuestion (const std::string& question, int choice)
|
||||
void DialogueManager::addChoice (const std::string& text, int choice)
|
||||
{
|
||||
mIsInChoice = true;
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
win->addChoice(question, choice);
|
||||
mChoices.push_back(std::make_pair(text, choice));
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, int> >& DialogueManager::getChoices()
|
||||
{
|
||||
return mChoices;
|
||||
}
|
||||
|
||||
bool DialogueManager::isGoodbye()
|
||||
{
|
||||
return mGoodbye;
|
||||
}
|
||||
|
||||
void DialogueManager::goodbye()
|
||||
{
|
||||
mIsInChoice = true;
|
||||
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
win->goodbye();
|
||||
mIsInChoice = false;
|
||||
mGoodbye = true;
|
||||
}
|
||||
|
||||
void DialogueManager::persuade(int type)
|
||||
DialogueManager::Response DialogueManager::persuade(int type)
|
||||
{
|
||||
bool success;
|
||||
float temp, perm;
|
||||
|
@ -515,7 +510,7 @@ namespace MWDialogue
|
|||
text = "Bribe";
|
||||
}
|
||||
|
||||
executeTopic (text + (success ? " Success" : " Fail"));
|
||||
return executeTopic (text + (success ? " Success" : " Fail"));
|
||||
}
|
||||
|
||||
int DialogueManager::getTemporaryDispositionChange() const
|
||||
|
@ -528,7 +523,7 @@ namespace MWDialogue
|
|||
mTemporaryDispositionChange += delta;
|
||||
}
|
||||
|
||||
bool DialogueManager::checkServiceRefused()
|
||||
bool DialogueManager::checkServiceRefused(Response& response)
|
||||
{
|
||||
Filter filter (mActor, mChoice, mTalkedTo);
|
||||
|
||||
|
@ -536,7 +531,6 @@ namespace MWDialogue
|
|||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
|
||||
|
||||
const ESM::Dialogue& dialogue = *dialogues.find ("Service Refusal");
|
||||
MWGui::DialogueWindow* win = MWBase::Environment::get().getWindowManager()->getDialogueWindow();
|
||||
|
||||
std::vector<const ESM::DialInfo *> infos = filter.list (dialogue, false, false, true);
|
||||
if (!infos.empty())
|
||||
|
@ -550,8 +544,7 @@ namespace MWDialogue
|
|||
|
||||
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
|
||||
|
||||
win->addResponse (Interpreter::fixDefinesDialog(info->mResponse, interpreterContext),
|
||||
gmsts.find ("sServiceRefusal")->getString());
|
||||
response = Response(gmsts.find ("sServiceRefusal")->getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
|
||||
|
||||
executeScript (info->mResultScript, mActor);
|
||||
return true;
|
||||
|
|
|
@ -41,19 +41,22 @@ namespace MWDialogue
|
|||
int mChoice;
|
||||
std::string mLastTopic; // last topic ID, lowercase
|
||||
bool mIsInChoice;
|
||||
bool mGoodbye;
|
||||
|
||||
std::vector<std::pair<std::string, int> > mChoices;
|
||||
|
||||
float mTemporaryDispositionChange;
|
||||
float mPermanentDispositionChange;
|
||||
|
||||
void parseText (const std::string& text);
|
||||
|
||||
void updateTopics();
|
||||
void updateActorKnownTopics();
|
||||
void updateGlobals();
|
||||
|
||||
bool compile (const std::string& cmd, std::vector<Interpreter::Type_Code>& code, const MWWorld::Ptr& actor);
|
||||
void executeScript (const std::string& script, const MWWorld::Ptr& actor);
|
||||
|
||||
void executeTopic (const std::string& topic);
|
||||
Response executeTopic (const std::string& topic);
|
||||
|
||||
const ESM::Dialogue* searchDialogue(const std::string& id);
|
||||
|
||||
|
@ -65,24 +68,29 @@ namespace MWDialogue
|
|||
|
||||
virtual bool isInChoice() const;
|
||||
|
||||
virtual void startDialogue (const MWWorld::Ptr& actor);
|
||||
virtual bool startDialogue (const MWWorld::Ptr& actor, Response& response);
|
||||
|
||||
std::list<std::string> getAvailableTopics();
|
||||
|
||||
virtual void addTopic (const std::string& topic);
|
||||
|
||||
virtual void askQuestion (const std::string& question,int choice);
|
||||
virtual void addChoice (const std::string& text,int choice);
|
||||
const std::vector<std::pair<std::string, int> >& getChoices();
|
||||
|
||||
virtual bool isGoodbye();
|
||||
|
||||
virtual void goodbye();
|
||||
|
||||
virtual bool checkServiceRefused ();
|
||||
virtual bool checkServiceRefused (Response& response);
|
||||
|
||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic);
|
||||
|
||||
//calbacks for the GUI
|
||||
virtual void keywordSelected (const std::string& keyword);
|
||||
virtual Response keywordSelected (const std::string& keyword);
|
||||
virtual void goodbyeSelected();
|
||||
virtual void questionAnswered (int answer);
|
||||
virtual Response questionAnswered (int answer);
|
||||
|
||||
virtual void persuade (int type);
|
||||
virtual Response persuade (int type);
|
||||
virtual int getTemporaryDispositionChange () const;
|
||||
|
||||
/// @note This change is temporary and gets discarded when dialogue ends.
|
||||
|
|
|
@ -68,7 +68,9 @@ namespace MWGui
|
|||
else /*if (sender == mBribe1000Button)*/
|
||||
type = MWBase::MechanicsManager::PT_Bribe1000;
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->persuade(type);
|
||||
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->persuade(type);
|
||||
|
||||
eventPersuadeMsg(response.first, response.second);
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
|
@ -214,30 +216,26 @@ namespace MWGui
|
|||
|
||||
void Choice::activated()
|
||||
{
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||
MWBase::Environment::get().getDialogueManager()->questionAnswered(mChoiceId);
|
||||
eventChoiceActivated(mChoiceId);
|
||||
}
|
||||
|
||||
void Topic::activated()
|
||||
{
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(mTopicId);
|
||||
eventTopicActivated(mTopicId);
|
||||
}
|
||||
|
||||
void Goodbye::activated()
|
||||
{
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->playSound("Menu Click");
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
eventActivated();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
||||
DialogueWindow::DialogueWindow()
|
||||
: WindowBase("openmw_dialogue_window.layout")
|
||||
, mEnabled(false)
|
||||
, mGoodbye(false)
|
||||
, mPersuasionDialog()
|
||||
{
|
||||
|
@ -245,13 +243,14 @@ namespace MWGui
|
|||
center();
|
||||
|
||||
mPersuasionDialog.setVisible(false);
|
||||
mPersuasionDialog.eventPersuadeMsg += MyGUI::newDelegate(this, &DialogueWindow::onPersuadeResult);
|
||||
|
||||
//History view
|
||||
getWidget(mHistory, "History");
|
||||
|
||||
//Topics list
|
||||
getWidget(mTopicsList, "TopicsList");
|
||||
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectTopic);
|
||||
mTopicsList->eventItemSelected += MyGUI::newDelegate(this, &DialogueWindow::onSelectListItem);
|
||||
|
||||
getWidget(mGoodbyeButton, "ByeButton");
|
||||
mGoodbyeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &DialogueWindow::onByeClicked);
|
||||
|
@ -269,15 +268,27 @@ namespace MWGui
|
|||
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &DialogueWindow::onWindowResize);
|
||||
}
|
||||
|
||||
DialogueWindow::~DialogueWindow()
|
||||
{
|
||||
mPersuasionDialog.eventPersuadeMsg.clear();
|
||||
|
||||
deleteLater();
|
||||
for (Link* link : mLinks)
|
||||
delete link;
|
||||
for (auto link : mTopicLinks)
|
||||
delete link.second;
|
||||
for (auto history : mHistoryContents)
|
||||
delete history;
|
||||
}
|
||||
|
||||
void DialogueWindow::onTradeComplete()
|
||||
{
|
||||
addResponse(MyGUI::LanguageManager::getInstance().replaceTags("#{sBarterDialog5}"));
|
||||
addResponse("", MyGUI::LanguageManager::getInstance().replaceTags("#{sBarterDialog5}"));
|
||||
}
|
||||
|
||||
bool DialogueWindow::exit()
|
||||
{
|
||||
if ((!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||
&& !mGoodbye)
|
||||
if ((MWBase::Environment::get().getDialogueManager()->isInChoice()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -315,9 +326,9 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
}
|
||||
|
||||
void DialogueWindow::onSelectTopic(const std::string& topic, int id)
|
||||
void DialogueWindow::onSelectListItem(const std::string& topic, int id)
|
||||
{
|
||||
if (!mEnabled || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||
if (mGoodbye || MWBase::Environment::get().getDialogueManager()->isInChoice())
|
||||
return;
|
||||
|
||||
int separatorPos = 0;
|
||||
|
@ -328,17 +339,18 @@ namespace MWGui
|
|||
}
|
||||
|
||||
if (id >= separatorPos)
|
||||
MWBase::Environment::get().getDialogueManager()->keywordSelected(topic);
|
||||
onTopicActivated(topic);
|
||||
else
|
||||
{
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
MWBase::DialogueManager::Response response;
|
||||
if (topic == gmst.find("sPersuasion")->getString())
|
||||
mPersuasionDialog.setVisible(true);
|
||||
else if (topic == gmst.find("sCompanionShare")->getString())
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Companion, mPtr);
|
||||
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused())
|
||||
else if (!MWBase::Environment::get().getDialogueManager()->checkServiceRefused(response))
|
||||
{
|
||||
if (topic == gmst.find("sBarter")->getString())
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Barter, mPtr);
|
||||
|
@ -355,21 +367,30 @@ namespace MWGui
|
|||
else if (topic == gmst.find("sRepair")->getString())
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_MerchantRepair, mPtr);
|
||||
}
|
||||
else
|
||||
addResponse(response.first, response.second);
|
||||
}
|
||||
}
|
||||
|
||||
void DialogueWindow::startDialogue(MWWorld::Ptr actor, std::string npcName)
|
||||
void DialogueWindow::setPtr(const MWWorld::Ptr& actor)
|
||||
{
|
||||
MWBase::DialogueManager::Response response;
|
||||
if (!MWBase::Environment::get().getDialogueManager()->startDialogue(actor, response))
|
||||
{
|
||||
// No greetings found. The dialogue window should not be shown.
|
||||
// If this is a companion, we must show the companion window directly (used by BM_bear_be_unique).
|
||||
if (isCompanion())
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Companion, mPtr);
|
||||
return;
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton);
|
||||
|
||||
mGoodbye = false;
|
||||
mEnabled = true;
|
||||
bool sameActor = (mPtr == actor);
|
||||
mPtr = actor;
|
||||
mTopicsList->setEnabled(true);
|
||||
setTitle(npcName);
|
||||
|
||||
clearChoices();
|
||||
setTitle(mPtr.getClass().getName(mPtr));
|
||||
|
||||
mTopicsList->clear();
|
||||
|
||||
|
@ -381,12 +402,13 @@ namespace MWGui
|
|||
}
|
||||
|
||||
for (std::vector<Link*>::iterator it = mLinks.begin(); it != mLinks.end(); ++it)
|
||||
delete (*it);
|
||||
mDeleteLater.push_back(*it); // Links are not deleted right away to prevent issues with event handlers
|
||||
mLinks.clear();
|
||||
|
||||
updateDisposition();
|
||||
|
||||
restock();
|
||||
|
||||
addResponse(response.first, response.second, false);
|
||||
}
|
||||
|
||||
void DialogueWindow::restock()
|
||||
|
@ -403,11 +425,18 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueWindow::deleteLater()
|
||||
{
|
||||
for (Link* link : mDeleteLater)
|
||||
delete link;
|
||||
mDeleteLater.clear();
|
||||
}
|
||||
|
||||
void DialogueWindow::setKeywords(std::list<std::string> keyWords)
|
||||
{
|
||||
mTopicsList->clear();
|
||||
for (std::map<std::string, Link*>::iterator it = mTopicLinks.begin(); it != mTopicLinks.end(); ++it)
|
||||
delete it->second;
|
||||
mDeleteLater.push_back(it->second);
|
||||
mTopicLinks.clear();
|
||||
mKeywordSearch.clear();
|
||||
|
||||
|
@ -416,9 +445,6 @@ namespace MWGui
|
|||
bool travel = (mPtr.getTypeName() == typeid(ESM::NPC).name() && !mPtr.get<ESM::NPC>()->mBase->getTransport().empty())
|
||||
|| (mPtr.getTypeName() == typeid(ESM::Creature).name() && !mPtr.get<ESM::Creature>()->mBase->getTransport().empty());
|
||||
|
||||
bool isCompanion = !mPtr.getClass().getScript(mPtr).empty()
|
||||
&& mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion");
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
|
@ -446,7 +472,7 @@ namespace MWGui
|
|||
if (services & ESM::NPC::Repair)
|
||||
mTopicsList->addItem(gmst.find("sRepair")->getString());
|
||||
|
||||
if (isCompanion)
|
||||
if (isCompanion())
|
||||
mTopicsList->addItem(gmst.find("sCompanionShare")->getString());
|
||||
|
||||
if (mTopicsList->getItemCount() > 0)
|
||||
|
@ -458,6 +484,7 @@ namespace MWGui
|
|||
mTopicsList->addItem(*it);
|
||||
|
||||
Topic* t = new Topic(*it);
|
||||
t->eventTopicActivated += MyGUI::newDelegate(this, &DialogueWindow::onTopicActivated);
|
||||
mTopicLinks[Misc::StringUtils::lowerCase(*it)] = t;
|
||||
|
||||
mKeywordSearch.seed(Misc::StringUtils::lowerCase(*it), intptr_t(t));
|
||||
|
@ -491,9 +518,11 @@ namespace MWGui
|
|||
typesetter->sectionBreak(9);
|
||||
// choices
|
||||
const TextColours& textColours = MWBase::Environment::get().getWindowManager()->getTextColours();
|
||||
for (std::vector<std::pair<std::string, int> >::iterator it = mChoices.begin(); it != mChoices.end(); ++it)
|
||||
mChoices = MWBase::Environment::get().getDialogueManager()->getChoices();
|
||||
for (std::vector<std::pair<std::string, int> >::const_iterator it = mChoices.begin(); it != mChoices.end(); ++it)
|
||||
{
|
||||
Choice* link = new Choice(it->second);
|
||||
link->eventChoiceActivated += MyGUI::newDelegate(this, &DialogueWindow::onChoiceActivated);
|
||||
mLinks.push_back(link);
|
||||
|
||||
typesetter->lineBreak();
|
||||
|
@ -503,9 +532,11 @@ namespace MWGui
|
|||
typesetter->write(questionStyle, to_utf8_span(it->first.c_str()));
|
||||
}
|
||||
|
||||
mGoodbye = MWBase::Environment::get().getDialogueManager()->isGoodbye();
|
||||
if (mGoodbye)
|
||||
{
|
||||
Goodbye* link = new Goodbye();
|
||||
link->eventActivated += MyGUI::newDelegate(this, &DialogueWindow::onGoodbyeActivated);
|
||||
mLinks.push_back(link);
|
||||
std::string goodbye = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString();
|
||||
BookTypesetter::Style* questionStyle = typesetter->createHotStyle(body, textColours.answer, textColours.answerOver,
|
||||
|
@ -550,15 +581,35 @@ namespace MWGui
|
|||
reinterpret_cast<Link*>(link)->activated();
|
||||
}
|
||||
|
||||
void DialogueWindow::onTopicActivated(const std::string &topicId)
|
||||
{
|
||||
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->keywordSelected(topicId);
|
||||
addResponse(response.first, response.second);
|
||||
}
|
||||
|
||||
void DialogueWindow::onChoiceActivated(int id)
|
||||
{
|
||||
MWBase::DialogueManager::Response response = MWBase::Environment::get().getDialogueManager()->questionAnswered(id);
|
||||
addResponse(response.first, response.second);
|
||||
}
|
||||
|
||||
void DialogueWindow::onGoodbyeActivated()
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Dialogue);
|
||||
resetReference();
|
||||
}
|
||||
|
||||
void DialogueWindow::onScrollbarMoved(MyGUI::ScrollBar *sender, size_t pos)
|
||||
{
|
||||
mHistory->setPosition(0, static_cast<int>(pos) * -1);
|
||||
}
|
||||
|
||||
void DialogueWindow::addResponse(const std::string &text, const std::string &title, bool needMargin)
|
||||
void DialogueWindow::addResponse(const std::string &title, const std::string &text, bool needMargin)
|
||||
{
|
||||
mHistoryContents.push_back(new Response(text, title, needMargin));
|
||||
updateHistory();
|
||||
updateTopics();
|
||||
}
|
||||
|
||||
void DialogueWindow::addMessageBox(const std::string& text)
|
||||
|
@ -567,18 +618,6 @@ namespace MWGui
|
|||
updateHistory();
|
||||
}
|
||||
|
||||
void DialogueWindow::addChoice(const std::string& choice, int id)
|
||||
{
|
||||
mChoices.push_back(std::make_pair(choice, id));
|
||||
updateHistory();
|
||||
}
|
||||
|
||||
void DialogueWindow::clearChoices()
|
||||
{
|
||||
mChoices.clear();
|
||||
updateHistory();
|
||||
}
|
||||
|
||||
void DialogueWindow::updateDisposition()
|
||||
{
|
||||
bool dispositionVisible = false;
|
||||
|
@ -608,13 +647,6 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void DialogueWindow::goodbye()
|
||||
{
|
||||
mGoodbye = true;
|
||||
mEnabled = false;
|
||||
updateHistory();
|
||||
}
|
||||
|
||||
void DialogueWindow::onReferenceUnavailable()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
|
@ -623,6 +655,30 @@ namespace MWGui
|
|||
void DialogueWindow::onFrame(float dt)
|
||||
{
|
||||
checkReferenceAvailable();
|
||||
if (mPtr.isEmpty())
|
||||
return;
|
||||
|
||||
updateDisposition();
|
||||
deleteLater();
|
||||
|
||||
if (mChoices != MWBase::Environment::get().getDialogueManager()->getChoices()
|
||||
|| mGoodbye != MWBase::Environment::get().getDialogueManager()->isGoodbye())
|
||||
updateHistory();
|
||||
}
|
||||
|
||||
void DialogueWindow::updateTopics()
|
||||
{
|
||||
setKeywords(MWBase::Environment::get().getDialogueManager()->getAvailableTopics());
|
||||
}
|
||||
|
||||
bool DialogueWindow::isCompanion()
|
||||
{
|
||||
return !mPtr.getClass().getScript(mPtr).empty()
|
||||
&& mPtr.getRefData().getLocals().getIntVar(mPtr.getClass().getScript(mPtr), "companion");
|
||||
}
|
||||
|
||||
void DialogueWindow::onPersuadeResult(const std::string &title, const std::string &text)
|
||||
{
|
||||
addResponse(title, text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "../mwdialogue/keywordsearch.hpp"
|
||||
|
||||
#include <MyGUI_Delegate.h>
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
class MWList;
|
||||
|
@ -20,14 +22,14 @@ namespace MWGui
|
|||
|
||||
namespace MWGui
|
||||
{
|
||||
class DialogueHistoryViewModel;
|
||||
class BookPage;
|
||||
|
||||
class PersuasionDialog : public WindowModal
|
||||
{
|
||||
public:
|
||||
PersuasionDialog();
|
||||
|
||||
typedef MyGUI::delegates::CMultiDelegate2<const std::string&, const std::string&> EventHandle_Result;
|
||||
EventHandle_Result eventPersuadeMsg;
|
||||
|
||||
virtual void onOpen();
|
||||
|
||||
private:
|
||||
|
@ -53,6 +55,8 @@ namespace MWGui
|
|||
|
||||
struct Topic : Link
|
||||
{
|
||||
typedef MyGUI::delegates::CMultiDelegate1<const std::string&> EventHandle_TopicId;
|
||||
EventHandle_TopicId eventTopicActivated;
|
||||
Topic(const std::string& id) : mTopicId(id) {}
|
||||
std::string mTopicId;
|
||||
virtual void activated ();
|
||||
|
@ -60,6 +64,8 @@ namespace MWGui
|
|||
|
||||
struct Choice : Link
|
||||
{
|
||||
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_ChoiceId;
|
||||
EventHandle_ChoiceId eventChoiceActivated;
|
||||
Choice(int id) : mChoiceId(id) {}
|
||||
int mChoiceId;
|
||||
virtual void activated ();
|
||||
|
@ -67,6 +73,8 @@ namespace MWGui
|
|||
|
||||
struct Goodbye : Link
|
||||
{
|
||||
typedef MyGUI::delegates::CMultiDelegate0 Event_Activated;
|
||||
Event_Activated eventActivated;
|
||||
virtual void activated ();
|
||||
};
|
||||
|
||||
|
@ -98,6 +106,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
DialogueWindow();
|
||||
~DialogueWindow();
|
||||
|
||||
void onTradeComplete();
|
||||
|
||||
|
@ -108,25 +117,29 @@ namespace MWGui
|
|||
|
||||
void notifyLinkClicked (TypesetBook::InteractiveId link);
|
||||
|
||||
void startDialogue(MWWorld::Ptr actor, std::string npcName);
|
||||
void setPtr(const MWWorld::Ptr& actor);
|
||||
|
||||
void setKeywords(std::list<std::string> keyWord);
|
||||
|
||||
void addResponse (const std::string& text, const std::string& title="", bool needMargin = true);
|
||||
void addResponse (const std::string& title, const std::string& text, bool needMargin = true);
|
||||
|
||||
void addMessageBox(const std::string& text);
|
||||
|
||||
void addChoice(const std::string& choice, int id);
|
||||
void clearChoices();
|
||||
|
||||
void goodbye();
|
||||
void onFrame(float dt);
|
||||
void clear() { resetReference(); }
|
||||
|
||||
protected:
|
||||
void onSelectTopic(const std::string& topic, int id);
|
||||
void updateTopics();
|
||||
bool isCompanion();
|
||||
|
||||
void onPersuadeResult(const std::string& title, const std::string& text);
|
||||
void onSelectListItem(const std::string& topic, int id);
|
||||
void onByeClicked(MyGUI::Widget* _sender);
|
||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||
void onWindowResize(MyGUI::Window* _sender);
|
||||
void onTopicActivated(const std::string& topicId);
|
||||
void onChoiceActivated(int id);
|
||||
void onGoodbyeActivated();
|
||||
|
||||
void onScrollbarMoved (MyGUI::ScrollBar* sender, size_t pos);
|
||||
|
||||
|
@ -137,17 +150,19 @@ namespace MWGui
|
|||
private:
|
||||
void updateDisposition();
|
||||
void restock();
|
||||
void deleteLater();
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
bool mGoodbye;
|
||||
|
||||
std::vector<DialogueText*> mHistoryContents;
|
||||
std::vector<std::pair<std::string, int> > mChoices;
|
||||
bool mGoodbye;
|
||||
|
||||
std::vector<Link*> mLinks;
|
||||
std::map<std::string, Link*> mTopicLinks;
|
||||
|
||||
std::vector<Link*> mDeleteLater;
|
||||
|
||||
KeywordSearchT mKeywordSearch;
|
||||
|
||||
BookPage* mHistory;
|
||||
|
|
|
@ -353,6 +353,7 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -323,6 +323,7 @@ namespace MWGui
|
|||
|
||||
onCancelButtonClicked(mCancelButton);
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,6 +197,7 @@ namespace MWGui
|
|||
// go back to game mode
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Training);
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
}
|
||||
|
||||
void TrainingWindow::onFrame(float dt)
|
||||
|
|
|
@ -178,6 +178,7 @@ namespace MWGui
|
|||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Travel);
|
||||
MWBase::Environment::get().getDialogueManager()->goodbyeSelected();
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
|
||||
// Teleports any followers, too.
|
||||
MWWorld::ActionTeleport action(interior ? cellname : "", pos, true);
|
||||
|
|
|
@ -1288,7 +1288,6 @@ namespace MWGui
|
|||
mConsole->executeFile (path);
|
||||
}
|
||||
|
||||
MWGui::DialogueWindow* WindowManager::getDialogueWindow() { return mDialogueWindow; }
|
||||
MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; }
|
||||
MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; }
|
||||
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; }
|
||||
|
|
|
@ -179,7 +179,6 @@ namespace MWGui
|
|||
virtual bool isAllowed(GuiWindow wnd) const;
|
||||
|
||||
/// \todo investigate, if we really need to expose every single lousy UI element to the outside world
|
||||
virtual MWGui::DialogueWindow* getDialogueWindow();
|
||||
virtual MWGui::InventoryWindow* getInventoryWindow();
|
||||
virtual MWGui::CountDialog* getCountDialog();
|
||||
virtual MWGui::ConfirmationDialog* getConfirmationDialog();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../mwbase/dialoguemanager.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
|
@ -116,7 +117,7 @@ namespace MWScript
|
|||
runtime.pop();
|
||||
arg0 = arg0 -1;
|
||||
}
|
||||
dialogue->askQuestion(question,choice);
|
||||
dialogue->addChoice(question,choice);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -133,7 +134,7 @@ namespace MWScript
|
|||
if (!ptr.getRefData().isEnabled())
|
||||
return;
|
||||
|
||||
MWBase::Environment::get().getDialogueManager()->startDialogue (ptr);
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "actiontalk.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
@ -9,6 +9,6 @@ namespace MWWorld
|
|||
|
||||
void ActionTalk::executeImp (const Ptr& actor)
|
||||
{
|
||||
MWBase::Environment::get().getDialogueManager()->startDialogue (getTarget());
|
||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, getTarget());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue