mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 16:45:33 +00:00
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
This commit is contained in:
parent
eeb13ad8a3
commit
947f3cf13c
10 changed files with 123 additions and 28 deletions
|
@ -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…
Reference in a new issue