aboutsummaryrefslogtreecommitdiff
path: root/engines/mutationofjb
diff options
context:
space:
mode:
authorĽubomír Remák2018-02-25 04:14:32 +0100
committerEugene Sandulenko2018-08-25 23:12:01 +0200
commit3672ea55720666acfd64b6df01b35d0727d6be78 (patch)
tree58e77efe67e9381c788c30d1e75b518a984c2020 /engines/mutationofjb
parentf7d5a825a053199ddbf4d7c564e84e9f9709d958 (diff)
downloadscummvm-rg350-3672ea55720666acfd64b6df01b35d0727d6be78.tar.gz
scummvm-rg350-3672ea55720666acfd64b6df01b35d0727d6be78.tar.bz2
scummvm-rg350-3672ea55720666acfd64b6df01b35d0727d6be78.zip
MUTATIONOFJB: Continue implementation of if/else script commands.
Diffstat (limited to 'engines/mutationofjb')
-rw-r--r--engines/mutationofjb/commands/command.cpp4
-rw-r--r--engines/mutationofjb/commands/command.h9
-rw-r--r--engines/mutationofjb/commands/conditionalcommand.cpp19
-rw-r--r--engines/mutationofjb/commands/conditionalcommand.h4
-rw-r--r--engines/mutationofjb/commands/endblockcommand.cpp108
-rw-r--r--engines/mutationofjb/commands/endblockcommand.h53
-rw-r--r--engines/mutationofjb/commands/ifcommand.cpp12
-rw-r--r--engines/mutationofjb/commands/ifcommand.h6
-rw-r--r--engines/mutationofjb/commands/seqcommand.cpp12
-rw-r--r--engines/mutationofjb/commands/seqcommand.h5
-rw-r--r--engines/mutationofjb/module.mk1
-rw-r--r--engines/mutationofjb/mutationofjb.cpp16
-rw-r--r--engines/mutationofjb/script.cpp61
-rw-r--r--engines/mutationofjb/script.h36
14 files changed, 330 insertions, 16 deletions
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!
// <t> 1B Tag.
// <ss> 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<IfCommand *>(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<SeqCommand *>(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<Common::String, Command *> macros;
Common::HashMap<Common::String, Command *> 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<Command*> 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<ConditionalCommandInfo> ConditionalCommandInfos;
+
+ ConditionalCommandInfos _pendingCondCommands;
+
+ enum Action {
+ Walk,
+ Talk,
+ Look,
+ Use
};
- Common::Array<ConditionalCommandInfo> _pendingCondCommands;
+
+ struct ActionInfo {
+ Action _action;
+ Common::String _object1Name;
+ Common::String _object2Name;
+ bool walkTo;
+ };
+ typedef Common::Array<ActionInfo> ActionInfos;
+ ActionInfos _actionInfos;
+private:
};
class Script {
public:
bool loadFromStream(Common::SeekableReadStream &stream);
+ ~Script();
private:
-
+ void destroy();
+ Commands _allCommands;
};
}