Optionally change color of keywords in the dialogue window based on the

next answer:
- if the answer was already heard, apply "color topic exhaused" setting
- if the answer was never heard, and the current actor is specified in
the dialog, apply "color topic specific"
- otherwise, do nothing special
pull/578/head
fredzio 6 years ago
parent eeb13ad8a3
commit 947f3cf13c

@ -225,6 +225,7 @@
Bug #5350: An attempt to launch magic bolt causes "AL error invalid value" error
Bug #5352: Light source items' duration is decremented while they aren't visible
Feature #1724: Handle AvoidNode
Feature #2159: "Graying out" exhausted dialogue topics
Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls
Feature #3442: Default values for fallbacks from ini file

@ -53,6 +53,8 @@ namespace MWBase
virtual bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback) = 0;
virtual bool inJournal (const std::string& topicId, const std::string& infoId) = 0;
virtual void addTopic (const std::string& topic) = 0;
virtual void addChoice (const std::string& text,int choice) = 0;
@ -68,7 +70,14 @@ namespace MWBase
virtual void goodbyeSelected() = 0;
virtual void questionAnswered (int answer, ResponseCallback* callback) = 0;
enum TopicType
{
Specific = 1,
Exhausted = 2
};
virtual std::list<std::string> getAvailableTopics() = 0;
virtual int getTopicFlag(const std::string&) = 0;
virtual bool checkServiceRefused (ResponseCallback* callback) = 0;

@ -228,6 +228,30 @@ namespace MWDialogue
}
}
bool DialogueManager::inJournal (const std::string& topicId, const std::string& infoId)
{
const MWDialogue::Topic *topicHistory = nullptr;
MWBase::Journal *journal = MWBase::Environment::get().getJournal();
for (auto it = journal->topicBegin(); it != journal->topicEnd(); ++it)
{
if (it->first == topicId)
{
topicHistory = &it->second;
break;
}
}
if (!topicHistory)
return false;
for(const auto& topic : *topicHistory)
{
if (topic.mInfoId == infoId)
return true;
}
return false;
}
void DialogueManager::executeTopic (const std::string& topic, ResponseCallback* callback)
{
Filter filter (mActor, mChoice, mTalkedTo);
@ -300,22 +324,34 @@ namespace MWDialogue
mActorKnownTopics.clear();
const MWWorld::Store<ESM::Dialogue> &dialogs =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
const auto& dialogs = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
Filter filter (mActor, -1, mTalkedTo);
for (MWWorld::Store<ESM::Dialogue>::iterator iter = dialogs.begin(); iter != dialogs.end(); ++iter)
for (const auto& dialog : dialogs)
{
if (iter->mType == ESM::Dialogue::Topic)
if (dialog.mType == ESM::Dialogue::Topic)
{
if (filter.responseAvailable (*iter))
const auto* answer = filter.search(dialog, true);
auto topicId = Misc::StringUtils::lowerCase(dialog.mId);
if (answer != nullptr)
{
mActorKnownTopics.insert (iter->mId);
int flag = 0;
if(!inJournal(topicId, answer->mId))
{
// Does this dialogue contains some actor-specific answer?
if (answer->mActor == mActor.getCellRef().getRefId())
flag |= MWBase::DialogueManager::TopicType::Specific;
}
else
flag |= MWBase::DialogueManager::TopicType::Exhausted;
mActorKnownTopics.insert (dialog.mId);
mActorKnownTopicsFlag[dialog.mId] = flag;
}
}
}
}
std::list<std::string> DialogueManager::getAvailableTopics()
@ -336,6 +372,11 @@ namespace MWDialogue
return keywordList;
}
int DialogueManager::getTopicFlag(const std::string& topicId)
{
return mActorKnownTopicsFlag[topicId];
}
void DialogueManager::keywordSelected (const std::string& keyword, ResponseCallback* callback)
{
if(!mIsInChoice)

@ -5,6 +5,7 @@
#include <map>
#include <set>
#include <unordered_map>
#include <components/compiler/streamerrorhandler.hpp>
#include <components/translation/translation.hpp>
@ -30,6 +31,7 @@ namespace MWDialogue
ModFactionReactionMap mChangedFactionReaction;
std::set<std::string, Misc::StringUtils::CiComp> mActorKnownTopics;
std::unordered_map<std::string, int> mActorKnownTopicsFlag;
Translation::Storage& mTranslationDataStorage;
MWScript::CompilerContext mCompilerContext;
@ -71,6 +73,9 @@ namespace MWDialogue
virtual bool startDialogue (const MWWorld::Ptr& actor, ResponseCallback* callback);
std::list<std::string> getAvailableTopics();
int getTopicFlag(const std::string& topicId) final;
bool inJournal (const std::string& topicId, const std::string& infoId) final;
virtual void addTopic (const std::string& topic);

@ -681,15 +681,3 @@ std::vector<const ESM::DialInfo *> MWDialogue::Filter::list (const ESM::Dialogue
return infos;
}
bool MWDialogue::Filter::responseAvailable (const ESM::Dialogue& dialogue) const
{
for (ESM::Dialogue::InfoContainer::const_iterator iter = dialogue.mInfo.begin();
iter!=dialogue.mInfo.end(); ++iter)
{
if (testActor (*iter) && testPlayer (*iter) && testSelectStructs (*iter))
return true;
}
return false;
}

@ -66,9 +66,6 @@ namespace MWDialogue
const ESM::DialInfo* search (const ESM::Dialogue& dialogue, const bool fallbackToInfoRefusal) const;
///< Get a matching response for the requested dialogue.
/// Redirect to "Info Refusal" topic if a response fulfills all conditions but disposition.
bool responseAvailable (const ESM::Dialogue& dialogue) const;
///< Does a matching response exist? (disposition is ignored for this check)
};
}

