mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +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)
 | 
			
		||||
    hristoast
 | 
			
		||||
    Internecine
 | 
			
		||||
    Ivan Beloborodov (myrix)
 | 
			
		||||
    Jackerty
 | 
			
		||||
    Jacob Essex (Yacoby)
 | 
			
		||||
    Jacob Turnbull (Tankinfrank)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,6 +110,7 @@
 | 
			
		|||
    Feature #6251: OpenMW-CS: Set instance movement based on camera zoom
 | 
			
		||||
    Feature #6288: Preserve the "blocked" record flag for referenceable objects.
 | 
			
		||||
    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 #6264: Remove the old classes in animation.cpp
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,9 +76,10 @@ namespace MWDialogue
 | 
			
		|||
        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);
 | 
			
		||||
 | 
			
		||||
        for (std::vector<HyperTextParser::Token>::iterator tok = hypertext.begin(); tok != hypertext.end(); ++tok)
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +96,18 @@ namespace MWDialogue
 | 
			
		|||
                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 ))
 | 
			
		||||
                mKnownTopics.insert( topicId );
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +149,6 @@ namespace MWDialogue
 | 
			
		|||
        mTalkedTo = creatureStats.hasTalkedToPlayer();
 | 
			
		||||
 | 
			
		||||
        mActorKnownTopics.clear();
 | 
			
		||||
        mActorKnownTopicsFlag.clear();
 | 
			
		||||
 | 
			
		||||
        //greeting
 | 
			
		||||
        const MWWorld::Store<ESM::Dialogue> &dialogs =
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +175,7 @@ namespace MWDialogue
 | 
			
		|||
                    executeScript (info->mResultScript, mActor);
 | 
			
		||||
                    mLastTopic = it->mId;
 | 
			
		||||
 | 
			
		||||
                    parseText (info->mResponse);
 | 
			
		||||
                    addTopicsFromText (info->mResponse);
 | 
			
		||||
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +289,10 @@ namespace MWDialogue
 | 
			
		|||
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
            std::string title;
 | 
			
		||||
| 
						 | 
				
			
			@ -320,7 +335,7 @@ namespace MWDialogue
 | 
			
		|||
 | 
			
		||||
            executeScript (info->mResultScript, mActor);
 | 
			
		||||
 | 
			
		||||
            parseText (info->mResponse);
 | 
			
		||||
            addTopicsFromText (info->mResponse);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -339,7 +354,6 @@ namespace MWDialogue
 | 
			
		|||
        updateGlobals();
 | 
			
		||||
 | 
			
		||||
        mActorKnownTopics.clear();
 | 
			
		||||
        mActorKnownTopicsFlag.clear();
 | 
			
		||||
 | 
			
		||||
        const auto& dialogs = MWBase::Environment::get().getWorld()->getStore().get<ESM::Dialogue>();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -354,21 +368,41 @@ namespace MWDialogue
 | 
			
		|||
 | 
			
		||||
                if (answer != nullptr)
 | 
			
		||||
                {
 | 
			
		||||
                    int flag = 0;
 | 
			
		||||
                    int topicFlags = 0;
 | 
			
		||||
                    if(!inJournal(topicId, answer->mId))
 | 
			
		||||
                    {
 | 
			
		||||
                        // Does this dialogue contains some actor-specific answer?
 | 
			
		||||
                        if (Misc::StringUtils::ciEqual(answer->mActor, mActor.getCellRef().getRefId()))
 | 
			
		||||
                            flag |= MWBase::DialogueManager::TopicType::Specific;
 | 
			
		||||
                            topicFlags |= MWBase::DialogueManager::TopicType::Specific;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        flag |= MWBase::DialogueManager::TopicType::Exhausted;
 | 
			
		||||
                    mActorKnownTopics.insert (dialog.mId);
 | 
			
		||||
                    mActorKnownTopicsFlag[dialog.mId] = flag;
 | 
			
		||||
                        topicFlags |= MWBase::DialogueManager::TopicType::Exhausted;
 | 
			
		||||
                    mActorKnownTopics.insert (std::make_pair(dialog.mId, ActorKnownTopicInfo {topicFlags, answer}));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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()
 | 
			
		||||
| 
						 | 
				
			
			@ -377,7 +411,7 @@ namespace MWDialogue
 | 
			
		|||
 | 
			
		||||
        std::list<std::string> keywordList;
 | 
			
		||||
 | 
			
		||||
        for (const std::string& topic : mActorKnownTopics)
 | 
			
		||||
        for (const auto& [topic, topicInfo] : mActorKnownTopics)
 | 
			
		||||
        {
 | 
			
		||||
            //does the player know the topic?
 | 
			
		||||
            if (mKnownTopics.count(topic))
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +425,7 @@ namespace MWDialogue
 | 
			
		|||
 | 
			
		||||
    int DialogueManager::getTopicFlag(const std::string& topicId)
 | 
			
		||||
    {
 | 
			
		||||
        return mActorKnownTopicsFlag[topicId];
 | 
			
		||||
        return mActorKnownTopics[topicId].mFlags;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void DialogueManager::keywordSelected (const std::string& keyword, ResponseCallback* callback)
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +478,7 @@ namespace MWDialogue
 | 
			
		|||
                if (const ESM::DialInfo *info = filter.search (*dialogue, true))
 | 
			
		||||
                {
 | 
			
		||||
                    std::string text = info->mResponse;
 | 
			
		||||
                    parseText (text);
 | 
			
		||||
                    addTopicsFromText (text);
 | 
			
		||||
 | 
			
		||||
                    mChoice = -1;
 | 
			
		||||
                    mIsInChoice = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -579,7 +613,7 @@ namespace MWDialogue
 | 
			
		|||
        {
 | 
			
		||||
            const ESM::DialInfo* info = infos[0];
 | 
			
		||||
 | 
			
		||||
            parseText (info->mResponse);
 | 
			
		||||
            addTopicsFromText (info->mResponse);
 | 
			
		||||
 | 
			
		||||
            const MWWorld::Store<ESM::GameSetting>& gmsts =
 | 
			
		||||
                MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
#include <components/compiler/streamerrorhandler.hpp>
 | 
			
		||||
#include <components/translation/translation.hpp>
 | 
			
		||||
#include <components/misc/stringops.hpp>
 | 
			
		||||
#include <components/esm/loadinfo.hpp>
 | 
			
		||||
 | 
			
		||||
#include "../mwworld/ptr.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,14 +25,19 @@ namespace MWDialogue
 | 
			
		|||
{
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
            // Modified faction reactions. <Faction1, <Faction2, Difference> >
 | 
			
		||||
            typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
 | 
			
		||||
            ModFactionReactionMap mChangedFactionReaction;
 | 
			
		||||
 | 
			
		||||
            std::set<std::string, Misc::StringUtils::CiComp> mActorKnownTopics;
 | 
			
		||||
            std::unordered_map<std::string, int> mActorKnownTopicsFlag;
 | 
			
		||||
            std::map<std::string, ActorKnownTopicInfo, Misc::StringUtils::CiComp> mActorKnownTopics;
 | 
			
		||||
 | 
			
		||||
            Translation::Storage& mTranslationDataStorage;
 | 
			
		||||
            MWScript::CompilerContext mCompilerContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +57,8 @@ namespace MWDialogue
 | 
			
		|||
            int mCurrentDisposition;
 | 
			
		||||
            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 updateGlobals();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue