aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorEugene Sandulenko2010-01-18 00:13:37 +0200
committerEugene Sandulenko2015-12-27 15:39:52 +0100
commit879425385e07e9c8712908066102c0c102e3e40c (patch)
treeaed15387ea2bda02860a63750f4f716b19f91f11 /engines
parente8194a6b79e21eed0647a6358802e8349518872d (diff)
downloadscummvm-rg350-879425385e07e9c8712908066102c0c102e3e40c.tar.gz
scummvm-rg350-879425385e07e9c8712908066102c0c102e3e40c.tar.bz2
scummvm-rg350-879425385e07e9c8712908066102c0c102e3e40c.zip
WAGE: Started implementing script execution.
Signed-off-by: Eugene Sandulenko <sev@scummvm.org>
Diffstat (limited to 'engines')
-rw-r--r--engines/wage/entities.h3
-rw-r--r--engines/wage/script.cpp269
-rw-r--r--engines/wage/script.h85
-rw-r--r--engines/wage/wage.cpp2
-rw-r--r--engines/wage/wage.h29
-rw-r--r--engines/wage/world.cpp4
-rw-r--r--engines/wage/world.h10
7 files changed, 390 insertions, 12 deletions
diff --git a/engines/wage/entities.h b/engines/wage/entities.h
index 4ac63c5adb..f99d6d189a 100644
--- a/engines/wage/entities.h
+++ b/engines/wage/entities.h
@@ -59,6 +59,7 @@ class Scene;
class Script;
class Context {
+public:
enum StatVariables {
/** The base physical accuracy of the player. */
PHYS_ACC_BAS = 0,
@@ -118,6 +119,8 @@ public:
}
void setDesignBounds(Common::Rect *bounds);
+
+ String toString() { return _name; }
};
class Chr : public Designed {
diff --git a/engines/wage/script.cpp b/engines/wage/script.cpp
index 47e00c1261..a478b8bfed 100644
--- a/engines/wage/script.cpp
+++ b/engines/wage/script.cpp
@@ -49,9 +49,278 @@
*/
#include "wage/wage.h"
+#include "wage/entities.h"
#include "wage/script.h"
+#include "wage/world.h"
namespace Wage {
+bool Script::execute(World *world, int loopCount, String *inputText, Designed *inputClick, WageEngine *callbacks) {
+ _world = world;
+ _loopCount = loopCount;
+ _inputText = inputText;
+ _inputClick = inputClick;
+ _callbacks = callbacks;
+ _handled = false;
+
+ _index = 12;
+ while (_index < _dataSize) {
+ switch(_data[_index]) {
+ case 0x80: // IF
+ _index++;
+ processIf();
+ break;
+ case 0x87: // EXIT
+ debug(0, "exit at offset %d", _index - 1);
+
+ return true;
+ case 0x89: // MOVE
+ {
+ _index++;
+ Scene *currentScene = _world->_player->_currentScene;
+ processMove();
+ if (_world->_player->_currentScene != currentScene)
+ return true;
+ break;
+ }
+ case 0x8B: // PRINT
+ {
+ _index++;
+ Operand *op = readOperand();
+ // TODO check op type is string or number, or something good...
+ appendText(op->_str);
+ // TODO check data[_index] == 0xFD
+ _index++;
+ break;
+ }
+ case 0x8C: // SOUND
+ {
+ _index++;
+ Operand *op = readOperand();
+ // TODO check op type is string.
+ _handled = true;
+ callbacks->playSound(op->_str);
+ // TODO check data[_index] == 0xFD
+ _index++;
+ break;
+ }
+ case 0x8E: // LET
+ _index++;
+ processLet();
+ break;
+ case 0x95: // MENU
+ {
+ _index++;
+ Operand *op = readStringOperand(); // allows empty menu
+ // TODO check op type is string.
+ _callbacks->setMenu(op->_str);
+ // TODO check data[_index] == 0xFD
+ _index++;
+ }
+ case 0x88: // END
+ _index++;
+ break;
+ default:
+ debug(0, "Unknown opcode: %d", _index);
+ }
+ }
+
+
+ if (_world->_globalScript != this) {
+ debug(0, "Executing global script...");
+ bool globalHandled = _world->_globalScript->execute(_world, _loopCount, _inputText, _inputClick, _callbacks);
+ if (globalHandled)
+ _handled = true;
+ }
+
+#if 0
+ else if (inputText != null) {
+ String input = inputText.toLowerCase();
+ if (input.equals("n") || input.contains("north")) {
+ handleMoveCommand(Scene.NORTH, "north");
+ } else if (input.equals("e") || input.contains("east")) {
+ handleMoveCommand(Scene.EAST, "east");
+ } else if (input.equals("s") || input.contains("south")) {
+ handleMoveCommand(Scene.SOUTH, "south");
+ } else if (input.equals("w") || input.contains("west")) {
+ handleMoveCommand(Scene.WEST, "west");
+ } else if (input.startsWith("take ")) {
+ handleTakeCommand(input.substring(5));
+ } else if (input.startsWith("get ")) {
+ handleTakeCommand(input.substring(4));
+ } else if (input.startsWith("pick up ")) {
+ handleTakeCommand(input.substring(8));
+ } else if (input.startsWith("drop ")) {
+ handleDropCommand(input.substring(5));
+ } else if (input.startsWith("aim ")) {
+ handleAimCommand(input.substring(4));
+ } else if (input.startsWith("wear ")) {
+ handleWearCommand(input.substring(5));
+ } else if (input.startsWith("put on ")) {
+ handleWearCommand(input.substring(7));
+ } else if (input.startsWith("offer ")) {
+ handleOfferCommand(input.substring(6));
+ } else if (input.contains("look")) {
+ handleLookCommand();
+ } else if (input.contains("inventory")) {
+ handleInventoryCommand();
+ } else if (input.contains("status")) {
+ handleStatusCommand();
+ } else if (input.contains("rest") || input.equals("wait")) {
+ handleRestCommand();
+ } else if (callbacks.getOffer() != null && input.contains("accept")) {
+ handleAcceptCommand();
+ } else {
+ Chr player = world.getPlayer();
+ for (Weapon weapon : player.getWeapons()) {
+ if (tryAttack(weapon, input)) {
+ handleAttack(weapon);
+ break;
+ }
+ }
+ }
+ // TODO: weapons, offer, etc...
+ } else if (inputClick instanceof Obj) {
+ Obj obj = (Obj) inputClick;
+ if (obj.getType() != Obj.IMMOBILE_OBJECT) {
+ takeObj(obj);
+ } else {
+ appendText(obj.getClickMessage());
+ }
+ }
+#endif
+
+ return _handled;
+}
+
+Script::Operand *Script::readOperand() {
+ switch (_data[_index++]) {
+ case 0xA0: // TEXT$
+ return new Operand(_inputText, Operand::TEXT_INPUT);
+ case 0xA1:
+ return new Operand(_inputClick, Operand::CLICK_INPUT);
+ case 0xC0: // STORAGE@
+ return new Operand(&_world->_storageScene, Operand::SCENE);
+ case 0xC1: // SCENE@
+ return new Operand(_world->_player->_currentScene, Operand::SCENE);
+ case 0xC2: // PLAYER@
+ return new Operand(_world->_player, Operand::CHR);
+ case 0xC3: // MONSTER@
+ return new Operand(_callbacks->_monster, Operand::CHR);
+ case 0xC4: // RANDOMSCN@
+ return new Operand(_world->_orderedScenes[_callbacks->_rnd.getRandomNumber(_world->_orderedScenes.size())], Operand::SCENE);
+ case 0xC5: // RANDOMCHR@
+ return new Operand(_world->_orderedChrs[_callbacks->_rnd.getRandomNumber(_world->_orderedChrs.size())], Operand::CHR);
+ case 0xC6: // RANDOMOBJ@
+ return new Operand(_world->_orderedObjs[_callbacks->_rnd.getRandomNumber(_world->_orderedObjs.size())], Operand::OBJ);
+ case 0xB0: // VISITS#
+ return new Operand(_world->_player->_context._visits, Operand::NUMBER);
+ case 0xB1: // RANDOM# for Star Trek, but VISITS# for some other games?
+ return new Operand(1 + _callbacks->_rnd.getRandomNumber(100), Operand::NUMBER);
+ case 0xB5: // RANDOM# // A random number between 1 and 100.
+ return new Operand(1 + _callbacks->_rnd.getRandomNumber(100), Operand::NUMBER);
+ case 0xB2: // LOOP#
+ return new Operand(_loopCount, Operand::NUMBER);
+ case 0xB3: // VICTORY#
+ return new Operand(_world->_player->_context._kills, Operand::NUMBER);
+ case 0xB4: // BADCOPY#
+ return new Operand(0, Operand::NUMBER); // ????
+ case 0xFF:
+ {
+ // user variable
+ int value = _data[_index++];
+ if (value < 0)
+ value += 256;
+
+ // TODO: Verify that we're using the right index.
+ return new Operand(_world->_player->_context._userVariables[value], Operand::NUMBER);
+ }
+ case 0xD0:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_STR_BAS], Operand::NUMBER);
+ case 0xD1:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_HIT_BAS], Operand::NUMBER);
+ case 0xD2:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_ARM_BAS], Operand::NUMBER);
+ case 0xD3:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_ACC_BAS], Operand::NUMBER);
+ case 0xD4:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_STR_BAS], Operand::NUMBER);
+ case 0xD5:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_HIT_BAS], Operand::NUMBER);
+ case 0xD6:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_ARM_BAS], Operand::NUMBER);
+ case 0xD7:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_ACC_BAS], Operand::NUMBER);
+ case 0xD8:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_SPE_BAS], Operand::NUMBER);
+ case 0xE0:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_STR_CUR], Operand::NUMBER);
+ case 0xE1:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_HIT_CUR], Operand::NUMBER);
+ case 0xE2:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_ARM_CUR], Operand::NUMBER);
+ case 0xE3:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_ACC_CUR], Operand::NUMBER);
+ case 0xE4:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_STR_CUR], Operand::NUMBER);
+ case 0xE5:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_HIT_CUR], Operand::NUMBER);
+ case 0xE6:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_ARM_CUR], Operand::NUMBER);
+ case 0xE7:
+ return new Operand(_world->_player->_context._statVariables[Context::SPIR_ACC_CUR], Operand::NUMBER);
+ case 0xE8:
+ return new Operand(_world->_player->_context._statVariables[Context::PHYS_SPE_CUR], Operand::NUMBER);
+ default:
+ _index--;
+ if (_data[_index] >= 0x20 && _data[_index] < 0x80) {
+ return readStringOperand();
+ } else {
+ debug("Dunno what %x is (index=%d)!\n", _data[_index], _index);
+ }
+ _index++;
+ return NULL;
+ }
+}
+
+Script::Operand *Script::readStringOperand() {
+ String *sb;
+ bool allDigits = true;
+
+ sb = new String();
+
+ while (_data[_index] >= 0x20 && _data[_index] < 0x80) {
+ char c = _data[_index++];
+ if (c < '0' || c > '9')
+ allDigits = false;
+ *sb += c;
+ }
+
+ if (allDigits && sb->size() > 0) {
+ debug(0, "Read number %s", sb->c_str());
+ int r = atol(sb->c_str());
+ delete sb;
+
+ return new Operand(r, Operand::NUMBER);
+ } else {
+ // TODO: This string could be a room name or something like that.
+ debug(0, "Read string %s", sb->c_str());
+ return new Operand(sb, Operand::STRING);
+ }
+}
+
+void Script::processIf() {
+}
+
+void Script::processMove() {
+}
+
+void Script::processLet() {
+}
+
+void Script::appendText(String str) {
+ _handled = true;
+ _callbacks->appendText(str);
+}
} // End of namespace Wage
diff --git a/engines/wage/script.h b/engines/wage/script.h
index dcbf4087e7..a5288d66da 100644
--- a/engines/wage/script.h
+++ b/engines/wage/script.h
@@ -55,11 +55,94 @@ namespace Wage {
class Script {
public:
- Script(byte *data) : _data(data) {}
+ Script(byte *data, int dataSize) : _data(data), _dataSize(dataSize) {}
~Script();
private:
byte *_data;
+ int _dataSize;
+
+ WageEngine *_callbacks;
+ World *_world;
+ int _loopCount;
+ String *_inputText;
+ Designed *_inputClick;
+ int _index;
+ bool _evalResult;
+ bool _handled;
+
+ class Operand {
+ public:
+ enum OperandTypes {
+ OBJ = 0,
+ CHR = 1,
+ SCENE = 2,
+ NUMBER = 3,
+ STRING = 4,
+ CLICK_INPUT = 5,
+ TEXT_INPUT = 6
+ };
+
+ union {
+ Obj *obj;
+ Chr *chr;
+ Scene *scene;
+ int16 number;
+ String *string;
+ Designed *inputClick;
+ } _value;
+ OperandTypes _type;
+ String _str;
+
+ Operand(Obj *value, OperandTypes type) {
+ _value.obj = value;
+ _str = value->toString();
+ _type = type;
+ }
+
+ Operand(Chr *value, OperandTypes type) {
+ _value.chr = value;
+ _str = value->toString();
+ _type = type;
+ }
+
+ Operand(Scene *value, OperandTypes type) {
+ _value.scene = value;
+ _str = value->toString();
+ _type = type;
+ }
+
+ Operand(int value, OperandTypes type) {
+ char buf[30];
+ _value.number = value;
+ snprintf(buf, 30, "%d", value);
+ _str = value;
+ _type = type;
+ }
+
+ Operand(String *value, OperandTypes type) {
+ _value.string = value;
+ _str = *value;
+ _type = type;
+ }
+
+ Operand(Designed *value, OperandTypes type) {
+ _value.inputClick = value;
+ _str = value->toString();
+ _type = type;
+ }
+ };
+
+
+ bool execute(World *world, int loopCount, String *inputText, Designed *inputClick, WageEngine *callbacks);
+ Operand *readOperand();
+ Operand *readStringOperand();
+ void processIf();
+ void processMove();
+ void processLet();
+
+ void appendText(String str);
+
};
} // End of namespace Wage
diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp
index a681fc69bb..2be43e7880 100644
--- a/engines/wage/wage.cpp
+++ b/engines/wage/wage.cpp
@@ -64,6 +64,8 @@ namespace Wage {
WageEngine::WageEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc) {
// Don't forget to register your random source
g_eventRec.registerRandomSource(_rnd, "wage");
+
+ _aim = -1;
printf("WageEngine::WageEngine\n");
}
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index 04a505c4ab..5c56d74eb8 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -64,6 +64,9 @@ namespace Wage {
class Console;
class World;
+class Scene;
+class Obj;
+class Chr;
using Common::String;
@@ -95,17 +98,35 @@ public:
private:
bool loadWorld(Common::MacResManager *resMan);
-private:
- Console *_console;
-
+public:
// We need random numbers
Common::RandomSource _rnd;
+ World *_world;
+
+ Scene *_lastScene;
+ //PrintStream out;
+ int _loopCount;
+ int _turn;
+ //Callbacks callbacks;
+ Chr *_monster;
+ Obj *_offer;
+ bool _commandWasQuick;
+ int _aim;
+ bool _temporarilyHidden;
+
+ void playSound(String soundName) {}
+ void setMenu(String soundName) {}
+ void appendText(String str) {}
+
+
+private:
+ Console *_console;
+
const ADGameDescription *_gameDescription;
Common::MacResManager *_resManager;
- World *_world;
};
// Example console class
diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp
index a2cca7cce1..c8ed238be0 100644
--- a/engines/wage/world.cpp
+++ b/engines/wage/world.cpp
@@ -75,7 +75,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {
// Load global script
res = resMan->getResource("GCOD", resArray[0], &resSize);
- _globalScript = new Script(res);
+ _globalScript = new Script(res, resSize);
// Load main configuration
if ((resArray = resMan->getResIDArray("VERS")).size() == 0)
@@ -112,7 +112,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {
res = resMan->getResource("ACOD", *iter, &resSize);
if (res != NULL)
- scene->_script = new Script(res);
+ scene->_script = new Script(res, resSize);
res = resMan->getResource("ATXT", *iter, &resSize);
if (res != NULL) {
diff --git a/engines/wage/world.h b/engines/wage/world.h
index 3ffd607eca..30832a603d 100644
--- a/engines/wage/world.h
+++ b/engines/wage/world.h
@@ -74,11 +74,11 @@ public:
Common::HashMap<String, Obj *> _objs;
Common::HashMap<String, Chr *> _chrs;
Common::HashMap<String, Sound *> _sounds;
- Common::List<Scene *> _orderedScenes;
- Common::List<Obj *> _orderedObjs;
- Common::List<Chr *> _orderedChrs;
- Common::List<Sound *> _orderedSounds;
- Common::List<byte *> _patterns;
+ Common::Array<Scene *> _orderedScenes;
+ Common::Array<Obj *> _orderedObjs;
+ Common::Array<Chr *> _orderedChrs;
+ Common::Array<Sound *> _orderedSounds;
+ Common::Array<byte *> _patterns;
Scene _storageScene;
Chr *_player;
//List<MoveListener> moveListeners;