mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-03 23:56:43 +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