1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 21:15:36 +00:00

#6419 Topic shouldn't be greyed out if they can produce another topic reference.

This commit is contained in:
Ivan Beloborodov 2021-12-02 08:04:29 +00:00 committed by psi29a
parent 3de8645be9
commit ead0cb5ce0
4 changed files with 62 additions and 19 deletions

View file

@ -92,6 +92,7 @@ Programmers
Haoda Wang (h313) Haoda Wang (h313)
hristoast hristoast
Internecine Internecine
Ivan Beloborodov (myrix)
Jackerty Jackerty
Jacob Essex (Yacoby) Jacob Essex (Yacoby)
Jacob Turnbull (Tankinfrank) Jacob Turnbull (Tankinfrank)

View file

@ -110,6 +110,7 @@
Feature #6251: OpenMW-CS: Set instance movement based on camera zoom Feature #6251: OpenMW-CS: Set instance movement based on camera zoom
Feature #6288: Preserve the "blocked" record flag for referenceable objects. Feature #6288: Preserve the "blocked" record flag for referenceable objects.
Feature #6380: Commas are treated as whitespace in vanilla Feature #6380: Commas are treated as whitespace in vanilla
Feature #6419: Topics shouldn't be greyed out if they can produce another topic reference
Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings Task #6201: Remove the "Note: No relevant classes found. No output generated" warnings
Task #6264: Remove the old classes in animation.cpp Task #6264: Remove the old classes in animation.cpp

View file

@ -76,9 +76,10 @@ namespace MWDialogue
mKnownTopics.insert( Misc::StringUtils::lowerCase(topic) ); mKnownTopics.insert( Misc::StringUtils::lowerCase(topic) );
} }
void DialogueManager::parseText (const std::string& text) std::vector<std::string> DialogueManager::parseTopicIdsFromText (const std::string& text)
{ {
updateActorKnownTopics(); std::vector<std::string> topicIdList;
std::vector<HyperTextParser::Token> hypertext = HyperTextParser::parseHyperText(text); std::vector<HyperTextParser::Token> hypertext = HyperTextParser::parseHyperText(text);
for (std::vector<HyperTextParser::Token>::iterator tok = hypertext.begin(); tok != hypertext.end(); ++tok) for (std::vector<HyperTextParser::Token>::iterator tok = hypertext.begin(); tok != hypertext.end(); ++tok)
@ -95,6 +96,18 @@ namespace MWDialogue
topicId = mTranslationDataStorage.topicStandardForm(topicId); topicId = mTranslationDataStorage.topicStandardForm(topicId);
} }
topicIdList.push_back(topicId);
}
return topicIdList;
}
void DialogueManager::addTopicsFromText (const std::string& text)
{
updateActorKnownTopics();
for (const auto& topicId : parseTopicIdsFromText(text))
{
if (mActorKnownTopics.count( topicId )) if (mActorKnownTopics.count( topicId ))
mKnownTopics.insert( topicId ); mKnownTopics.insert( topicId );
} }
@ -136,7 +149,6 @@ namespace MWDialogue
mTalkedTo = creatureStats.hasTalkedToPlayer(); mTalkedTo = creatureStats.hasTalkedToPlayer();
mActorKnownTopics.clear(); mActorKnownTopics.clear();
mActorKnownTopicsFlag.clear();
//greeting //greeting
const MWWorld::Store<ESM::Dialogue> &dialogs = const MWWorld::Store<ESM::Dialogue> &dialogs =
@ -163,7 +175,7 @@ namespace MWDialogue
executeScript (info->mResultScript, mActor); executeScript (info->mResultScript, mActor);
mLastTopic = it->mId; mLastTopic = it->mId;
parseText (info->mResponse); addTopicsFromText (info->mResponse);
return true; return true;
} }
@ -277,7 +289,10 @@ namespace MWDialogue
const ESM::Dialogue& dialogue = *dialogues.find (topic); const ESM::Dialogue& dialogue = *dialogues.find (topic);
const ESM::DialInfo* info = filter.search(dialogue, true); const ESM::DialInfo* info =
mChoice == -1 && mActorKnownTopics.count(topic) ?
mActorKnownTopics[topic].mInfo : filter.search(dialogue, true);
if (info) if (info)
{ {
std::string title; std::string title;
@ -320,7 +335,7 @@ namespace MWDialogue
executeScript (info->mResultScript, mActor); executeScript (info->mResultScript, mActor);
parseText (info->mResponse); addTopicsFromText (info->mResponse);
} }
} }
@ -339,7 +354,6 @@ namespace MWDialogue
updateGlobals(); updateGlobals();
mActorKnownTopics.clear(); mActorKnownTopics.clear();
mActorKnownTopicsFlag.clear();
const auto& dialogs = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>(); const auto& dialogs = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
@ -354,21 +368,41 @@ namespace MWDialogue
if (answer != nullptr) if (answer != nullptr)
{ {
int flag = 0; int topicFlags = 0;
if(!inJournal(topicId, answer->mId)) if(!inJournal(topicId, answer->mId))
{ {
// Does this dialogue contains some actor-specific answer? // Does this dialogue contains some actor-specific answer?
if (Misc::StringUtils::ciEqual(answer->mActor, mActor.getCellRef().getRefId())) if (Misc::StringUtils::ciEqual(answer->mActor, mActor.getCellRef().getRefId()))
flag |= MWBase::DialogueManager::TopicType::Specific; topicFlags |= MWBase::DialogueManager::TopicType::Specific;
} }
else else
flag |= MWBase::DialogueManager::TopicType::Exhausted; topicFlags |= MWBase::DialogueManager::TopicType::Exhausted;
mActorKnownTopics.insert (dialog.mId); mActorKnownTopics.insert (std::make_pair(dialog.mId, ActorKnownTopicInfo {topicFlags, answer}));
mActorKnownTopicsFlag[dialog.mId] = flag;
} }
} }
} }
// If response to a topic leads to a new topic, the original topic is not exhausted.
for (auto& [dialogId, topicInfo] : mActorKnownTopics)
{
// If the topic is not marked as exhausted, we don't need to do anything about it.
// If the topic will not be shown to the player, the flag actually does not matter.
if (!(topicInfo.mFlags & MWBase::DialogueManager::TopicType::Exhausted) ||
!mKnownTopics.count(dialogId))
continue;
for (const auto& topicId : parseTopicIdsFromText(topicInfo.mInfo->mResponse))
{
if (mActorKnownTopics.count( topicId ) && !mKnownTopics.count( topicId ))
{
topicInfo.mFlags &= ~MWBase::DialogueManager::TopicType::Exhausted;
break;
}
}
}
} }
std::list<std::string> DialogueManager::getAvailableTopics() std::list<std::string> DialogueManager::getAvailableTopics()
@ -377,7 +411,7 @@ namespace MWDialogue
std::list<std::string> keywordList; std::list<std::string> keywordList;
for (const std::string& topic : mActorKnownTopics) for (const auto& [topic, topicInfo] : mActorKnownTopics)
{ {
//does the player know the topic? //does the player know the topic?
if (mKnownTopics.count(topic)) if (mKnownTopics.count(topic))
@ -391,7 +425,7 @@ namespace MWDialogue
int DialogueManager::getTopicFlag(const std::string& topicId) int DialogueManager::getTopicFlag(const std::string& topicId)
{ {
return mActorKnownTopicsFlag[topicId]; return mActorKnownTopics[topicId].mFlags;
} }
void DialogueManager::keywordSelected (const std::string& keyword, ResponseCallback* callback) void DialogueManager::keywordSelected (const std::string& keyword, ResponseCallback* callback)
@ -444,7 +478,7 @@ namespace MWDialogue
if (const ESM::DialInfo *info = filter.search (*dialogue, true)) if (const ESM::DialInfo *info = filter.search (*dialogue, true))
{ {
std::string text = info->mResponse; std::string text = info->mResponse;
parseText (text); addTopicsFromText (text);
mChoice = -1; mChoice = -1;
mIsInChoice = false; mIsInChoice = false;
@ -579,7 +613,7 @@ namespace MWDialogue
{ {
const ESM::DialInfo* info = infos[0]; const ESM::DialInfo* info = infos[0];
parseText (info->mResponse); addTopicsFromText (info->mResponse);
const MWWorld::Store<ESM::GameSetting>& gmsts = const MWWorld::Store<ESM::GameSetting>& gmsts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();

View file

@ -10,6 +10,7 @@
#include <components/compiler/streamerrorhandler.hpp> #include <components/compiler/streamerrorhandler.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/esm/loadinfo.hpp>
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
@ -24,14 +25,19 @@ namespace MWDialogue
{ {
class DialogueManager : public MWBase::DialogueManager class DialogueManager : public MWBase::DialogueManager
{ {
struct ActorKnownTopicInfo
{
int mFlags;
const ESM::DialInfo* mInfo;
};
std::set<std::string, Misc::StringUtils::CiComp> mKnownTopics;// Those are the topics the player knows. std::set<std::string, Misc::StringUtils::CiComp> mKnownTopics;// Those are the topics the player knows.
// Modified faction reactions. <Faction1, <Faction2, Difference> > // Modified faction reactions. <Faction1, <Faction2, Difference> >
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap; typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
ModFactionReactionMap mChangedFactionReaction; ModFactionReactionMap mChangedFactionReaction;
std::set<std::string, Misc::StringUtils::CiComp> mActorKnownTopics; std::map<std::string, ActorKnownTopicInfo, Misc::StringUtils::CiComp> mActorKnownTopics;
std::unordered_map<std::string, int> mActorKnownTopicsFlag;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
MWScript::CompilerContext mCompilerContext; MWScript::CompilerContext mCompilerContext;
@ -51,7 +57,8 @@ namespace MWDialogue
int mCurrentDisposition; int mCurrentDisposition;
int mPermanentDispositionChange; int mPermanentDispositionChange;
void parseText (const std::string& text); std::vector<std::string> parseTopicIdsFromText (const std::string& text);
void addTopicsFromText (const std::string& text);
void updateActorKnownTopics(); void updateActorKnownTopics();
void updateGlobals(); void updateGlobals();