From d358a65bbc57ab9099620bf2309893f99dbf164c Mon Sep 17 00:00:00 2001 From: Ľubomír Remák Date: Sun, 15 Jul 2018 15:52:29 +0200 Subject: MUTATIONOFJB: Run extra sections from conversation. --- engines/mutationofjb/commands/endblockcommand.cpp | 27 ++++++++++++ engines/mutationofjb/commands/endblockcommand.h | 1 + engines/mutationofjb/conversationlinelist.cpp | 4 +- engines/mutationofjb/mutationofjb.cpp | 1 + engines/mutationofjb/script.cpp | 27 ++++++++++++ engines/mutationofjb/script.h | 5 +++ engines/mutationofjb/tasks/conversationtask.cpp | 54 ++++++++++++++++++++--- engines/mutationofjb/tasks/conversationtask.h | 9 +++- 8 files changed, 119 insertions(+), 9 deletions(-) diff --git a/engines/mutationofjb/commands/endblockcommand.cpp b/engines/mutationofjb/commands/endblockcommand.cpp index 5fcccd390b..b883beed48 100644 --- a/engines/mutationofjb/commands/endblockcommand.cpp +++ b/engines/mutationofjb/commands/endblockcommand.cpp @@ -35,6 +35,7 @@ ("#U " | "-U ") [] ("#ELSE" | "-ELSE") [] "#MACRO " + "#EXTRA" If a line starts with '#', '=', '-', it is treated as the end of a section. However, at the same time it can also start a new section depending on what follows. @@ -46,6 +47,8 @@ #ELSE is used by conditional commands (see comments for IfCommand and others). #MACRO starts a new macro. Global script can call macros from local script and vice versa. + + #EXTRA defines an "extra" section. This is called from dialog responses ("TALK TO HIM" command). */ namespace MutationOfJB { @@ -119,6 +122,9 @@ bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext const uint8 startupId = atoi(line.c_str() + 9); IdAndCommand ic = {startupId, command}; _foundStartups.push_back(ic); + } else if (line.size() >= 7 && line.hasPrefix("#EXTRA")) { + NameAndCommand nc = {line.c_str() + 6, command}; + _foundExtras.push_back(nc); } if (firstChar == '#') { @@ -183,6 +189,23 @@ void EndBlockCommandParser::transition(ScriptParseContext &parseCtx, Command *ol } } } + if (!_foundExtras.empty()) { + if (newCommand) { + for (NameAndCommandArray::iterator it = _foundExtras.begin(); it != _foundExtras.end();) { + if (it->_command != oldCommand) { + it++; + continue; + } + + if (!parseCtx._extras.contains(it->_name)) { + parseCtx._extras[it->_name] = newCommand; + } else { + warning(_("Extra '%s' already exists"), it->_name.c_str()); + } + it = _foundExtras.erase(it); + } + } + } if (newCommandParser != this) { if (!_pendingActionInfos.empty()) { @@ -208,9 +231,13 @@ void EndBlockCommandParser::finish(ScriptParseContext &) { if (!_foundStartups.empty()) { debug("Problem: Found startups from end block parser is not empty!"); } + if (!_foundExtras.empty()) { + debug("Problem: Found extras from end block parser is not empty!"); + } _pendingActionInfos.clear(); _foundMacros.clear(); _foundStartups.clear(); + _foundExtras.clear(); } Command::ExecuteResult EndBlockCommand::execute(ScriptExecutionContext &scriptExecCtx) { diff --git a/engines/mutationofjb/commands/endblockcommand.h b/engines/mutationofjb/commands/endblockcommand.h index 4ca46dd97d..55656aa351 100644 --- a/engines/mutationofjb/commands/endblockcommand.h +++ b/engines/mutationofjb/commands/endblockcommand.h @@ -56,6 +56,7 @@ private: typedef Common::Array IdAndCommandArray; NameAndCommandArray _foundMacros; IdAndCommandArray _foundStartups; + NameAndCommandArray _foundExtras; }; class EndBlockCommand : public Command { diff --git a/engines/mutationofjb/conversationlinelist.cpp b/engines/mutationofjb/conversationlinelist.cpp index 562c2d0e39..3164ff507b 100644 --- a/engines/mutationofjb/conversationlinelist.cpp +++ b/engines/mutationofjb/conversationlinelist.cpp @@ -56,8 +56,8 @@ bool ConversationLineList::parseFile(const Common::String &fileName) { Common::String::iterator endIt = Common::find(lineStr.begin(), lineStr.end(), '|'); if (endIt != lineStr.end()) { - Common::String extra = lineStr + endIt; - if (*endIt == 'X') { + endIt++; + if (endIt != lineStr.end() && *endIt == 'X') { line._extra = Common::String(endIt + 1, lineStr.end()); // Skip 'X' char. } } diff --git a/engines/mutationofjb/mutationofjb.cpp b/engines/mutationofjb/mutationofjb.cpp index e7f534edb0..986b00dfc9 100644 --- a/engines/mutationofjb/mutationofjb.cpp +++ b/engines/mutationofjb/mutationofjb.cpp @@ -202,6 +202,7 @@ Common::Error MutationOfJBEngine::run() { _game->setCurrentAction(ActionInfo::PickUp); break; } + break; } default: break; diff --git a/engines/mutationofjb/script.cpp b/engines/mutationofjb/script.cpp index d90f37e161..39c485991b 100644 --- a/engines/mutationofjb/script.cpp +++ b/engines/mutationofjb/script.cpp @@ -189,6 +189,23 @@ Command *ScriptExecutionContext::getMacro(const Common::String &name) const { return cmd; } +Command *ScriptExecutionContext::getExtra(const Common::String &name) const { + Command *cmd = nullptr; + + Script *const localScript = _localScriptOverride ? _localScriptOverride : _game.getLocalScript(); + Script *const globalScript = _game.getGlobalScript(); + + if (localScript) { + cmd = localScript->getExtra(name); + } + + if (!cmd && globalScript) { + cmd = globalScript->getExtra(name); + } + + return cmd; +} + bool Script::loadFromStream(Common::SeekableReadStream &stream) { destroy(); @@ -236,6 +253,7 @@ bool Script::loadFromStream(Common::SeekableReadStream &stream) { _macros = parseCtx._macros; _startups = parseCtx._startups; + _extras = parseCtx._extras; return true; } @@ -285,4 +303,13 @@ Command *Script::getStartup(uint8 startupId) const { return it->_value; } +Command *Script::getExtra(const Common::String &name) const { + Extras::const_iterator it = _extras.find(name); + if (it == _extras.end()) { + return nullptr; + } + + return it->_value; +} + } diff --git a/engines/mutationofjb/script.h b/engines/mutationofjb/script.h index 3ef25f4b68..28e0e98526 100644 --- a/engines/mutationofjb/script.h +++ b/engines/mutationofjb/script.h @@ -67,6 +67,7 @@ typedef Common::Array ActionInfos; typedef Common::Array GotoCommands; typedef Common::HashMap Macros; typedef Common::HashMap Startups; +typedef Common::HashMap Extras; class ScriptParseContext { public: @@ -98,6 +99,7 @@ public: ActionInfos _actionInfos; Macros _macros; Startups _startups; + Extras _extras; private: }; @@ -116,6 +118,7 @@ public: Game &getGame(); GameData &getGameData(); Command *getMacro(const Common::String &name) const; + Command *getExtra(const Common::String &name) const; private: Game &_game; @@ -135,6 +138,7 @@ public: const Startups &getStartups() const; Command *getMacro(const Common::String &name) const; Command *getStartup(uint8 startupId) const; + Command *getExtra(const Common::String &name) const; private: void destroy(); @@ -142,6 +146,7 @@ private: ActionInfos _actionInfos[5]; Macros _macros; Startups _startups; + Extras _extras; }; } diff --git a/engines/mutationofjb/tasks/conversationtask.cpp b/engines/mutationofjb/tasks/conversationtask.cpp index 512b38b710..47f27df247 100644 --- a/engines/mutationofjb/tasks/conversationtask.cpp +++ b/engines/mutationofjb/tasks/conversationtask.cpp @@ -27,11 +27,14 @@ #include "mutationofjb/game.h" #include "mutationofjb/gamedata.h" #include "mutationofjb/gui.h" +#include "mutationofjb/script.h" #include "mutationofjb/tasks/saytask.h" #include "mutationofjb/tasks/taskmanager.h" #include "mutationofjb/util.h" #include "mutationofjb/widgets/conversationwidget.h" +#include "common/translation.h" + namespace MutationOfJB { void ConversationTask::start() { @@ -69,11 +72,11 @@ void ConversationTask::update() { break; } case SAYING_RESPONSE: { - if (_currentItem->_nextLineIndex == 0) { - finish(); - } else { - _currentLineIndex = _currentItem->_nextLineIndex - 1; - showChoicesOrPick(); + startExtra(); + + if (_substate != RUNNING_EXTRA) + { + gotoNextLine(); } break; } @@ -82,6 +85,16 @@ void ConversationTask::update() { } } } + + if (_innerExecCtx) { + Command::ExecuteResult res = _innerExecCtx->runActiveCommand(); + if (res == Command::Finished) { + delete _innerExecCtx; + _innerExecCtx = nullptr; + + gotoNextLine(); + } + } } void ConversationTask::onChoiceClicked(ConversationWidget *convWidget, int, uint32 data) { @@ -203,4 +216,35 @@ void ConversationTask::finish() { game.getGui().markDirty(); // TODO: Handle automatically when changing visibility. } +void ConversationTask::startExtra() { + const ConversationLineList& responseList = getTaskManager()->getGame().getAssets().getResponseList(); + const ConversationLineList::Line *const line = responseList.getLine(_currentItem->_response); + if (!line->_extra.empty()) { + _innerExecCtx = new ScriptExecutionContext(getTaskManager()->getGame()); + Command *const extraCmd = _innerExecCtx->getExtra(line->_extra); + if (extraCmd) { + Command::ExecuteResult res = _innerExecCtx->startCommand(extraCmd); + if (res == Command::InProgress) { + _substate = RUNNING_EXTRA; + } else { + delete _innerExecCtx; + _innerExecCtx = nullptr; + } + } else { + warning(_("Extra '%s' not found"), line->_extra.c_str()); + delete _innerExecCtx; + _innerExecCtx = nullptr; + } + } +} + +void ConversationTask::gotoNextLine() { + if (_currentItem->_nextLineIndex == 0) { + finish(); + } else { + _currentLineIndex = _currentItem->_nextLineIndex - 1; + showChoicesOrPick(); + } +} + } diff --git a/engines/mutationofjb/tasks/conversationtask.h b/engines/mutationofjb/tasks/conversationtask.h index 3bcbb6f998..41c82849ee 100644 --- a/engines/mutationofjb/tasks/conversationtask.h +++ b/engines/mutationofjb/tasks/conversationtask.h @@ -27,10 +27,11 @@ namespace MutationOfJB { class SayTask; +class ScriptExecutionContext; class ConversationTask : public Task, public ConversationWidgetCallback { public: - ConversationTask(uint8 sceneId, const ConversationInfo& convInfo) : _sceneId(sceneId), _convInfo(convInfo), _currentLineIndex(0), _currentItem(nullptr), _sayTask(nullptr), _substate(IDLE), _haveChoices(false) {} + ConversationTask(uint8 sceneId, const ConversationInfo& convInfo) : _sceneId(sceneId), _convInfo(convInfo), _currentLineIndex(0), _currentItem(nullptr), _sayTask(nullptr), _substate(IDLE), _haveChoices(false), _innerExecCtx(nullptr) {} virtual ~ConversationTask() {} virtual void start() override; @@ -41,6 +42,8 @@ private: void showChoicesOrPick(); const ConversationInfo::Line *getCurrentLine() const; void finish(); + void startExtra(); + void gotoNextLine(); uint8 _sceneId; const ConversationInfo &_convInfo; @@ -52,11 +55,13 @@ private: IDLE, SAYING_CHOICE, SAYING_RESPONSE, - SAYING_NO_CHOICES + SAYING_NO_CHOICES, + RUNNING_EXTRA }; Substate _substate; bool _haveChoices; + ScriptExecutionContext *_innerExecCtx; }; } -- cgit v1.2.3