From 3672ea55720666acfd64b6df01b35d0727d6be78 Mon Sep 17 00:00:00 2001 From: Ľubomír Remák Date: Sun, 25 Feb 2018 04:14:32 +0100 Subject: MUTATIONOFJB: Continue implementation of if/else script commands. --- engines/mutationofjb/commands/command.cpp | 4 + engines/mutationofjb/commands/command.h | 9 ++ .../mutationofjb/commands/conditionalcommand.cpp | 19 +++- engines/mutationofjb/commands/conditionalcommand.h | 4 + engines/mutationofjb/commands/endblockcommand.cpp | 108 +++++++++++++++++++++ engines/mutationofjb/commands/endblockcommand.h | 53 ++++++++++ engines/mutationofjb/commands/ifcommand.cpp | 12 ++- engines/mutationofjb/commands/ifcommand.h | 6 ++ engines/mutationofjb/commands/seqcommand.cpp | 12 ++- engines/mutationofjb/commands/seqcommand.h | 5 + engines/mutationofjb/module.mk | 1 + engines/mutationofjb/mutationofjb.cpp | 16 +++ engines/mutationofjb/script.cpp | 61 ++++++++++-- engines/mutationofjb/script.h | 36 +++++-- 14 files changed, 330 insertions(+), 16 deletions(-) create mode 100644 engines/mutationofjb/commands/endblockcommand.cpp create mode 100644 engines/mutationofjb/commands/endblockcommand.h (limited to 'engines') diff --git a/engines/mutationofjb/commands/command.cpp b/engines/mutationofjb/commands/command.cpp index d0b3f826e3..af4c28e7eb 100644 --- a/engines/mutationofjb/commands/command.cpp +++ b/engines/mutationofjb/commands/command.cpp @@ -24,6 +24,10 @@ #include "common/scummsys.h" namespace MutationOfJB { + +void CommandParser::transition(ScriptParseContext &, Command *, Command *) {} +CommandParser::~CommandParser() {} + Command::~Command() {} SeqCommand *Command::asSeqCommand() { diff --git a/engines/mutationofjb/commands/command.h b/engines/mutationofjb/commands/command.h index beae9d2833..ab0ebc6da8 100644 --- a/engines/mutationofjb/commands/command.h +++ b/engines/mutationofjb/commands/command.h @@ -38,6 +38,15 @@ class Command; typedef bool (*CommandParseFunc)(const Common::String &line, ScriptParseContext &parseContext, Command *&command); +class CommandParser { +public: + virtual ~CommandParser(); + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) = 0; + + /* Old command - created by this parser. */ + virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand); +}; + class Command { public: enum ExecuteResult { diff --git a/engines/mutationofjb/commands/conditionalcommand.cpp b/engines/mutationofjb/commands/conditionalcommand.cpp index 3118e6d8cb..13ea6741d1 100644 --- a/engines/mutationofjb/commands/conditionalcommand.cpp +++ b/engines/mutationofjb/commands/conditionalcommand.cpp @@ -31,6 +31,23 @@ ConditionalCommand::ConditionalCommand() : _cachedResult(false) {} + +Command *ConditionalCommand::getTrueCommand() const { + return _trueCommand; +} + +Command *ConditionalCommand::getFalseCommand() const { + return _falseCommand; +} + +void ConditionalCommand::setTrueCommand(Command *command) { + _trueCommand = command; +} + +void ConditionalCommand::setFalseCommand(Command *command) { + _falseCommand = command; +} + Command *ConditionalCommand::next() const { if (_cachedResult) { return _trueCommand; @@ -38,4 +55,4 @@ Command *ConditionalCommand::next() const { return _falseCommand; } } -}; +} diff --git a/engines/mutationofjb/commands/conditionalcommand.h b/engines/mutationofjb/commands/conditionalcommand.h index e355662454..27a8ac1968 100644 --- a/engines/mutationofjb/commands/conditionalcommand.h +++ b/engines/mutationofjb/commands/conditionalcommand.h @@ -28,6 +28,10 @@ namespace MutationOfJB { class ConditionalCommand : public Command { public: ConditionalCommand(); + + Command *getTrueCommand() const; + Command *getFalseCommand() const; + void setTrueCommand(Command *command); void setFalseCommand(Command *command); diff --git a/engines/mutationofjb/commands/endblockcommand.cpp b/engines/mutationofjb/commands/endblockcommand.cpp new file mode 100644 index 0000000000..218be1a31f --- /dev/null +++ b/engines/mutationofjb/commands/endblockcommand.cpp @@ -0,0 +1,108 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "mutationofjb/commands/endblockcommand.h" +#include "mutationofjb/script.h" +#include "mutationofjb/commands/conditionalcommand.h" +#include "common/str.h" +#include "common/debug.h" + +namespace MutationOfJB { + +bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *& command) { + if (line.empty()) { + return false; + } + + const char firstChar = line.firstChar(); + if (firstChar != '#' && firstChar != '=' && firstChar != '-') { + return false; + } + + // This is the start or end of section/block. + + if (line.size() >= 4 && (line.hasPrefix("#L ") || line.hasPrefix("-L "))) { + ScriptParseContext::ActionInfo ai = {ScriptParseContext::Look, line.c_str() + 3, "", firstChar == '#'}; + parseCtx._actionInfos.push_back(ai); + debug("# Look: %s", line.c_str() + 3); + } else if (line.size() >= 4 && (line.hasPrefix("#W ") || line.hasPrefix("-W "))) { + ScriptParseContext::ActionInfo ai = {ScriptParseContext::Walk, line.c_str() + 3, "", firstChar == '#'}; + parseCtx._actionInfos.push_back(ai); + } else if (line.size() >= 4 && (line.hasPrefix("#T ") || line.hasPrefix("-T "))) { + ScriptParseContext::ActionInfo ai = {ScriptParseContext::Talk, line.c_str() + 3, "", firstChar == '#'}; + parseCtx._actionInfos.push_back(ai); + } else if (line.size() >= 4 && (line.hasPrefix("#U ") || line.hasPrefix("-U "))) { + int secondObjPos = -1; + for (int i = 3; i < (int) line.size(); ++i) { + if (line[i] == ' ') { + secondObjPos = i + 1; + break; + } + } + ScriptParseContext::ActionInfo ai = { + ScriptParseContext::Talk, + line.c_str() + 3, + (secondObjPos != -1) ? line.c_str() + secondObjPos : "", + firstChar == '#' + }; + parseCtx._actionInfos.push_back(ai); + } else if ((line.hasPrefix("#ELSE") || line.hasPrefix("=ELSE"))) { + _elseFound = true; + _ifTag = 0; + if (line.size() >= 6) { + _ifTag = line[5]; + } + } + + command = new EndBlockCommand(); + + return true; +} + +void EndBlockCommandParser::transition(ScriptParseContext &parseCtx, Command *, Command *newCommand) { + if (_elseFound) { + if (newCommand) { + ScriptParseContext::ConditionalCommandInfos::iterator it = parseCtx._pendingCondCommands.begin(); + + while (it != parseCtx._pendingCondCommands.end()) { + if (it->_tag == _ifTag) { + it->_command->setFalseCommand(newCommand); + it = parseCtx._pendingCondCommands.erase(it); + } else { + ++it; + } + } + } + + _elseFound = false; + _ifTag = 0; + } +} + +Command::ExecuteResult EndBlockCommand::execute(GameData &) { + return Finished; +} + +Command *EndBlockCommand::next() const { + return nullptr; +} +} diff --git a/engines/mutationofjb/commands/endblockcommand.h b/engines/mutationofjb/commands/endblockcommand.h new file mode 100644 index 0000000000..1ac636c6d5 --- /dev/null +++ b/engines/mutationofjb/commands/endblockcommand.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef MUTATIONOFJB_ENDBLOCKCOMMAND_H +#define MUTATIONOFJB_ENDBLOCKCOMMAND_H + +#include "mutationofjb/commands/command.h" +#include "common/scummsys.h" + +namespace MutationOfJB { + +class EndBlockCommandParser : public CommandParser { +public: + EndBlockCommandParser() : _elseFound(false), _ifTag(0) {} + + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command); + virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand); + +private: + bool _elseFound; + char _ifTag; +}; + +class EndBlockCommand : public Command { +public: + static bool ParseFunc(const Common::String &line, ScriptParseContext &parseContext, Command *&command); + + virtual ExecuteResult execute(GameData &gameData) override; + virtual Command *next() const override; +}; + +} + +#endif diff --git a/engines/mutationofjb/commands/ifcommand.cpp b/engines/mutationofjb/commands/ifcommand.cpp index 18b8081842..5ba35bc3ea 100644 --- a/engines/mutationofjb/commands/ifcommand.cpp +++ b/engines/mutationofjb/commands/ifcommand.cpp @@ -28,8 +28,7 @@ namespace MutationOfJB { -bool IfCommand::ParseFunc(const Common::String &line, ScriptParseContext &parseContext, Command *&command) -{ +bool IfCommandParser::parse(const Common::String &line, ScriptParseContext &parseContext, Command *&command) { // IFtss oo val! // 1B Tag. // 2B Scene. @@ -59,6 +58,15 @@ bool IfCommand::ParseFunc(const Common::String &line, ScriptParseContext &parseC return true; } +void IfCommandParser::transition(ScriptParseContext &, Command *oldCommand, Command *newCommand) { + if (!oldCommand || !newCommand) { + warning(_("Unexpected empty command in transition")); + return; + } + + static_cast(oldCommand)->setTrueCommand(newCommand); +} + IfCommand::IfCommand(uint8 sceneId, uint8 objectId, uint16 value, bool negative) : _sceneId(sceneId), _objectId(objectId), diff --git a/engines/mutationofjb/commands/ifcommand.h b/engines/mutationofjb/commands/ifcommand.h index d33f34ffb0..290260be93 100644 --- a/engines/mutationofjb/commands/ifcommand.h +++ b/engines/mutationofjb/commands/ifcommand.h @@ -30,6 +30,12 @@ namespace MutationOfJB { class ScriptParseContext; +class IfCommandParser : public CommandParser { +public: + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command); + virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand); +}; + class IfCommand : public ConditionalCommand { public: static bool ParseFunc(const Common::String &line, ScriptParseContext &parseContext, Command *&command); diff --git a/engines/mutationofjb/commands/seqcommand.cpp b/engines/mutationofjb/commands/seqcommand.cpp index ab98497f21..22d1c9051b 100644 --- a/engines/mutationofjb/commands/seqcommand.cpp +++ b/engines/mutationofjb/commands/seqcommand.cpp @@ -20,10 +20,20 @@ * */ -#include "seqcommand.h" +#include "mutationofjb/commands/seqcommand.h" +#include "common/translation.h" namespace MutationOfJB { +void SeqCommandParser::transition(ScriptParseContext &, Command * oldCommand, Command * newCommand) { + if (!oldCommand || !newCommand) { + warning(_("Unexpected empty command in transition")); + return; + } + + static_cast(oldCommand)->setNextCommand(newCommand); +} + void SeqCommand::setNextCommand(Command *nextCommand) { _nextCommand = nextCommand; diff --git a/engines/mutationofjb/commands/seqcommand.h b/engines/mutationofjb/commands/seqcommand.h index b247fb22e1..1d21f66948 100644 --- a/engines/mutationofjb/commands/seqcommand.h +++ b/engines/mutationofjb/commands/seqcommand.h @@ -28,6 +28,11 @@ namespace MutationOfJB { +class SeqCommandParser : public CommandParser +{ + virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand) override; +}; + class SeqCommand : public Command { public: void setNextCommand(Command *nextCommand); diff --git a/engines/mutationofjb/module.mk b/engines/mutationofjb/module.mk index e6c539a2c8..132d8698aa 100644 --- a/engines/mutationofjb/module.mk +++ b/engines/mutationofjb/module.mk @@ -3,6 +3,7 @@ MODULE := engines/mutationofjb MODULE_OBJS := \ commands/command.o \ commands/conditionalcommand.o \ + commands/endblockcommand.o \ commands/ifcommand.o \ commands/seqcommand.o \ detection.o \ diff --git a/engines/mutationofjb/mutationofjb.cpp b/engines/mutationofjb/mutationofjb.cpp index cdefbb9833..59553d4d34 100644 --- a/engines/mutationofjb/mutationofjb.cpp +++ b/engines/mutationofjb/mutationofjb.cpp @@ -36,6 +36,7 @@ #include "mutationofjb/game.h" #include "mutationofjb/encryptedfile.h" #include "mutationofjb/util.h" +#include "mutationofjb/script.h" namespace MutationOfJB { @@ -96,10 +97,24 @@ Common::Error MutationOfJBEngine::run() { _room = new Room(_screen); _room->load(_gameData->_currentScene, false); + EncryptedFile globalScriptFile; + globalScriptFile.open("global.atn"); + Script *script = new Script; + script->loadFromStream(globalScriptFile); + globalScriptFile.close(); + while(!shouldQuit()) { Common::Event event; while (_eventMan->pollEvent(event)) { switch (event.type) { + case Common::EVENT_KEYDOWN: + { + if ((event.kbd.hasFlags(Common::KBD_CTRL) && event.kbd.keycode == Common::KEYCODE_d) || + event.kbd.ascii == '~' || event.kbd.ascii == '#') { + _console->attach(); + } + break; + } case Common::EVENT_LBUTTONDOWN: { const Scene* const scene = _gameData->getScene(_gameData->_currentScene); @@ -119,6 +134,7 @@ Common::Error MutationOfJBEngine::run() { } } + _console->onFrame(); _system->delayMillis(40); _screen->update(); } diff --git a/engines/mutationofjb/script.cpp b/engines/mutationofjb/script.cpp index 0280c86198..a20c11eef0 100644 --- a/engines/mutationofjb/script.cpp +++ b/engines/mutationofjb/script.cpp @@ -25,25 +25,37 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "common/stream.h" +#include "common/debug.h" #include "mutationofjb/commands/command.h" +#include "mutationofjb/commands/ifcommand.h" +#include "mutationofjb/commands/endblockcommand.h" namespace MutationOfJB { -static CommandParseFunc* getParseFuncs() { - static CommandParseFunc funcs[] = { +static CommandParser** getParsers() { + static CommandParser* parsers[] = { + new IfCommandParser, + new EndBlockCommandParser, nullptr }; - return funcs; + return parsers; } -ScriptParseContext::ScriptParseContext(Common::SeekableReadStream &stream) : _stream(stream) {} +ScriptParseContext::ScriptParseContext(Common::SeekableReadStream &stream) : + _stream(stream), + _currentCommand(nullptr), + _lastCommand(nullptr) +{} bool ScriptParseContext::readLine(Common::String &line) { do { Common::String str = _stream.readLine(); - if (str.empty() || str[0] != '.') { + if (str.empty()) + continue; + + if (str[0] != '.') { line = str; if (line[0] == '*') { line.deleteChar(0); @@ -61,15 +73,52 @@ void ScriptParseContext::addConditionalCommand(ConditionalCommand *command, char } bool Script::loadFromStream(Common::SeekableReadStream &stream) { + destroy(); - CommandParseFunc * const parseFuncs = getParseFuncs(); + CommandParser **parsers = getParsers(); ScriptParseContext parseCtx(stream); + Common::String line; + + Command *lastCmd = nullptr; + CommandParser *lastParser = nullptr; + while (parseCtx.readLine(line)) { + Command *currentCmd = nullptr; + CommandParser *currentParser = nullptr; + + for (CommandParser **parser = parsers; *parser; ++parser) { + if ((*parser)->parse(line, parseCtx, currentCmd)) { + currentParser = *parser; + break; + } + } + if (lastParser) { + lastParser->transition(parseCtx, lastCmd, currentCmd); + } + + if (currentCmd) { + _allCommands.push_back(currentCmd); + } + + lastParser = currentParser; + } + Common::HashMap macros; Common::HashMap labels; return true; } +void Script::destroy() { + for (Commands::iterator it = _allCommands.begin(); it != _allCommands.end(); ++it) { + delete *it; + } + _allCommands.clear(); +} + +Script::~Script() { + destroy(); +} + } diff --git a/engines/mutationofjb/script.h b/engines/mutationofjb/script.h index 9c0f0f3b1c..da90a2411f 100644 --- a/engines/mutationofjb/script.h +++ b/engines/mutationofjb/script.h @@ -32,7 +32,9 @@ namespace Common { namespace MutationOfJB { +class Command; class ConditionalCommand; +typedef Common::Array Commands; class ScriptParseContext { @@ -40,23 +42,45 @@ public: ScriptParseContext(Common::SeekableReadStream &stream); bool readLine(Common::String &line); void addConditionalCommand(ConditionalCommand *command, char tag); - //void setLastIfCommand(IfCommand *command); + void addLookSection(const Common::String & item, bool walkTo); -private: Common::SeekableReadStream &_stream; + Command *_currentCommand; + Command *_lastCommand; struct ConditionalCommandInfo { - ConditionalCommand *command; - char tag; + ConditionalCommand *_command; + char _tag; + }; + typedef Common::Array ConditionalCommandInfos; + + ConditionalCommandInfos _pendingCondCommands; + + enum Action { + Walk, + Talk, + Look, + Use }; - Common::Array _pendingCondCommands; + + struct ActionInfo { + Action _action; + Common::String _object1Name; + Common::String _object2Name; + bool walkTo; + }; + typedef Common::Array ActionInfos; + ActionInfos _actionInfos; +private: }; class Script { public: bool loadFromStream(Common::SeekableReadStream &stream); + ~Script(); private: - + void destroy(); + Commands _allCommands; }; } -- cgit v1.2.3