diff options
-rw-r--r-- | engines/mutationofjb/commands/changecommand.cpp | 334 | ||||
-rw-r--r-- | engines/mutationofjb/commands/changecommand.h | 120 | ||||
-rw-r--r-- | engines/mutationofjb/commands/command.h | 2 | ||||
-rw-r--r-- | engines/mutationofjb/commands/ifcommand.cpp | 2 | ||||
-rw-r--r-- | engines/mutationofjb/commands/seqcommand.h | 1 | ||||
-rw-r--r-- | engines/mutationofjb/game.cpp | 18 | ||||
-rw-r--r-- | engines/mutationofjb/game.h | 2 | ||||
-rw-r--r-- | engines/mutationofjb/module.mk | 1 | ||||
-rw-r--r-- | engines/mutationofjb/script.cpp | 5 |
9 files changed, 482 insertions, 3 deletions
diff --git a/engines/mutationofjb/commands/changecommand.cpp b/engines/mutationofjb/commands/changecommand.cpp new file mode 100644 index 0000000000..54c6d1e616 --- /dev/null +++ b/engines/mutationofjb/commands/changecommand.cpp @@ -0,0 +1,334 @@ +/* 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/changecommand.h" +#include "common/translation.h" + +namespace MutationOfJB { + +// CHANGEe rr ss ii val +// <e> 1B Entity to change register for. +// D door +// O object +// S static +// <rr> 2B Register name. +// <ss> 2B Scene ID. +// <ii> 2B Entity ID. +// <val> VL Value. + +bool ChangeCommandParser::parseValueString(const Common::String &valueString, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister ®, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv) { + if (valueString.size() < 8) { + return false; + } + + sceneId = atoi(valueString.c_str() + 3); + entityId = atoi(valueString.c_str() + 6); + const char *val = nullptr; + if (valueString.size() >= 9) { + val = valueString.c_str() + 9; + } + + if (valueString.hasPrefix("NM")) { + reg = ChangeCommand::NM; + op = ChangeCommand::SetValue; + strncpy(ccv._strVal, val, MAX_STR_LENGTH); + } else if (valueString.hasPrefix("LT")) { + reg = ChangeCommand::LT; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("SX")) { + reg = ChangeCommand::SX; + ccv._wordVal = parseInteger(val, op); + } else if (valueString.hasPrefix("SY")) { + reg = ChangeCommand::SY; + ccv._wordVal = parseInteger(val, op); + } else if (valueString.hasPrefix("XX")) { + reg = ChangeCommand::XX; + ccv._wordVal = parseInteger(val, op); + } else if (valueString.hasPrefix("YY")) { + reg = ChangeCommand::YY; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("XL")) { + reg = ChangeCommand::XL; + ccv._wordVal = parseInteger(val, op); + } else if (valueString.hasPrefix("YL")) { + reg = ChangeCommand::YL; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("WX")) { + reg = ChangeCommand::WX; + ccv._wordVal = parseInteger(val, op); + } else if (valueString.hasPrefix("WY")) { + reg = ChangeCommand::WY; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("AC")) { + reg = ChangeCommand::AC; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("FA")) { + reg = ChangeCommand::FA; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("FR")) { + reg = ChangeCommand::FR; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("NA")) { + reg = ChangeCommand::NA; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("FS")) { + reg = ChangeCommand::FS; + ccv._byteVal = parseInteger(val, op); + } else if (valueString.hasPrefix("CA")) { + reg = ChangeCommand::CA; + ccv._byteVal = parseInteger(val, op); + } + + return true; +} + + +bool ChangeDoorCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) { + if (!line.hasPrefix("CHANGED ")) { + return false; + } + uint8 sceneId = 0; + uint8 objectId = 0; + ChangeCommand::ChangeRegister reg; + ChangeCommand::ChangeOperation op; + ChangeCommandValue val; + if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) { + return false; + } + + command = new ChangeObjectCommand(sceneId, objectId, reg, op, val); + return true; +} + +bool ChangeObjectCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) { + if (!line.hasPrefix("CHANGEO ")) { + return false; + } + uint8 sceneId = 0; + uint8 objectId = 0; + ChangeCommand::ChangeRegister reg; + ChangeCommand::ChangeOperation op; + ChangeCommandValue val; + if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) { + return false; + } + + command = new ChangeObjectCommand(sceneId, objectId, reg, op, val); + return true; +} + +bool ChangeStaticCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) { + if (!line.hasPrefix("CHANGES ")) { + return false; + } + uint8 sceneId = 0; + uint8 objectId = 0; + ChangeCommand::ChangeRegister reg; + ChangeCommand::ChangeOperation op; + ChangeCommandValue val; + if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) { + return false; + } + + command = new ChangeObjectCommand(sceneId, objectId, reg, op, val); + return true; +} + +int ChangeCommandParser::parseInteger(const char *val, ChangeCommand::ChangeOperation &op) { + if (!val || !(*val)) { + op = ChangeCommand::SetValue; + return 0; + } + + if (val[0] == '\\') { + op = ChangeCommand::SetValue; + val++; + } else if (val[0] == '+') { + op = ChangeCommand::AddValue; + val++; + } else if (val[0] == '-') { + op = ChangeCommand::SubtractValue; + val++; + } + + return atoi(val); +} + +Command::ExecuteResult ChangeDoorCommand::execute(GameData &gameData) { + Scene *const scene = gameData.getScene(_sceneId); + if (!scene) { + return Finished; + } + + Door *const door = scene->getDoor(_entityId); + if (!door) { + return Finished; + } + + switch (_register) { + case NM: + strncpy(door->_name, _value._strVal, MAX_STR_LENGTH); + break; + case LT: + door->_destSceneId = _value._byteVal; + break; + case SX: + door->_destX = _value._wordVal; + break; + case SY: + door->_destY = _value._wordVal; + break; + case XX: + door->_x = _value._wordVal; + break; + case YY: + door->_y = _value._byteVal; + break; + case XL: + door->_width = _value._wordVal; + break; + case YL: + door->_height = _value._byteVal; + break; + case WX: + door->_walkToX = _value._wordVal; + break; + case WY: + door->_walkToY = _value._byteVal; + break; + case SP: + door->_SP = _value._byteVal; + break; + default: + warning("Object does not support changing this register."); + break; + } + + return Finished; +} + +Command::ExecuteResult ChangeObjectCommand::execute(GameData &gameData) { + Scene *const scene = gameData.getScene(_sceneId); + if (!scene) { + return Finished; + } + + Object *const object = scene->getObject(_entityId); + if (!object) { + return Finished; + } + + switch (_register) { + case AC: + object->_AC = _value._byteVal; + break; + case FA: + object->_FA = _value._byteVal; + break; + case FR: + object->_FR = _value._byteVal; + break; + case NA: + object->_NA = _value._byteVal; + break; + case FS: + object->_FS = _value._byteVal; + break; + case CA: + object->_CA = _value._byteVal; + break; + case XX: + object->_x = _value._wordVal; + break; + case YY: + object->_y = _value._byteVal; + break; + case XL: + object->_XL = _value._wordVal; + break; + case YL: + object->_YL = _value._byteVal; + break; + case WX: + object->_WX = _value._wordVal; + break; + case WY: + object->_WY = _value._byteVal; + break; + case SP: + object->_SP = _value._byteVal; + break; + default: + warning("Object does not support changing this register."); + break; + } + + return Finished; +} + +Command::ExecuteResult ChangeStaticCommand::execute(GameData &gameData) { + Scene *const scene = gameData.getScene(_sceneId); + if (!scene) { + return Finished; + } + + Static *const stat = scene->getStatic(_entityId); + if (!stat) { + return Finished; + } + + switch (_register) { + case AC: + stat->_active = _value._byteVal; + break; + case NM: + strncpy(stat->_name, _value._strVal, MAX_STR_LENGTH); + break; + case XX: + stat->_x = _value._wordVal; + break; + case YY: + stat->_y = _value._byteVal; + break; + case XL: + stat->_width = _value._wordVal; + break; + case YL: + stat->_height = _value._byteVal; + break; + case WX: + stat->_walkToX = _value._wordVal; + break; + case WY: + stat->_walkToY = _value._byteVal; + break; + case SP: + stat->_SP = _value._byteVal; + break; + default: + warning("Object does not support changing this register."); + break; + } + + return Finished; +} +} diff --git a/engines/mutationofjb/commands/changecommand.h b/engines/mutationofjb/commands/changecommand.h new file mode 100644 index 0000000000..5b9a91e47e --- /dev/null +++ b/engines/mutationofjb/commands/changecommand.h @@ -0,0 +1,120 @@ +/* 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/seqcommand.h" +#include "mutationofjb/game.h" + +namespace MutationOfJB { + +union ChangeCommandValue { + uint8 _byteVal; + uint16 _wordVal; + char _strVal[MAX_STR_LENGTH + 1]; +}; + +class ChangeCommand : public SeqCommand { +public: + enum ChangeRegister { + NM, // Name + LT, // Destination scene ID + SX, // Destination X + SY, // Destination Y + XX, // X + YY, // Y + XL, // Width + YL, // Height + WX, // Walk to X + WY, // Walk to Y + SP, // + AC, // Active + FA, // First animation + FR, + NA, + FS, + CA + }; + + enum ChangeOperation { + SetValue, + AddValue, + SubtractValue + }; + + ChangeCommand(uint8 sceneId, uint8 entityId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val) : + _sceneId(sceneId), _entityId(entityId), _register(reg), _operation(op), _value(val) + {} +protected: + uint8 _sceneId; + uint8 _entityId; + ChangeRegister _register; + ChangeOperation _operation; + ChangeCommandValue _value; +}; + +class ChangeCommandParser : public SeqCommandParser { +protected: + bool parseValueString(const Common::String &valueString, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister ®, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv); + int parseInteger(const char *val, ChangeCommand::ChangeOperation &op); +}; + +class ChangeObjectCommandParser : public ChangeCommandParser { +public: + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override; +}; + +class ChangeDoorCommandParser : public ChangeCommandParser { +public: + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override; +}; + +class ChangeStaticCommandParser : public ChangeCommandParser { +public: + virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override; +}; + + + +class ChangeDoorCommand : public ChangeCommand { +public: + ChangeDoorCommand(uint8 sceneId, uint8 doorId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val) + : ChangeCommand(sceneId, doorId, reg, op, val) + {} + virtual ExecuteResult execute(GameData &gameData) override; +}; + +class ChangeObjectCommand : public ChangeCommand { +public: + ChangeObjectCommand(uint8 sceneId, uint8 objectId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val) + : ChangeCommand(sceneId, objectId, reg, op, val) + {} + virtual ExecuteResult execute(GameData &gameData) override; +}; + +class ChangeStaticCommand : public ChangeCommand { +public: + ChangeStaticCommand(uint8 sceneId, uint8 staticId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val) + : ChangeCommand(sceneId, staticId, reg, op, val) + {} + virtual ExecuteResult execute(GameData &gameData) override; +}; + +} diff --git a/engines/mutationofjb/commands/command.h b/engines/mutationofjb/commands/command.h index ab0ebc6da8..f8c160e3cb 100644 --- a/engines/mutationofjb/commands/command.h +++ b/engines/mutationofjb/commands/command.h @@ -36,8 +36,6 @@ class CallMacroCommand; class ScriptParseContext; class Command; -typedef bool (*CommandParseFunc)(const Common::String &line, ScriptParseContext &parseContext, Command *&command); - class CommandParser { public: virtual ~CommandParser(); diff --git a/engines/mutationofjb/commands/ifcommand.cpp b/engines/mutationofjb/commands/ifcommand.cpp index 5ba35bc3ea..8026c841e1 100644 --- a/engines/mutationofjb/commands/ifcommand.cpp +++ b/engines/mutationofjb/commands/ifcommand.cpp @@ -40,7 +40,7 @@ bool IfCommandParser::parse(const Common::String &line, ScriptParseContext &pars return false; } - if (strncmp(line.c_str(), "IF", 2) != 0) { + if (!line.hasPrefix("IF")) { return false; } diff --git a/engines/mutationofjb/commands/seqcommand.h b/engines/mutationofjb/commands/seqcommand.h index 1d21f66948..90e302836e 100644 --- a/engines/mutationofjb/commands/seqcommand.h +++ b/engines/mutationofjb/commands/seqcommand.h @@ -30,6 +30,7 @@ namespace MutationOfJB { class SeqCommandParser : public CommandParser { +public: virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand) override; }; diff --git a/engines/mutationofjb/game.cpp b/engines/mutationofjb/game.cpp index 740fb1cab6..9f517d6608 100644 --- a/engines/mutationofjb/game.cpp +++ b/engines/mutationofjb/game.cpp @@ -143,6 +143,15 @@ bool Scene::loadFromStream(Common::ReadStream &stream) { return true; } +Door *Scene::getDoor(uint8 doorId) { + if (doorId == 0 || doorId > _noDoors) { + warning(_("Door %d does not exist"), doorId); + return nullptr; + } + + return &_doors[doorId - 1]; +} + Object *Scene::getObject(uint8 objectId) { if (objectId == 0 || objectId > _noObjects) { warning(_("Object %d does not exist"), objectId); @@ -152,6 +161,15 @@ Object *Scene::getObject(uint8 objectId) { return &_objects[objectId - 1]; } +Static *Scene::getStatic(uint8 staticId) { + if (staticId == 0 || staticId > _noStatics) { + warning(_("Static %d does not exist"), staticId); + return nullptr; + } + + return &_statics[staticId - 1]; +} + GameData::GameData() : _currentScene(0) {} Scene *GameData::getScene(uint8 sceneId) diff --git a/engines/mutationofjb/game.h b/engines/mutationofjb/game.h index d49a966001..eda178bf8f 100644 --- a/engines/mutationofjb/game.h +++ b/engines/mutationofjb/game.h @@ -93,7 +93,9 @@ struct Bitmap { struct Scene { + Door *getDoor(uint8 objectId); Object *getObject(uint8 objectId); + Static *getStatic(uint8 staticId); uint8 _startup; uint8 _unknown001; diff --git a/engines/mutationofjb/module.mk b/engines/mutationofjb/module.mk index 132d8698aa..16a0c3b06f 100644 --- a/engines/mutationofjb/module.mk +++ b/engines/mutationofjb/module.mk @@ -1,6 +1,7 @@ MODULE := engines/mutationofjb MODULE_OBJS := \ + commands/changecommand.o \ commands/command.o \ commands/conditionalcommand.o \ commands/endblockcommand.o \ diff --git a/engines/mutationofjb/script.cpp b/engines/mutationofjb/script.cpp index a20c11eef0..0deeccbb73 100644 --- a/engines/mutationofjb/script.cpp +++ b/engines/mutationofjb/script.cpp @@ -29,6 +29,7 @@ #include "mutationofjb/commands/command.h" #include "mutationofjb/commands/ifcommand.h" #include "mutationofjb/commands/endblockcommand.h" +#include "mutationofjb/commands/changecommand.h" namespace MutationOfJB { @@ -36,6 +37,9 @@ static CommandParser** getParsers() { static CommandParser* parsers[] = { new IfCommandParser, new EndBlockCommandParser, + new ChangeDoorCommandParser, + new ChangeObjectCommandParser, + new ChangeStaticCommandParser, nullptr }; @@ -101,6 +105,7 @@ bool Script::loadFromStream(Common::SeekableReadStream &stream) { _allCommands.push_back(currentCmd); } + lastCmd = currentCmd; lastParser = currentParser; } |