@ -339,6 +339,7 @@ namespace MWGui
mTopicsList->adjustSize();
updateHistory();
updateTopicFormat();
mCurrentWindowSize = _sender->getSize();
}
@ -448,7 +449,6 @@ namespace MWGui
setTitle(mPtr.getClass().getName(mPtr));
updateTopics();
updateTopicsPane(); // force update for new services
updateDisposition();
restock();
@ -489,8 +489,6 @@ namespace MWGui
return;
mIsCompanion = isCompanion();
mKeywords = keyWords;
updateTopicsPane();
}
void DialogueWindow::updateTopicsPane()
@ -540,15 +538,16 @@ namespace MWGui
mTopicsList->addSeparator();
for(std::string& keyword : mKeywords)
for(const auto& keyword : mKeywords)
{
std::string topicId = Misc::StringUtils::lowerCase(keyword);
mTopicsList->addItem(keyword);
Topic* t = new Topic(keyword);
t->eventTopicActivated += MyGUI::newDelegate(this, &DialogueWindow::onTopicActivated);
mTopicLinks[Misc::StringUtils::lowerCase(keyword)] = t;
mTopicLinks[topicId] = t;
mKeywordSearch.seed(Misc::StringUtils::lowerCase(keyword), intptr_t(t));
mKeywordSearch.seed(topicId, intptr_t(t));
}
mTopicsList->adjustSize();
@ -734,9 +733,28 @@ namespace MWGui
updateHistory();
}
void DialogueWindow::updateTopicFormat()
{
std::string specialColour = Settings::Manager::getString("color topic specific", "GUI");
std::string oldColour = Settings::Manager::getString("color topic exhausted", "GUI");
for (const std::string& keyword : mKeywords)
{
int flag = MWBase::Environment::get().getDialogueManager()->getTopicFlag(keyword);
MyGUI::Button* button = mTopicsList->getItemWidget(keyword);
if (!specialColour.empty() && flag & MWBase::DialogueManager::TopicType::Specific)
button->getSubWidgetText()->setTextColour(MyGUI::Colour::parse(specialColour));
else if (!oldColour.empty() && flag & MWBase::DialogueManager::TopicType::Exhausted)
button->getSubWidgetText()->setTextColour(MyGUI::Colour::parse(oldColour));
}
}
void DialogueWindow::updateTopics()
{
setKeywords(MWBase::Environment::get().getDialogueManager()->getAvailableTopics());
updateTopicsPane();
updateTopicFormat();
}
bool DialogueWindow::isCompanion()

@ -186,6 +186,8 @@ namespace MWGui
std::unique_ptr<ResponseCallback> mCallback;
std::unique_ptr<ResponseCallback> mGreetingCallback;
void updateTopicFormat();
};
}
#endif

@ -140,3 +140,29 @@ The alpha value is currently ignored.
This setting can only be configured by editing the settings configuration file.
This setting has no effect if the crosshair setting in the HUD Settings Section is false.
This setting has no effect if the show owned setting in the Game Settings Section is false.
color topic specific
--------------------
:Type: RGBA floating point
:Range: 0.0 to 1.0
:Default: empty
This setting overrides the color of keywords in the dialogue topic window.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
The color is overriden if the actor is about to give an answer that is unique to him (that is, dialogue with their object ID in the Actor field) that wasn't seen yet.
color topic exhausted
---------------------
:Type: RGBA floating point
:Range: 0.0 to 1.0
:Default: empty
This setting overrides the color of keywords in the dialogue topic window.
The value is composed of four floating point values representing the red, green, blue and alpha channels.
The alpha value is currently ignored.
The color is overridden if the next actor responses to the topic keyword has already been seen by the player.

@ -190,6 +190,14 @@ color crosshair owned = 1.0 0.15 0.15 1.0
# Controls whether Arrow keys, Movement keys, Tab/Shift-Tab and Spacebar/Enter/Activate may be used to navigate GUI buttons.
keyboard navigation = true
# The color of dialogue topic keywords that gives unique actor responses
# Format R G B A or empty for default
color topic specific =
# The color of dialogue topic keywords that gives already read responses
# Format R G B A or empty for default
color topic exhausted =
[HUD]
# Displays the crosshair or reticle when not in GUI mode.

Loading…
Cancel
Save