From 2dd54dbcfcef832ce2c3fe49f31cecf741e316f7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 10 Jun 2014 16:36:22 +0200 Subject: [PATCH] Implement ClearInfoActor script instruction (Fixes #1422) --- apps/openmw/mwbase/dialoguemanager.hpp | 3 +++ apps/openmw/mwbase/journal.hpp | 5 +++++ apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 9 +++++++++ apps/openmw/mwdialogue/dialoguemanagerimp.hpp | 5 ++++- apps/openmw/mwdialogue/journalimp.cpp | 10 ++++++++++ apps/openmw/mwdialogue/journalimp.hpp | 5 +++++ apps/openmw/mwdialogue/topic.cpp | 13 +++++++++++++ apps/openmw/mwdialogue/topic.hpp | 2 ++ apps/openmw/mwscript/dialogueextensions.cpp | 14 ++++++++++++++ apps/openmw/mwscript/docs/vmformat.txt | 4 +++- components/compiler/extensions0.cpp | 1 + components/compiler/opcodes.hpp | 2 ++ 12 files changed, 71 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwbase/dialoguemanager.hpp b/apps/openmw/mwbase/dialoguemanager.hpp index dfb002cfc0..d0e64b23c8 100644 --- a/apps/openmw/mwbase/dialoguemanager.hpp +++ b/apps/openmw/mwbase/dialoguemanager.hpp @@ -76,6 +76,9 @@ namespace MWBase /// @return faction1's opinion of faction2 virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const = 0; + + /// Removes the last added topic response for the given actor from the journal + virtual void clearInfoActor (const MWWorld::Ptr& actor) const = 0; }; } diff --git a/apps/openmw/mwbase/journal.hpp b/apps/openmw/mwbase/journal.hpp index c43ebeb8f3..938cec74b2 100644 --- a/apps/openmw/mwbase/journal.hpp +++ b/apps/openmw/mwbase/journal.hpp @@ -60,6 +60,11 @@ namespace MWBase ///< Get the journal index. virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor) = 0; + /// \note topicId must be lowercase + + virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName) = 0; + ///< Removes the last topic response added for the given topicId and actor name. + /// \note topicId must be lowercase virtual TEntryIter begin() const = 0; ///< Iterator pointing to the begin of the main journal. diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index aca287854b..aa7df1fd4e 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -698,6 +698,15 @@ namespace MWDialogue return diff; } + void DialogueManager::clearInfoActor(const MWWorld::Ptr &actor) const + { + if (actor == mActor && !mLastTopic.empty()) + { + MWBase::Environment::get().getJournal()->removeLastAddedTopicResponse( + mLastTopic, actor.getClass().getName(actor)); + } + } + std::vector ParseHyperText(const std::string& text) { std::vector result; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index 94f8f3ec1a..6553ddc014 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -40,7 +40,7 @@ namespace MWDialogue bool mTalkedTo; int mChoice; - std::string mLastTopic; + std::string mLastTopic; // last topic ID, lowercase bool mIsInChoice; float mTemporaryDispositionChange; @@ -99,6 +99,9 @@ namespace MWDialogue /// @return faction1's opinion of faction2 virtual int getFactionReaction (const std::string& faction1, const std::string& faction2) const; + + /// Removes the last added topic response for the given actor from the journal + virtual void clearInfoActor (const MWWorld::Ptr& actor) const; }; diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index 1429415e51..9497347e3a 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -113,6 +113,16 @@ namespace MWDialogue topic.addEntry (entry); } + void Journal::removeLastAddedTopicResponse(const std::string &topicId, const std::string &actorName) + { + Topic& topic = getTopic (topicId); + + topic.removeLastAddedResponse(actorName); + + if (topic.begin() == topic.end()) + mTopics.erase(mTopics.find(topicId)); // All responses removed -> remove topic + } + int Journal::getJournalIndex (const std::string& id) const { TQuestContainer::const_iterator iter = mQuests.find (id); diff --git a/apps/openmw/mwdialogue/journalimp.hpp b/apps/openmw/mwdialogue/journalimp.hpp index 17b764436c..d15b909fa0 100644 --- a/apps/openmw/mwdialogue/journalimp.hpp +++ b/apps/openmw/mwdialogue/journalimp.hpp @@ -39,6 +39,11 @@ namespace MWDialogue ///< Get the journal index. virtual void addTopic (const std::string& topicId, const std::string& infoId, const MWWorld::Ptr& actor); + /// \note topicId must be lowercase + + virtual void removeLastAddedTopicResponse (const std::string& topicId, const std::string& actorName); + ///< Removes the last topic response added for the given topicId and actor name. + /// \note topicId must be lowercase virtual TEntryIter begin() const; ///< Iterator pointing to the begin of the main journal. diff --git a/apps/openmw/mwdialogue/topic.cpp b/apps/openmw/mwdialogue/topic.cpp index ea39174b8f..c1a45f841c 100644 --- a/apps/openmw/mwdialogue/topic.cpp +++ b/apps/openmw/mwdialogue/topic.cpp @@ -58,4 +58,17 @@ namespace MWDialogue { return mEntries.end(); } + + void Topic::removeLastAddedResponse (const std::string& actorName) + { + for (std::vector::reverse_iterator it = mEntries.rbegin(); + it != mEntries.rend(); ++it) + { + if (it->mActorName == actorName) + { + mEntries.erase( (++it).base() ); // erase doesn't take a reverse_iterator + return; + } + } + } } diff --git a/apps/openmw/mwdialogue/topic.hpp b/apps/openmw/mwdialogue/topic.hpp index cbff2296cb..72486ef8af 100644 --- a/apps/openmw/mwdialogue/topic.hpp +++ b/apps/openmw/mwdialogue/topic.hpp @@ -48,6 +48,8 @@ namespace MWDialogue virtual std::string getName() const; + void removeLastAddedResponse (const std::string& actorName); + TEntryIter begin() const; ///< Iterator pointing to the begin of the journal for this topic. diff --git a/apps/openmw/mwscript/dialogueextensions.cpp b/apps/openmw/mwscript/dialogueextensions.cpp index 9dde65ab2c..45eeccf182 100644 --- a/apps/openmw/mwscript/dialogueextensions.cpp +++ b/apps/openmw/mwscript/dialogueextensions.cpp @@ -235,6 +235,18 @@ namespace MWScript } }; + template + class OpClearInfoActor : public Interpreter::Opcode0 + { + public: + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + + MWBase::Environment::get().getDialogueManager()->clearInfoActor(ptr); + } + }; + void installOpcodes (Interpreter::Interpreter& interpreter) { @@ -256,6 +268,8 @@ namespace MWScript interpreter.installSegment5 (Compiler::Dialogue::opcodeSameFactionExplicit, new OpSameFaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeModFactionReaction, new OpModFactionReaction); interpreter.installSegment5 (Compiler::Dialogue::opcodeGetFactionReaction, new OpGetFactionReaction); + interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActor, new OpClearInfoActor); + interpreter.installSegment5 (Compiler::Dialogue::opcodeClearInfoActorExplicit, new OpClearInfoActor); } } diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 24b0b6f7aa..91d0f031f3 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -393,5 +393,7 @@ op 0x2000241: onKnockoutExplicit op 0x2000242: ModFactionReaction op 0x2000243: GetFactionReaction op 0x2000244: Activate, explicit +op 0x2000245: ClearInfoActor +op 0x2000246: ClearInfoActor, explicit -opcodes 0x2000245-0x3ffffff unused +opcodes 0x2000247-0x3ffffff unused diff --git a/components/compiler/extensions0.cpp b/components/compiler/extensions0.cpp index 0f726a52d2..61464e5c2a 100644 --- a/components/compiler/extensions0.cpp +++ b/components/compiler/extensions0.cpp @@ -181,6 +181,7 @@ namespace Compiler opcodeSameFactionExplicit); extensions.registerInstruction("modfactionreaction", "ccl", opcodeModFactionReaction); extensions.registerFunction("getfactionreaction", 'l', "ccl", opcodeGetFactionReaction); + extensions.registerInstruction("clearinfoactor", "", opcodeClearInfoActor, opcodeClearInfoActorExplicit); } } diff --git a/components/compiler/opcodes.hpp b/components/compiler/opcodes.hpp index 8796c53c54..4b22e4b9cd 100644 --- a/components/compiler/opcodes.hpp +++ b/components/compiler/opcodes.hpp @@ -154,6 +154,8 @@ namespace Compiler const int opcodeSameFactionExplicit = 0x20001b6; const int opcodeModFactionReaction = 0x2000242; const int opcodeGetFactionReaction = 0x2000243; + const int opcodeClearInfoActor = 0x2000245; + const int opcodeClearInfoActorExplicit = 0x2000246; } namespace Gui