From 18a8b5b3af96bc0d74167db27552956b646cd0d0 Mon Sep 17 00:00:00 2001 From: Denis Kasak Date: Fri, 31 Jul 2009 04:32:33 +0000 Subject: * Added Game::runGateProgram() * Added a separate mechanism to Game to keep track both of the current room number and the next room/gate. Periodically, I check whether the new room differs from the old one and, if it does, I do the change. Doing it any other would is nearly impossible because of the way the original scripts were written. * Added GPL command Script::newRoom(). Rooms can now be traversed by clicking on their exits. Also, the intro animation partly works. Some parts go by far too soon. I assume this is because the engine still lacks a dialogue GPL command. * Fixed bug where the gates array of a room was not cleared between uses. * Save old jump value when we enter Script::run() and restore it in the end (mimicking the original engine). * Fixed small bug where the gate was supposed to be stored as the first in-game variable and not the room number. svn-id: r42957 --- engines/draci/game.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++------ engines/draci/game.h | 7 +++++ engines/draci/script.cpp | 24 +++++++++++++++- engines/draci/script.h | 1 + 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 7b6e3608e7..3665c09d71 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -153,13 +153,31 @@ Game::Game(DraciEngine *vm) : _vm(vm) { void Game::start() { while (!shouldQuit()) { - Game::loop(); + + if (_newRoom != _currentRoom._roomNum) { + + changeRoom(_newRoom); + + _currentRoom._roomNum = _newRoom; + _currentGate = _newGate; + + // HACK: Won't be needed once I've implemented the loop properly + _roomChange = false; + + runGateProgram(_newGate); + } + + loop(); } } void Game::init() { _shouldQuit = false; _shouldExitLoop = false; + + // HACK: Won't be needed once I've implemented the loop properly + _roomChange = false; + _loopStatus = kStatusOrdinary; _objUnderCursor = kOverlayImage; @@ -177,15 +195,20 @@ void Game::init() { _currentRoom._roomNum = _info._startRoom; _currentGate = 0; - _variables[0] = _currentRoom._roomNum; - _variables[1] = _currentGate; + _newRoom = _currentRoom._roomNum; + _newGate = _currentGate; - changeRoom(_info._startRoom); + _variables[0] = _currentGate; + _variables[1] = _currentRoom._roomNum; + + changeRoom(_currentRoom._roomNum); + runGateProgram(_currentGate); } void Game::loop() { - + do { + _vm->handleEvents(); if (_currentRoom._mouseOn) { @@ -235,6 +258,9 @@ void Game::loop() { _vm->_screen->copyToScreen(); _vm->_system->delayMillis(20); + // HACK: Won't be needed once the game loop is implemented properly + _shouldExitLoop = _shouldExitLoop || _roomChange; + } while (!shouldExitLoop()); } @@ -352,10 +378,11 @@ void Game::loadRoom(int roomNum) { debugC(4, kDraciLogicDebugLevel, "Gates: %d", _currentRoom._numGates); // Read in the gates' numbers - Common::Array gates; + + _currentRoom._gates.clear(); for (uint i = 0; i < _currentRoom._numGates; ++i) { - gates.push_back(roomReader.readSint16LE() - 1); + _currentRoom._gates.push_back(roomReader.readSint16LE()); } // Load the room's objects @@ -605,12 +632,39 @@ void Game::changeRoom(uint roomNum) { loadOverlays(); } +void Game::runGateProgram(int gate) { + + // Mark last animation + int lastAnimIndex = _vm->_anims->getLastIndex(); + + // Run gate program + _vm->_script->run(_currentRoom._program, _currentRoom._gates[gate]); + + // Delete all animations loaded after the marked one + // (from objects and from the AnimationManager) + for (uint i = 0; i < getNumObjects(); ++i) { + GameObject *obj = &_objects[i]; + + for (uint j = 0; j < obj->_anims.size(); ++j) { + Animation *anim; + + anim = _vm->_anims->getAnimation(obj->_anims[j]); + if (anim != NULL && anim->getIndex() > lastAnimIndex) + obj->_anims.remove_at(j); + } + } + + _vm->_anims->deleteAfterIndex(lastAnimIndex); + + setExitLoop(false); +} + int Game::getRoomNum() { return _currentRoom._roomNum; } void Game::setRoomNum(int room) { - _currentRoom._roomNum = room; + _newRoom = room; } int Game::getGateNum() { @@ -618,7 +672,7 @@ int Game::getGateNum() { } void Game::setGateNum(int gate) { - _currentGate = gate; + _newGate = gate; } void Game::setLoopStatus(LoopStatus status) { diff --git a/engines/draci/game.h b/engines/draci/game.h index c6168d6d49..1e488ca083 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -131,6 +131,7 @@ struct Room { double _pers0, _persStep; byte _escRoom; byte _numGates; + Common::Array _gates; GPL2Program _program; }; @@ -223,6 +224,10 @@ public: bool shouldExitLoop() { return _shouldExitLoop; } void setExitLoop(bool exit) { _shouldExitLoop = exit; } + void runGateProgram(int gate); + + bool _roomChange; + private: DraciEngine *_vm; @@ -236,6 +241,8 @@ private: Room _currentRoom; int _currentGate; + int _newRoom; + int _newGate; LoopStatus _loopStatus; diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index 8ec9e5f582..78ea91b3f7 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -66,7 +66,7 @@ void Script::setupCommandList() { { 12, 2, "BlackPalette", 0, { 0 }, NULL }, { 13, 1, "FadePalette", 3, { 1, 1, 1 }, NULL }, { 13, 2, "FadePalettePlay", 3, { 1, 1, 1 }, NULL }, - { 14, 1, "NewRoom", 2, { 3, 1 }, NULL }, + { 14, 1, "NewRoom", 2, { 3, 1 }, &Script::newRoom }, { 15, 1, "ExecInit", 1, { 3 }, &Script::execInit }, { 15, 2, "ExecLook", 1, { 3 }, &Script::execLook }, { 15, 3, "ExecUse", 1, { 3 }, &Script::execUse }, @@ -516,6 +516,23 @@ void Script::walkOn(Common::Queue ¶ms) { _vm->_game->walkHero(x, y); } + +void Script::newRoom(Common::Queue ¶ms) { + + if (_vm->_game->getLoopStatus() == kStatusInventory) { + return; + } + + int room = params.pop() - 1; + int gate = params.pop() - 1; + + _vm->_game->setRoomNum(room); + _vm->_game->setGateNum(gate); + + // HACK: Won't be needed once I've implemented the loop properly + _vm->_game->_roomChange = true; +} + /** * @brief Evaluates mathematical expressions * @param reader Stream reader set to the beginning of the expression @@ -679,6 +696,8 @@ const GPL2Command *Script::findCommand(byte num, byte subnum) { int Script::run(GPL2Program program, uint16 offset) { + int oldJump = _jump; + // Mark the last animation index before we do anything so a Release command // doesn't unload too many animations if we forget to use a Mark command first _vm->_game->setMarkedAnimationIndex(_vm->_anims->getLastIndex()); @@ -748,6 +767,7 @@ int Script::run(GPL2Program program, uint16 offset) { else { debugC(1, kDraciBytecodeDebugLevel, "Unknown opcode %d, %d", num, subnum); + abort(); } GPLHandler handler = cmd->_handler; @@ -759,6 +779,8 @@ int Script::run(GPL2Program program, uint16 offset) { } while (cmd->_name != "gplend" && cmd->_name != "exit"); + _jump = oldJump; + return 0; } diff --git a/engines/draci/script.h b/engines/draci/script.h index 69effbedf0..d799dcaed5 100644 --- a/engines/draci/script.h +++ b/engines/draci/script.h @@ -114,6 +114,7 @@ private: void walkOn(Common::Queue ¶ms); void play(Common::Queue ¶ms); void startPlay(Common::Queue ¶ms); + void newRoom(Common::Queue ¶ms); int operAnd(int op1, int op2); int operOr(int op1, int op2); -- cgit v1.2.3