Permalink
Browse files

MUTATIONOFJB: Add support for macro definitions.

  • Loading branch information...
LubomirR committed Mar 22, 2018
1 parent 44f2663 commit a1adb9a85017cec51ca23f7fcd7da02e3db8f2ff
@@ -24,7 +24,7 @@
#define MUTATIONOFJB_COMMAND_H

namespace Common {
class String;
class String;
}

namespace MutationOfJB {
@@ -26,6 +26,26 @@
#include "common/str.h"
#include "common/debug.h"

/*
("#L " | "-L ") <object>
("#W " | "-W ") <object>
("#T " | "-T ") <object>
("#U " | "-U ") <object1> [<object2>]
("#ELSE" | "-ELSE") [<tag>]
"#MACRO " <name>
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.
#L (look), #W (walk), #T (talk), #U (use) sections are executed
when the user starts corresponding action on the object or in case of "use" up to two objects.
The difference between '#' and '-' version is whether the player walks towards the object ('#') or not ('-').
#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.
*/

namespace MutationOfJB {

bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
@@ -85,6 +105,8 @@ bool EndBlockCommandParser::parse(const Common::String &line, ScriptParseContext
if (line.size() >= 6) {
_ifTag = line[5];
}
} else if (line.size() >= 8 && line.hasPrefix("#MACRO")) {
_foundMacro = line.c_str() + 7;
}

if (firstChar == '#') {
@@ -116,6 +138,13 @@ void EndBlockCommandParser::transition(ScriptParseContext &parseCtx, Command *,
_ifTag = 0;
}

if (!_foundMacro.empty() && newCommand) {
if (!parseCtx._macros.contains(_foundMacro)) {
parseCtx._macros[_foundMacro] = newCommand;
}
_foundMacro = "";
}

if (newCommandParser != this) {
if (!_pendingActionInfos.empty()) {
for (Common::Array<uint>::iterator it = _pendingActionInfos.begin(); it != _pendingActionInfos.end(); ++it) {
@@ -135,6 +164,7 @@ void EndBlockCommandParser::finish(ScriptParseContext &) {
debug("Problem: Pending action infos from end block parser is not empty!");
}
_pendingActionInfos.clear();
_foundMacro = "";
}

Command::ExecuteResult EndBlockCommand::execute(GameData &) {
@@ -44,6 +44,7 @@ class EndBlockCommandParser : public CommandParser {
char _ifTag;

Common::Array<uint> _pendingActionInfos;
Common::String _foundMacro;
};

class EndBlockCommand : public Command {
@@ -204,4 +204,55 @@ bool Console::cmd_showsection(int argc, const char **argv) {
return true;
}

bool Console::cmd_listmacros(int argc, const char **argv) {
if (argc == 2) {
Script *script = nullptr;
if (strcmp(argv[1], "G") == 0) {
script = _vm->getGame().getGlobalScript();
} else if (strcmp(argv[1], "L") == 0) {
script = _vm->getGame().getLocalScript();
}
if (!script) {
debugPrintf(_("Choose 'G' (global) or 'L' (local) script.\n"));
} else {
const Macros &macros = script->getMacros();
for (Macros::const_iterator it = macros.begin(); it != macros.end(); ++it) {
debugPrintf("%s\n", it->_key.c_str());
}
}
} else {
debugPrintf(_("listmacros <G|L>\n"));
}

return true;
}

bool Console::cmd_showmacro(int argc, const char **argv) {
if (argc == 3) {
Script *script = nullptr;
if (strcmp(argv[1], "G") == 0) {
script = _vm->getGame().getGlobalScript();
} else if (strcmp(argv[1], "L") == 0) {
script = _vm->getGame().getLocalScript();
}
if (!script) {
debugPrintf(_("Choose 'G' (global) or 'L' (local) script.\n"));
} else {
const Macros &macros = script->getMacros();
Macros::const_iterator itMacro = macros.find(argv[2]);
if (itMacro != macros.end()) {
if (itMacro->_value) {
showCommands(itMacro->_value);
}
} else {
debugPrintf("Macro not found.\n");
}
}
} else {
debugPrintf(_("showmacro <G|L> <macroname>\n"));
}

return true;
}

}
@@ -37,6 +37,8 @@ class Console : public GUI::Debugger {
private:
bool cmd_listsections(int argc, const char **argv);
bool cmd_showsection(int argc, const char **argv);
bool cmd_listmacros(int argc, const char **argv);
bool cmd_showmacro(int argc, const char **argv);

void showIndent(int indentLevel);
void showCommands(Command *command, int indentLevel = 0);
@@ -151,8 +151,7 @@ bool Script::loadFromStream(Common::SeekableReadStream &stream) {
}
}

Common::HashMap<Common::String, Command *> macros;
Common::HashMap<Common::String, Command *> labels;
_macros = parseCtx._macros;

return true;
}
@@ -184,4 +183,8 @@ const ActionInfos &Script::getUseActionInfos() const {
return _useActionInfos;
}

const Macros &Script::getMacros() const {
return _macros;
}

}
@@ -58,6 +58,7 @@ struct ActionInfo {

typedef Common::Array<ActionInfo> ActionInfos;
typedef Common::Array<GotoCommand *> GotoCommands;
typedef Common::HashMap<Common::String, Command *> Macros;

class ScriptParseContext {
public:
@@ -85,6 +86,7 @@ class ScriptParseContext {
PendingGotoMap _pendingGotos;

ActionInfos _actionInfos;
Macros _macros;

private:
};
@@ -98,6 +100,7 @@ class Script {
const ActionInfos &getWalkActionInfos() const;
const ActionInfos &getTalkActionInfos() const;
const ActionInfos &getUseActionInfos() const;
const Macros &getMacros() const;

private:
void destroy();
@@ -106,6 +109,7 @@ class Script {
ActionInfos _walkActionInfos;
ActionInfos _talkActionInfos;
ActionInfos _useActionInfos;
Macros _macros;
};

}

0 comments on commit a1adb9a

Please sign in to comment.