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:
parent
3de8645be9
commit
ead0cb5ce0
4 changed files with 62 additions and 19 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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>();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue