diff options
| author | uruk | 2014-05-30 11:14:47 +0200 |
|---|---|---|
| committer | uruk | 2014-05-30 11:14:47 +0200 |
| commit | bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d (patch) | |
| tree | 9a1e28cfb1eb1a322225c05adc0962a2f96ea521 /engines | |
| parent | 5ad4e157e5398347651a0da0db07f9daf01bf373 (diff) | |
| parent | 0a46d67baea121bed0511ce45bfdd8438a43d35d (diff) | |
| download | scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.gz scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.tar.bz2 scummvm-rg350-bb2f8dd68e1d6b2b30b07f60c0cd4e125b47ea4d.zip | |
Merge branch 'master' of https://github.com/scummvm/scummvm into cge2
Diffstat (limited to 'engines')
232 files changed, 65247 insertions, 3593 deletions
diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index 5f222adf89..6d7f9384cd 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -32,27 +32,27 @@ namespace Agi { Console::Console(AgiEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("debug", WRAP_METHOD(Console, Cmd_Debug)); - DCmd_Register("cont", WRAP_METHOD(Console, Cmd_Cont)); - DCmd_Register("agiver", WRAP_METHOD(Console, Cmd_Agiver)); - DCmd_Register("flags", WRAP_METHOD(Console, Cmd_Flags)); - DCmd_Register("logic0", WRAP_METHOD(Console, Cmd_Logic0)); - DCmd_Register("objs", WRAP_METHOD(Console, Cmd_Objs)); - DCmd_Register("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode)); - DCmd_Register("opcode", WRAP_METHOD(Console, Cmd_Opcode)); - DCmd_Register("step", WRAP_METHOD(Console, Cmd_Step)); - DCmd_Register("trigger", WRAP_METHOD(Console, Cmd_Trigger)); - DCmd_Register("vars", WRAP_METHOD(Console, Cmd_Vars)); - DCmd_Register("setvar", WRAP_METHOD(Console, Cmd_SetVar)); - DCmd_Register("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); - DCmd_Register("setobj", WRAP_METHOD(Console, Cmd_SetObj)); - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); - DCmd_Register("bt", WRAP_METHOD(Console, Cmd_BT)); + registerCmd("debug", WRAP_METHOD(Console, Cmd_Debug)); + registerCmd("cont", WRAP_METHOD(Console, Cmd_Cont)); + registerCmd("agiver", WRAP_METHOD(Console, Cmd_Agiver)); + registerCmd("flags", WRAP_METHOD(Console, Cmd_Flags)); + registerCmd("logic0", WRAP_METHOD(Console, Cmd_Logic0)); + registerCmd("objs", WRAP_METHOD(Console, Cmd_Objs)); + registerCmd("runopcode", WRAP_METHOD(Console, Cmd_RunOpcode)); + registerCmd("opcode", WRAP_METHOD(Console, Cmd_Opcode)); + registerCmd("step", WRAP_METHOD(Console, Cmd_Step)); + registerCmd("trigger", WRAP_METHOD(Console, Cmd_Trigger)); + registerCmd("vars", WRAP_METHOD(Console, Cmd_Vars)); + registerCmd("setvar", WRAP_METHOD(Console, Cmd_SetVar)); + registerCmd("setflag", WRAP_METHOD(Console, Cmd_SetFlag)); + registerCmd("setobj", WRAP_METHOD(Console, Cmd_SetObj)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("bt", WRAP_METHOD(Console, Cmd_BT)); } bool Console::Cmd_SetVar(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -64,7 +64,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) { bool Console::Cmd_SetFlag(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -76,7 +76,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) { bool Console::Cmd_SetObj(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>\n"); + debugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -88,7 +88,7 @@ bool Console::Cmd_SetObj(int argc, const char **argv) { bool Console::Cmd_RunOpcode(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: runopcode <name> <parameter0> ....\n"); + debugPrintf("Usage: runopcode <name> <parameter0> ....\n"); return true; } @@ -96,7 +96,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { if (!strcmp(argv[1], logicNamesCmd[i].name)) { uint8 p[16]; if ((argc - 2) != logicNamesCmd[i].argumentsLength()) { - DebugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength()); + debugPrintf("AGI command wants %d arguments\n", logicNamesCmd[i].argumentsLength()); return 0; } p[0] = argv[2] ? (char)strtoul(argv[2], NULL, 0) : 0; @@ -113,7 +113,7 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { } } - DebugPrintf("Unknown opcode\n"); + debugPrintf("Unknown opcode\n"); return true; } @@ -125,7 +125,7 @@ bool Console::Cmd_Agiver(int argc, const char **argv) { maj = (ver >> 12) & 0xf; min = ver & 0xfff; - DebugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min); + debugPrintf(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min); return true; } @@ -133,17 +133,17 @@ bool Console::Cmd_Agiver(int argc, const char **argv) { bool Console::Cmd_Flags(int argc, const char **argv) { int i, j; - DebugPrintf(" "); + debugPrintf(" "); for (j = 0; j < 10; j++) - DebugPrintf("%d ", j); - DebugPrintf("\n"); + debugPrintf("%d ", j); + debugPrintf("\n"); for (i = 0; i < 255;) { - DebugPrintf("%3d ", i); + debugPrintf("%3d ", i); for (j = 0; j < 10; j++, i++) { - DebugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F'); + debugPrintf("%c ", _vm->getflag(i) ? 'T' : 'F'); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -154,9 +154,9 @@ bool Console::Cmd_Vars(int argc, const char **argv) { for (i = 0; i < 255;) { for (j = 0; j < 5; j++, i++) { - DebugPrintf("%03d:%3d ", i, _vm->getvar(i)); + debugPrintf("%03d:%3d ", i, _vm->getvar(i)); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -166,7 +166,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) { unsigned int i; for (i = 0; i < _vm->_game.numObjects; i++) { - DebugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i)); + debugPrintf("%3d]%-24s(%3d)\n", i, _vm->objectName(i), _vm->objectGetLocation(i)); } return true; @@ -174,7 +174,7 @@ bool Console::Cmd_Objs(int argc, const char **argv) { bool Console::Cmd_Opcode(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: opcode on|off\n"); + debugPrintf("Usage: opcode on|off\n"); return true; } @@ -185,7 +185,7 @@ bool Console::Cmd_Opcode(int argc, const char **argv) { bool Console::Cmd_Logic0(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: logic0 on|off\n"); + debugPrintf("Usage: logic0 on|off\n"); return true; } @@ -196,7 +196,7 @@ bool Console::Cmd_Logic0(int argc, const char **argv) { bool Console::Cmd_Trigger(int argc, const char **argv) { if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) { - DebugPrintf("Usage: trigger on|off\n"); + debugPrintf("Usage: trigger on|off\n"); return true; } _vm->_debug.ignoretriggers = strcmp (argv[1], "on"); @@ -236,13 +236,13 @@ bool Console::Cmd_Room(int argc, const char **argv) { _vm->newRoom(strtoul(argv[1], NULL, 0)); } - DebugPrintf("Current room: %d\n", _vm->getvar(0)); + debugPrintf("Current room: %d\n", _vm->getvar(0)); return true; } bool Console::Cmd_BT(int argc, const char **argv) { - DebugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size()); + debugPrintf("Current script: %d\nStack depth: %d\n", _vm->_game.lognum, _vm->_game.execStack.size()); uint8 *code = NULL; uint8 op = 0; @@ -257,12 +257,12 @@ bool Console::Cmd_BT(int argc, const char **argv) { memmove(p, &code[it->curIP], num); memset(p + num, 0, CMD_BSIZE - num); - DebugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name); + debugPrintf("%d(%d): %s(", it->script, it->curIP, logicNamesCmd[op].name); for (int i = 0; i < num; i++) - DebugPrintf("%d, ", p[i]); + debugPrintf("%d, ", p[i]); - DebugPrintf(")\n"); + debugPrintf(")\n"); } return true; @@ -271,9 +271,9 @@ bool Console::Cmd_BT(int argc, const char **argv) { MickeyConsole::MickeyConsole(MickeyEngine *mickey) : GUI::Debugger() { _mickey = mickey; - DCmd_Register("room", WRAP_METHOD(MickeyConsole, Cmd_Room)); - DCmd_Register("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic)); - DCmd_Register("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj)); + registerCmd("room", WRAP_METHOD(MickeyConsole, Cmd_Room)); + registerCmd("drawPic", WRAP_METHOD(MickeyConsole, Cmd_DrawPic)); + registerCmd("drawObj", WRAP_METHOD(MickeyConsole, Cmd_DrawObj)); } bool MickeyConsole::Cmd_Room(int argc, const char **argv) { @@ -287,7 +287,7 @@ bool MickeyConsole::Cmd_Room(int argc, const char **argv) { bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Picture number>\n", argv[0]); + debugPrintf("Usage: %s <Picture number>\n", argv[0]); else _mickey->drawPic(atoi(argv[1])); return true; @@ -295,7 +295,7 @@ bool MickeyConsole::Cmd_DrawPic(int argc, const char **argv) { bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Object number>\n", argv[0]); + debugPrintf("Usage: %s <Object number>\n", argv[0]); else _mickey->drawObj((ENUM_MSA_OBJECT)atoi(argv[1]), 0, 0); return true; @@ -304,7 +304,7 @@ bool MickeyConsole::Cmd_DrawObj(int argc, const char **argv) { WinnieConsole::WinnieConsole(WinnieEngine *winnie) : GUI::Debugger() { _winnie = winnie; - DCmd_Register("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom)); + registerCmd("curRoom", WRAP_METHOD(WinnieConsole, Cmd_CurRoom)); } bool WinnieConsole::Cmd_CurRoom(int argc, const char **argv) { diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 561b56d199..4ca8d00824 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -2228,10 +2228,10 @@ void MickeyEngine::waitAnyKey(bool anim) { // Console-related functions void MickeyEngine::debugCurRoom() { - _console->DebugPrintf("Current Room = %d\n", _gameStateMickey.iRoom); + _console->debugPrintf("Current Room = %d\n", _gameStateMickey.iRoom); if (_gameStateMickey.iRmObj[_gameStateMickey.iRoom] != IDI_MSA_OBJECT_NONE) { - _console->DebugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]); + _console->debugPrintf("Object %d is in the room\n", _gameStateMickey.iRmObj[_gameStateMickey.iRoom]); } } diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index d5ae0b59a0..a91ad24fc6 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -1308,7 +1308,7 @@ void WinnieEngine::printStrWinnie(char *szMsg) { // Console-related functions void WinnieEngine::debugCurRoom() { - _console->DebugPrintf("Current Room = %d\n", _room); + _console->debugPrintf("Current Room = %d\n", _room); } WinnieEngine::WinnieEngine(OSystem *syst, const AGIGameDescription *gameDesc) : PreAgiEngine(syst, gameDesc) { diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 7266c75474..6eda2eb9aa 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -21,6 +21,7 @@ */ #include "common/config-manager.h" +#include "common/debug-channels.h" #include "common/file.h" #include "common/fs.h" #include "common/textconsole.h" @@ -144,6 +145,14 @@ AGOSEngine_Elvira1::AGOSEngine_Elvira1(OSystem *system, const AGOSGameDescriptio AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd) : Engine(system), _rnd("agos"), _gameDescription(gd) { + DebugMan.addDebugChannel(kDebugOpcode, "opcode", "Opcode debug level"); + DebugMan.addDebugChannel(kDebugVGAOpcode, "vga_opcode", "VGA Opcode debug level"); + DebugMan.addDebugChannel(kDebugSubroutine, "subroutine", "Subroutine debug level"); + DebugMan.addDebugChannel(kDebugVGAScript, "vga_script", "VGA Script debug level"); + //Image dumping command disabled as it doesn't work well +#if 0 + DebugMan.addDebugChannel(kDebugImageDump, "image_dump", "Enable dumping of images to files"); +#endif _vcPtr = 0; _vcGetOutOfCode = 0; _gameOffsetsPtr = 0; @@ -243,13 +252,6 @@ AGOSEngine::AGOSEngine(OSystem *system, const AGOSGameDescription *gd) _backFlag = false; - _debugMode = 0; - _dumpScripts = false; - _dumpOpcodes = false; - _dumpVgaScripts = false; - _dumpVgaOpcodes = false; - _dumpImages = false; - _copyProtection = false; _pause = false; _speech = false; @@ -675,15 +677,6 @@ Common::Error AGOSEngine::init() { _subtitles = true; } - // TODO: Use special debug levels instead of the following hack. - _debugMode = (gDebugLevel >= 0); - switch (gDebugLevel) { - case 2: _dumpOpcodes = true; break; - case 3: _dumpVgaOpcodes = true; break; - case 4: _dumpScripts = true; break; - case 5: _dumpVgaScripts = true; break; - } - return Common::kNoError; } diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 5e49fce5ff..b6b5e427e1 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -61,6 +61,14 @@ struct Surface; namespace AGOS { +enum { + kDebugOpcode = 1 << 0, + kDebugVGAOpcode = 1 << 1, + kDebugSubroutine = 1 << 2, + kDebugVGAScript = 1 << 3, + kDebugImageDump = 1 << 4 +}; + uint fileReadItemID(Common::SeekableReadStream *in); #define CHECK_BOUNDS(x, y) assert((uint)(x) < ARRAYSIZE(y)) @@ -324,15 +332,9 @@ protected: bool _fastMode; bool _backFlag; - uint16 _debugMode; Common::Language _language; bool _copyProtection; bool _pause; - bool _dumpScripts; - bool _dumpOpcodes; - bool _dumpVgaScripts; - bool _dumpVgaOpcodes; - bool _dumpImages; bool _speech; bool _subtitles; bool _vgaVar9; diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp index 512137b685..7ad742c928 100644 --- a/engines/agos/debugger.cpp +++ b/engines/agos/debugger.cpp @@ -32,44 +32,21 @@ Debugger::Debugger(AGOSEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("level", WRAP_METHOD(Debugger, Cmd_DebugLevel)); - DCmd_Register("music", WRAP_METHOD(Debugger, Cmd_PlayMusic)); - DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); - DCmd_Register("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice)); - DCmd_Register("bit", WRAP_METHOD(Debugger, Cmd_SetBit)); - DCmd_Register("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2)); - DCmd_Register("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3)); - DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_SetVar)); - DCmd_Register("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag)); - DCmd_Register("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine)); - DCmd_Register("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage)); - DCmd_Register("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("music", WRAP_METHOD(Debugger, Cmd_PlayMusic)); + registerCmd("sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); + registerCmd("voice", WRAP_METHOD(Debugger, Cmd_PlayVoice)); + registerCmd("bit", WRAP_METHOD(Debugger, Cmd_SetBit)); + registerCmd("bit2", WRAP_METHOD(Debugger, Cmd_SetBit2)); + registerCmd("bit3", WRAP_METHOD(Debugger, Cmd_SetBit3)); + registerCmd("var", WRAP_METHOD(Debugger, Cmd_SetVar)); + registerCmd("obj", WRAP_METHOD(Debugger, Cmd_SetObjectFlag)); + registerCmd("sub", WRAP_METHOD(Debugger, Cmd_StartSubroutine)); + registerCmd("dumpimage", WRAP_METHOD(Debugger, Cmd_dumpImage)); + registerCmd("dumpscript", WRAP_METHOD(Debugger, Cmd_dumpScript)); } - -bool Debugger::Cmd_DebugLevel(int argc, const char **argv) { - if (argc == 1) { - if (_vm->_debugMode == false) - DebugPrintf("Debugging is not enabled at this time\n"); - else - DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel); - } else { // set level - gDebugLevel = atoi(argv[1]); - if (0 <= gDebugLevel && gDebugLevel < 11) { - _vm->_debugMode = true; - DebugPrintf("Debug level set to level %d\n", gDebugLevel); - } else if (gDebugLevel < 0) { - _vm->_debugMode = false; - DebugPrintf("Debugging is now disabled\n"); - } else - DebugPrintf("Not a valid debug level (0 - 10)\n"); - } - - return true; -} - bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { if (argc > 1) { uint music = atoi(argv[1]); @@ -83,9 +60,9 @@ bool Debugger::Cmd_PlayMusic(int argc, const char **argv) { _vm->playMusic(music, 0); } } else - DebugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic); + debugPrintf("Music out of range (0 - %d)\n", _vm->_numMusic); } else - DebugPrintf("Syntax: music <musicnum>\n"); + debugPrintf("Syntax: music <musicnum>\n"); return true; } @@ -96,9 +73,9 @@ bool Debugger::Cmd_PlaySound(int argc, const char **argv) { if (sound <= _vm->_numSFX) _vm->_sound->playEffects(sound); else - DebugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX); + debugPrintf("Sound out of range (0 - %d)\n", _vm->_numSFX); } else - DebugPrintf("Syntax: sound <soundnum>\n"); + debugPrintf("Syntax: sound <soundnum>\n"); return true; } @@ -109,9 +86,9 @@ bool Debugger::Cmd_PlayVoice(int argc, const char **argv) { if (voice <= _vm->_numSpeech) _vm->_sound->playVoice(voice); else - DebugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech); + debugPrintf("Voice out of range (0 - %d)\n", _vm->_numSpeech); } else - DebugPrintf("Syntax: voice <voicenum>\n"); + debugPrintf("Syntax: voice <voicenum>\n"); return true; } @@ -123,15 +100,15 @@ bool Debugger::Cmd_SetBit(int argc, const char **argv) { value = atoi(argv[2]); if (value <= 1) { _vm->setBitFlag(bit, value != 0); - DebugPrintf("Set bit %d to %d\n", bit, value); + debugPrintf("Set bit %d to %d\n", bit, value); } else - DebugPrintf("Bit value out of range (0 - 1)\n"); + debugPrintf("Bit value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = _vm->getBitFlag(bit); - DebugPrintf("Bit %d is %d\n", bit, value); + debugPrintf("Bit %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit <bitnum> <value>\n"); + debugPrintf("Syntax: bit <bitnum> <value>\n"); return true; } @@ -143,18 +120,18 @@ bool Debugger::Cmd_SetBit2(int argc, const char **argv) { value = atoi(argv[2]); if (value == 0) { _vm->_bitArrayTwo[bit / 16] &= ~(1 << (bit & 15)); - DebugPrintf("Set bit2 %d to %d\n", bit, value); + debugPrintf("Set bit2 %d to %d\n", bit, value); } else if (value == 1) { _vm->_bitArrayTwo[bit / 16] |= (1 << (bit & 15)); - DebugPrintf("Set bit2 %d to %d\n", bit, value); + debugPrintf("Set bit2 %d to %d\n", bit, value); } else - DebugPrintf("Bit2 value out of range (0 - 1)\n"); + debugPrintf("Bit2 value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = (_vm->_bitArrayTwo[bit / 16] & (1 << (bit & 15))) != 0; - DebugPrintf("Bit2 %d is %d\n", bit, value); + debugPrintf("Bit2 %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit2 <bitnum> <value>\n"); + debugPrintf("Syntax: bit2 <bitnum> <value>\n"); return true; } @@ -166,18 +143,18 @@ bool Debugger::Cmd_SetBit3(int argc, const char **argv) { value = atoi(argv[2]); if (value == 0) { _vm->_bitArrayThree[bit / 16] &= ~(1 << (bit & 15)); - DebugPrintf("Set bit3 %d to %d\n", bit, value); + debugPrintf("Set bit3 %d to %d\n", bit, value); } else if (value == 1) { _vm->_bitArrayThree[bit / 16] |= (1 << (bit & 15)); - DebugPrintf("Set bit3 %d to %d\n", bit, value); + debugPrintf("Set bit3 %d to %d\n", bit, value); } else - DebugPrintf("Bit3 value out of range (0 - 1)\n"); + debugPrintf("Bit3 value out of range (0 - 1)\n"); } else if (argc > 1) { bit = atoi(argv[1]); value = (_vm->_bitArrayThree[bit / 16] & (1 << (bit & 15))) != 0; - DebugPrintf("Bit3 %d is %d\n", bit, value); + debugPrintf("Bit3 %d is %d\n", bit, value); } else - DebugPrintf("Syntax: bit3 <bitnum> <value>\n"); + debugPrintf("Syntax: bit3 <bitnum> <value>\n"); return true; } @@ -190,15 +167,15 @@ bool Debugger::Cmd_SetVar(int argc, const char **argv) { if (argc > 2) { value = atoi(argv[2]); _vm->writeVariable(var, value); - DebugPrintf("Set var %d to %d\n", var, value); + debugPrintf("Set var %d to %d\n", var, value); } else { value = _vm->readVariable(var); - DebugPrintf("Var %d is %d\n", var, value); + debugPrintf("Var %d is %d\n", var, value); } } else - DebugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1); + debugPrintf("Var out of range (0 - %d)\n", _vm->_numVars - 1); } else - DebugPrintf("Syntax: var <varnum> <value>\n"); + debugPrintf("Syntax: var <varnum> <value>\n"); return true; } @@ -217,22 +194,22 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) { if (argc > 3) { value = atoi(argv[3]); o->objectFlagValue[offs] = value; - DebugPrintf("Object %d Flag %d set to %d\n", obj, prop, value); + debugPrintf("Object %d Flag %d set to %d\n", obj, prop, value); } else { value = o->objectFlagValue[offs]; - DebugPrintf("Object %d Flag %d is %d\n", obj, prop, value); + debugPrintf("Object %d Flag %d is %d\n", obj, prop, value); } } else { - DebugPrintf("Object flag out of range\n"); + debugPrintf("Object flag out of range\n"); } } else { - DebugPrintf("Item isn't an object\n"); + debugPrintf("Item isn't an object\n"); } } else { - DebugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1); + debugPrintf("Item out of range (1 - %d)\n", _vm->_itemArraySize - 1); } } else { - DebugPrintf("Syntax: obj <itemnum> <flag> <value>\n"); + debugPrintf("Syntax: obj <itemnum> <flag> <value>\n"); } return true; @@ -246,7 +223,7 @@ bool Debugger::Cmd_StartSubroutine(int argc, const char **argv) { if (sub != NULL) _vm->startSubroutine(sub); } else - DebugPrintf("Subroutine %d\n", _vm->_currentTable->id); + debugPrintf("Subroutine %d\n", _vm->_currentTable->id); return true; } @@ -259,11 +236,11 @@ bool Debugger::Cmd_dumpImage(int argc, const char **argv) { if (vpe->vgaFile2 != NULL) { _vm->dumpVgaBitmaps(zoneNum); } else { - DebugPrintf("Invalid Zone Number %d\n", zoneNum); + debugPrintf("Invalid Zone Number %d\n", zoneNum); } } else - DebugPrintf("Syntax: dumpimage <zonenum>\n"); + debugPrintf("Syntax: dumpimage <zonenum>\n"); return true; } @@ -276,11 +253,11 @@ bool Debugger::Cmd_dumpScript(int argc, const char **argv) { if (vpe->vgaFile1 != NULL) { _vm->dumpVgaFile(vpe->vgaFile1); } else { - DebugPrintf("Invalid Zone Number %d\n", zoneNum); + debugPrintf("Invalid Zone Number %d\n", zoneNum); } } else - DebugPrintf("Syntax: dumpscript <zonenum>\n"); + debugPrintf("Syntax: dumpscript <zonenum>\n"); return true; } diff --git a/engines/agos/debugger.h b/engines/agos/debugger.h index caac6e2caf..026194410f 100644 --- a/engines/agos/debugger.h +++ b/engines/agos/debugger.h @@ -37,7 +37,6 @@ public: private: AGOSEngine *_vm; - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_PlayMusic(int argc, const char **argv); bool Cmd_PlaySound(int argc, const char **argv); bool Cmd_PlayVoice(int argc, const char **argv); diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 6e97084811..33145b7d0d 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -20,6 +20,7 @@ * */ +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -1129,7 +1130,7 @@ void AGOSEngine::animate(uint16 windowNum, uint16 zoneNum, uint16 vgaSpriteId, i assert(READ_BE_UINT16(&((AnimationHeader_WW *) p)->id) == vgaSpriteId); } - if (_dumpVgaScripts) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) { if (getGameType() == GType_FF || getGameType() == GType_PP) { dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((AnimationHeader_Feeble*)p)->scriptOffs), zoneNum, vgaSpriteId); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { @@ -1235,7 +1236,7 @@ void AGOSEngine::setImage(uint16 vgaSpriteId, bool vgaScript) { } } - if (_dumpVgaScripts) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAScript)) { if (getGameType() == GType_FF || getGameType() == GType_PP) { dumpVgaScript(_curVgaFile1 + READ_LE_UINT16(&((ImageHeader_Feeble*)b)->scriptOffs), zoneNum, vgaSpriteId); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp index 6f809d9e2d..1dbb9c255a 100644 --- a/engines/agos/script.cpp +++ b/engines/agos/script.cpp @@ -22,6 +22,7 @@ // Item script opcodes for Simon1/Simon2 +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -987,7 +988,7 @@ int AGOSEngine::runScript() { return 1; do { - if (_dumpOpcodes) + if (DebugMan.isDebugChannelEnabled(kDebugOpcode)) dumpOpcode(_codePtr); if (getGameType() == GType_ELVIRA1) { diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index 39bc468dea..1e6ecaa829 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -20,8 +20,7 @@ * */ - - +#include "common/debug-channels.h" #include "common/file.h" #include "common/textconsole.h" @@ -531,7 +530,7 @@ int AGOSEngine::startSubroutine(Subroutine *sub) { _classMode1 = 0; _classMode2 = 0; - if (_dumpScripts) + if (DebugMan.isDebugChannelEnabled(kDebugSubroutine)) dumpSubroutine(sub); if (++_recursionDepth > 40) @@ -564,8 +563,7 @@ restart: else _codePtr += 8; - if (_dumpOpcodes) - debug("; %d", sub->id); + debugC(kDebugOpcode, "; %d", sub->id); result = runScript(); if (result != 0) { break; diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index c656c0167a..f761c3fc3f 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -27,6 +27,7 @@ #include "agos/intern.h" #include "agos/vga.h" +#include "common/debug-channels.h" #include "common/endian.h" #include "common/system.h" #include "common/textconsole.h" @@ -152,7 +153,7 @@ void AGOSEngine::runVgaScript() { for (;;) { uint opcode; - if (_dumpVgaOpcodes) { + if (DebugMan.isDebugChannelEnabled(kDebugVGAOpcode)) { if (_vcPtr != (const byte *)&_vcGetOutOfCode) { debugN("%.5d %.5X: %5d %4d ", _vgaTickCounter, (unsigned int)(_vcPtr - _curVgaFile1), _vgaCurSpriteId, _vgaCurZoneNum); dumpVideoScript(_vcPtr, true); @@ -381,8 +382,7 @@ void AGOSEngine::vcSkipNextInstruction() { _vcPtr += opcodeParamLenPN[opcode]; } - if (_dumpVgaOpcodes) - debugN("; skipped\n"); + debugCN(kDebugVGAOpcode, "; skipped\n"); } // VGA Script commands @@ -648,7 +648,7 @@ void AGOSEngine::drawImage_init(int16 image, uint16 palette, int16 x, int16 y, u if (height == 0 || width == 0) return; - if (_dumpImages) + if (DebugMan.isDebugChannelEnabled(kDebugImageDump)) dumpSingleBitmap(_vgaCurZoneNum, state.image, state.srcPtr, width, height, state.palette); state.width = state.draw_width = width; /* cl */ diff --git a/engines/avalanche/console.cpp b/engines/avalanche/console.cpp index 29ae5cf9c3..d4923affc1 100644 --- a/engines/avalanche/console.cpp +++ b/engines/avalanche/console.cpp @@ -31,7 +31,7 @@ namespace Avalanche { AvalancheConsole::AvalancheConsole(AvalancheEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines)); + registerCmd("magic_lines", WRAP_METHOD(AvalancheConsole, Cmd_MagicLines)); } AvalancheConsole::~AvalancheConsole() { @@ -42,7 +42,7 @@ AvalancheConsole::~AvalancheConsole() { */ bool AvalancheConsole::Cmd_MagicLines(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/avalanche/ghostroom.cpp b/engines/avalanche/ghostroom.cpp index 16c79fdee0..047a3670c2 100644 --- a/engines/avalanche/ghostroom.cpp +++ b/engines/avalanche/ghostroom.cpp @@ -49,6 +49,9 @@ GhostRoom::GhostRoom(AvalancheEngine *vm) { _greldetCount = 0; _redGreldet = false; _wasLoaded = false; + + _ghost = nullptr; + _glerk = nullptr; } GhostRoom::~GhostRoom() { diff --git a/engines/cge/console.cpp b/engines/cge/console.cpp index 447875c06f..e926e89506 100644 --- a/engines/cge/console.cpp +++ b/engines/cge/console.cpp @@ -26,7 +26,7 @@ namespace CGE { CGEConsole::CGEConsole(CGEEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries)); + registerCmd("Boundaries", WRAP_METHOD(CGEConsole, Cmd_boundaries)); } CGEConsole::~CGEConsole() { @@ -37,7 +37,7 @@ CGEConsole::~CGEConsole() { */ bool CGEConsole::Cmd_boundaries(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/cine/console.cpp b/engines/cine/console.cpp index 82197693d4..4646bdf280 100644 --- a/engines/cine/console.cpp +++ b/engines/cine/console.cpp @@ -29,7 +29,7 @@ bool labyrinthCheat; CineConsole::CineConsole(CineEngine *vm) : GUI::Debugger(), _vm(vm) { assert(_vm); - DCmd_Register("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat)); + registerCmd("labyrinthCheat", WRAP_METHOD(CineConsole, Cmd_LabyrinthCheat)); labyrinthCheat = false; } diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index f6419ecafc..b9175cac72 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -1902,7 +1902,9 @@ void maskBgOverlay(const byte *bgPtr, const byte *maskPtr, int16 width, int16 he destPtr++; srcPtr++; - maskPtr++; + + if (maskPtr) + maskPtr++; } } diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp index f3985c691e..18f260cab7 100644 --- a/engines/cine/pal.cpp +++ b/engines/cine/pal.cpp @@ -332,9 +332,9 @@ byte *Palette::save(byte *buf, const uint size, const Graphics::PixelFormat form // Save the palette to the output in the specified format for (uint i = firstIndex; i < firstIndex + numColors; i++) { - const uint r = (_colors[i].r * rNewMax) / rOrigMax; - const uint g = (_colors[i].g * gNewMax) / gOrigMax; - const uint b = (_colors[i].b * bNewMax) / bOrigMax; + const uint r = (_colors[i].r * rNewMax) / (rOrigMax == 0 ? 1 : rOrigMax); + const uint g = (_colors[i].g * gNewMax) / (gOrigMax == 0 ? 1 : gOrigMax); + const uint b = (_colors[i].b * bNewMax) / (bOrigMax == 0 ? 1 : bOrigMax); buf[i * format.bytesPerPixel + rBytePos] |= r << (format.rShift % 8); buf[i * format.bytesPerPixel + gBytePos] |= g << (format.gShift % 8); diff --git a/engines/cruise/debugger.cpp b/engines/cruise/debugger.cpp index 4ef66ee11e..d4e706a094 100644 --- a/engines/cruise/debugger.cpp +++ b/engines/cruise/debugger.cpp @@ -29,9 +29,9 @@ namespace Cruise { Debugger::Debugger(): GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); - DCmd_Register("items", WRAP_METHOD(Debugger, cmd_items)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); + registerCmd("items", WRAP_METHOD(Debugger, cmd_items)); } /** @@ -70,7 +70,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (*pObjectName) { getMultipleObjectParam(currentObject->overlay, currentObject->idx, ¶ms); - DebugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y); + debugPrintf("%s %s - %d,%d\n", pObjectName, pObjType, params.X, params.Y); } } @@ -96,7 +96,7 @@ bool Debugger::cmd_items(int argc, const char **argv) { getSingleObjectParam(i, j, 5, &returnVar); if (returnVar < -1) - DebugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj)); + debugPrintf("%s\n", getObjectName(j, pOvlData->arrayNameObj)); } } } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 4893b0fe34..4fbf2d31ea 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -50,44 +50,46 @@ enum { }; Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { - uint i; - _dialogueLinesNum = 0; _blockNum = 0; - for (i = 0; i < kDialogueLines; i++) - _dialogueAnims[0] = 0; + for (uint i = 0; i < kDialogueLines; i++) + _dialogueAnims[0] = nullptr; _loopStatus = kStatusOrdinary; _loopSubstatus = kOuterLoop; - _shouldQuit = 0; - _shouldExitLoop = 0; - _isReloaded = 0; _speechTick = 0; _speechDuration = 0; - _objUnderCursor = 0; - _animUnderCursor = 0; _markedAnimationIndex = 0; _scheduledPalette = 0; _fadePhases = 0; _fadePhase = 0; _fadeTick = 0; - _isFadeOut = 1; _mouseChangeTick = 0; - _enableQuickHero = 0; - _wantQuickHero = 0; - _enableSpeedText = 0; - _titleAnim = 0; - _inventoryAnim = 0; - _walkingMapOverlay = 0; - _walkingShortestPathOverlay = 0; - _walkingObliquePathOverlay = 0; - _currentItem = 0; - _itemUnderCursor = 0; _previousItemPosition = 0; - for (i = 0; i < kInventorySlots; i++) - _inventory[i] = 0; + _shouldQuit = false; + _shouldExitLoop = false; + _isReloaded = false; + _isPositionLoaded = false; + _isFadeOut = true; + _enableQuickHero = false; + _wantQuickHero = false; + _enableSpeedText = false; + _isPositionLoaded = false; + + _objUnderCursor = nullptr; + _animUnderCursor = nullptr; + _titleAnim = nullptr; + _inventoryAnim = nullptr; + _walkingMapOverlay = nullptr; + _walkingShortestPathOverlay = nullptr; + _walkingObliquePathOverlay = nullptr; + _currentItem = nullptr; + _itemUnderCursor = nullptr; + + for (int i = 0; i < kInventorySlots; i++) + _inventory[i] = nullptr; _newRoom = 0; _newGate = 0; @@ -95,10 +97,10 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _pushedNewRoom = 0; _pushedNewGate = 0; _currentDialogue = 0; - _dialogueArchive = 0; - _dialogueBlocks = 0; - _dialogueBegin = 0; - _dialogueExit = 0; + _dialogueArchive = nullptr; + _dialogueBlocks = nullptr; + _dialogueBegin = false; + _dialogueExit = false; _currentBlock = 0; _lastBlock = 0; @@ -113,7 +115,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { uint numPersons = file->_length / personSize; _persons = new Person[numPersons]; - for (i = 0; i < numPersons; ++i) { + for (uint i = 0; i < numPersons; ++i) { _persons[i]._x = personData.readUint16LE(); _persons[i]._y = personData.readUint16LE(); _persons[i]._fontColor = personData.readByte(); @@ -126,9 +128,9 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { uint numDialogues = file->_length / sizeof(uint16); _dialogueOffsets = new uint[numDialogues]; - uint curOffset; - for (i = 0, curOffset = 0; i < numDialogues; ++i) { - _dialogueOffsets[i] = curOffset; + uint curOffset, idx; + for (idx = 0, curOffset = 0; idx < numDialogues; ++idx) { + _dialogueOffsets[idx] = curOffset; curOffset += dialogueData.readUint16LE(); } @@ -163,7 +165,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _variables = new int[numVariables]; Common::MemoryReadStream variableData(file->_data, file->_length); - for (i = 0; i < numVariables; ++i) { + for (uint i = 0; i < numVariables; ++i) { _variables[i] = variableData.readUint16LE(); } @@ -181,7 +183,7 @@ Game::Game(DraciEngine *vm) : _vm(vm), _walkingState(vm) { _objects = new GameObject[numObjects]; Common::MemoryReadStream objStatus(file->_data, file->_length); - for (i = 0; i < numObjects; ++i) { + for (uint i = 0; i < numObjects; ++i) { byte tmp = objStatus.readByte(); // Set object visibility @@ -251,14 +253,14 @@ void Game::init() { setLoopStatus(kStatusGate); setLoopSubstatus(kOuterLoop); - _animUnderCursor = NULL; + _animUnderCursor = nullptr; - _currentItem = _itemUnderCursor = NULL; + _currentItem = _itemUnderCursor = nullptr; _previousItemPosition = -1; _vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor - _objUnderCursor = NULL; + _objUnderCursor = nullptr; // Set the inventory to empty initially memset(_inventory, 0, kInventorySlots * sizeof(GameItem *)); @@ -402,12 +404,12 @@ void Game::handleInventoryLoop() { // an overlay, for which we check. Item animations have their IDs // calculated by offseting their itemID from the ID of the last "special" // animation ID. In this way, we obtain its itemID. - if (_animUnderCursor != NULL && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) { + if (_animUnderCursor != nullptr && _animUnderCursor != _inventoryAnim && _animUnderCursor->getID() != kOverlayImage) { _itemUnderCursor = getItem(kInventoryItemsID - _animUnderCursor->getID()); - assert(_itemUnderCursor != NULL); + assert(_itemUnderCursor != nullptr); assert(_itemUnderCursor->_anim == _animUnderCursor); } else { - _itemUnderCursor = NULL; + _itemUnderCursor = nullptr; } // If the user pressed the left mouse button @@ -824,7 +826,7 @@ void Game::removeItem(GameItem *item) { return; for (uint i = 0; i < kInventorySlots; ++i) { if (_inventory[i] == item) { - _inventory[i] = NULL; + _inventory[i] = nullptr; item->_anim->stop(); break; } @@ -931,7 +933,7 @@ void Game::inventoryDone() { _walkingState.callbackLast(); // Reset item under cursor - _itemUnderCursor = NULL; + _itemUnderCursor = nullptr; // Don't start the inventory mode again if the mouse is on the top. _mouseChangeTick = kMouseDoNotSwitch; @@ -1640,7 +1642,7 @@ void Game::DoSync(Common::Serializer &s, uint8 saveVersion) { _currentItem = getItem(handItemID); } } else { - _currentItem = 0; + _currentItem = nullptr; } } diff --git a/engines/draci/walking.cpp b/engines/draci/walking.cpp index 6914898ec1..04cd929ac6 100644 --- a/engines/draci/walking.cpp +++ b/engines/draci/walking.cpp @@ -453,7 +453,7 @@ void WalkingState::callback() { _callback = NULL; _vm->_script->runWrapper(originalCallback, _callbackOffset, true, false); _callbackLast = NULL; - _callbackOffset = NULL; + _callbackOffset = 0; } void WalkingState::callbackLast() { diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp index 50e96c8757..b545c096d0 100644 --- a/engines/drascula/console.cpp +++ b/engines/drascula/console.cpp @@ -27,7 +27,7 @@ namespace Drascula { Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); } Console::~Console() { @@ -35,7 +35,7 @@ Console::~Console() { bool Console::Cmd_Room(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: room <number>\n"); + debugPrintf("Usage: room <number>\n"); return true; } diff --git a/engines/fullpipe/console.cpp b/engines/fullpipe/console.cpp index cb76345d66..dd3d1bf693 100644 --- a/engines/fullpipe/console.cpp +++ b/engines/fullpipe/console.cpp @@ -28,14 +28,14 @@ namespace Fullpipe { Console::Console(FullpipeEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene)); + registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene)); } bool Console::Cmd_Scene(int argc, const char **argv) { if (argc != 2) { int sceneTag = _vm->_currentScene->_sceneId; - DebugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag); - DebugPrintf("Use %s <scene> to change the current scene\n", argv[0]); + debugPrintf("Current scene: %d (scene tag: %d)\n", _vm->getSceneFromTag(sceneTag), sceneTag); + debugPrintf("Use %s <scene> to change the current scene\n", argv[0]); return true; } else { int scene = _vm->convertScene(atoi(argv[1])); diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp index 62c5dd3b80..de0ed04d25 100644 --- a/engines/fullpipe/detection.cpp +++ b/engines/fullpipe/detection.cpp @@ -26,6 +26,7 @@ #include "common/file.h" #include "fullpipe/fullpipe.h" +#include "fullpipe/gameloader.h" namespace Fullpipe { @@ -87,15 +88,72 @@ public: } virtual bool hasFeature(MetaEngineFeature f) const; + virtual int getMaximumSaveSlot() const { return 8; } + virtual SaveStateList listSaves(const char *target) const; + virtual void removeSaveState(const char *target, int slot) const; + virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; }; bool FullpipeMetaEngine::hasFeature(MetaEngineFeature f) const { - return false; + return + (f == kSupportsListSaves) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail) || + (f == kSavesSupportCreationDate) || + (f == kSupportsLoadingDuringStartup); } -bool Fullpipe::FullpipeEngine::hasFeature(EngineFeature f) const { - return false; +SaveStateList FullpipeMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String pattern("fullpipe.s??"); + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..) + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + // Obtain the last 2 digits of the filename, since they correspond to the save slot + int slotNum = atoi(file->c_str() + file->size() - 2); + + if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) { + Common::InSaveFile *in = saveFileMan->openForLoading(*file); + if (in) { + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); + delete header.thumbnail; + delete in; + } + } + } + + return saveList; +} + +void FullpipeMetaEngine::removeSaveState(const char *target, int slot) const { + g_system->getSavefileManager()->removeSavefile(Fullpipe::getSavegameFile(slot)); +} + +SaveStateDescriptor FullpipeMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + Fullpipe::getSavegameFile(slot)); + + if (f) { + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setThumbnail(header.thumbnail); + + return desc; + } + + return SaveStateDescriptor(); } bool FullpipeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index 5369c05de7..85a5167841 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -37,6 +37,7 @@ #include "fullpipe/scenes.h" #include "fullpipe/floaters.h" #include "fullpipe/console.h" +#include "fullpipe/constants.h" namespace Fullpipe { @@ -205,7 +206,39 @@ void FullpipeEngine::initialize() { } void FullpipeEngine::restartGame() { - warning("STUB: FullpipeEngine::restartGame()"); + _floaters->stopAll(); + + clearGlobalMessageQueueList(); + clearMessages(); + + initObjectStates(); + + if (_scene2) { + _scene2->getAniMan(); + _scene2 = 0; + } + + if (_currentScene) { + _gameLoader->unloadScene(_currentScene->_sceneId); + + _currentScene = 0; + } + + _gameLoader->restoreDefPicAniInfos(); + + getGameLoaderInventory()->clear(); + getGameLoaderInventory()->addItem(ANI_INV_MAP, 1); + getGameLoaderInventory()->rebuildItemRects(); + + initMap(); + + if (_flgPlayIntro) { + _gameLoader->loadScene(SC_INTRO1); + _gameLoader->gotoScene(SC_INTRO1, TrubaUp); + } else { + _gameLoader->loadScene(SC_1); + _gameLoader->gotoScene(SC_1, TrubaLeft); + } } Common::Error FullpipeEngine::run() { @@ -347,7 +380,7 @@ void FullpipeEngine::updateEvents() { case Common::EVENT_QUIT: _gameContinue = false; break; - case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: if (!_inputArFlag && (_updateTicks - _lastInputTicks) >= 2) { ex = new ExCommand(0, 17, 107, event.mouse.x, event.mouse.y, 0, 1, 0, 0, 0); ex->_excFlags |= 3; @@ -477,7 +510,20 @@ void FullpipeEngine::setObjectState(const char *name, int state) { } void FullpipeEngine::disableSaves(ExCommand *ex) { - warning("STUB: FullpipeEngine::disableSaves()"); + if (_isSaveAllowed) { + _isSaveAllowed = false; + + if (_globalMessageQueueList->size() && (*_globalMessageQueueList)[0] != 0) { + for (int i = 0; i < _globalMessageQueueList->size(); i++) { + if ((*_globalMessageQueueList)[i]->_flags & 1) + if ((*_globalMessageQueueList)[i]->_id != ex->_parId && !(*_globalMessageQueueList)[i]->_isFinished) + return; + } + } + + if (_currentScene) + _gameLoader->writeSavegame(_currentScene, "savetmp.sav"); + } } diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 27505252ab..afdc493258 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -99,7 +99,6 @@ public: const ADGameDescription *_gameDescription; const char *getGameId() const; Common::Platform getPlatform() const; - bool hasFeature(EngineFeature f) const; Common::RandomSource *_rnd; diff --git a/engines/fullpipe/gameloader.cpp b/engines/fullpipe/gameloader.cpp index d9f7327a6b..c8b01939dd 100644 --- a/engines/fullpipe/gameloader.cpp +++ b/engines/fullpipe/gameloader.cpp @@ -21,6 +21,7 @@ */ #include "fullpipe/fullpipe.h" +#include "graphics/thumbnail.h" #include "fullpipe/gameloader.h" #include "fullpipe/scene.h" @@ -501,6 +502,14 @@ void GameLoader::updateSystems(int counterdiff) { } } +void GameLoader::readSavegame(const char *fname) { + warning("STUB: readSavegame(%s)", fname); +} + +void GameLoader::writeSavegame(Scene *sc, const char *fname) { + warning("STUB: writeSavegame(sc, %s)", fname); +} + Sc2::Sc2() { _sceneId = 0; _field_2 = 0; @@ -593,6 +602,42 @@ bool PreloadItems::load(MfcArchive &file) { return true; } +const char *getSavegameFile(int saveGameIdx) { + static char buffer[20]; + sprintf(buffer, "fullpipe.s%02d", saveGameIdx); + return buffer; +} + +bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header) { + char saveIdentBuffer[6]; + header.thumbnail = NULL; + + // Validate the header Id + in->read(saveIdentBuffer, 6); + if (strcmp(saveIdentBuffer, "SVMCR")) + return false; + + header.version = in->readByte(); + if (header.version != FULLPIPE_SAVEGAME_VERSION) + return false; + + // Read in the string + header.saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header.saveName += ch; + + // Get the thumbnail + header.thumbnail = Graphics::loadThumbnail(*in); + if (!header.thumbnail) + return false; + + return true; +} + +void GameLoader::restoreDefPicAniInfos() { + warning("STUB: restoreDefPicAniInfos()"); +} + GameVar *FullpipeEngine::getGameLoaderGameVar() { if (_gameLoader) return _gameLoader->_gameVar; diff --git a/engines/fullpipe/gameloader.h b/engines/fullpipe/gameloader.h index a79c0e11b4..772cc51130 100644 --- a/engines/fullpipe/gameloader.h +++ b/engines/fullpipe/gameloader.h @@ -29,6 +29,8 @@ namespace Fullpipe { +#define FULLPIPE_SAVEGAME_VERSION 1 + class SceneTag; class MctlCompound; class InputController; @@ -72,6 +74,12 @@ class PreloadItems : public Common::Array<PreloadItem *>, public CObject { virtual bool load(MfcArchive &file); }; +struct FullpipeSavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; +}; + class GameLoader : public CObject { public: GameLoader(); @@ -89,6 +97,11 @@ class GameLoader : public CObject { void applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount); void saveScenePicAniInfos(int sceneId); + void readSavegame(const char *fname); + void writeSavegame(Scene *sc, const char *fname); + + void restoreDefPicAniInfos(); + GameProject *_gameProject; InteractionController *_interactionController; InputController *_inputController; @@ -108,6 +121,9 @@ class GameLoader : public CObject { int _preloadEntranceId; }; +const char *getSavegameFile(int saveGameIdx); +bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header); + Inventory2 *getGameLoaderInventory(); InteractionController *getGameLoaderInteractionController(); MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId); diff --git a/engines/fullpipe/gfx.cpp b/engines/fullpipe/gfx.cpp index 7c66a9a747..520e81835b 100644 --- a/engines/fullpipe/gfx.cpp +++ b/engines/fullpipe/gfx.cpp @@ -145,7 +145,7 @@ void Background::addPictureObject(PictureObject *pct) { bool inserted = false; for (uint i = 1; i < _picObjList.size(); i++) { - if (((PictureObject *)_picObjList[i])->_priority <= pct->_priority) { + if (_picObjList[i]->_priority <= pct->_priority) { _picObjList.insert_at(i, pct); inserted = true; break; @@ -192,7 +192,7 @@ bool PictureObject::load(MfcArchive &file, bool bigPicture) { _picture->load(file); - _pictureObject2List = new PtrList(); + _pictureObject2List = new Common::Array<GameObject *>; int count = file.readUint16LE(); @@ -351,7 +351,25 @@ void GameObject::setOXY(int x, int y) { _oy = y; } -void GameObject::renumPictures(PtrList *lst) { +void GameObject::renumPictures(Common::Array<StaticANIObject *> *lst) { + int *buf = (int *)calloc(lst->size() + 2, sizeof(int)); + + for (uint i = 0; i < lst->size(); i++) { + if (_id == ((GameObject *)((*lst)[i]))->_id) + buf[((GameObject *)((*lst)[i]))->_okeyCode] = 1; + } + + if (buf[_okeyCode]) { + uint count; + for (count = 1; buf[count] && count < lst->size() + 2; count++) + ; + _okeyCode = count; + } + + free(buf); +} + +void GameObject::renumPictures(Common::Array<PictureObject *> *lst) { int *buf = (int *)calloc(lst->size() + 2, sizeof(int)); for (uint i = 0; i < lst->size(); i++) { @@ -380,6 +398,7 @@ bool GameObject::getPicAniInfo(PicAniInfo *info) { info->ox = _ox; info->oy = _oy; info->priority = _priority; + warning("Yep %d", _id); return true; } diff --git a/engines/fullpipe/gfx.h b/engines/fullpipe/gfx.h index b3e22b610b..191df7709a 100644 --- a/engines/fullpipe/gfx.h +++ b/engines/fullpipe/gfx.h @@ -92,7 +92,7 @@ class Picture : public MemoryObject { virtual bool load(MfcArchive &file); void setAOIDs(); - void init(); + virtual void init(); void getDibInfo(); Bitmap *getPixelData(); virtual void draw(int x, int y, int style, int angle); @@ -141,7 +141,8 @@ class GameObject : public CObject { virtual bool load(MfcArchive &file); void setOXY(int x, int y); - void renumPictures(PtrList *lst); + void renumPictures(Common::Array<StaticANIObject *> *lst); + void renumPictures(Common::Array<PictureObject *> *lst); void setFlags(int16 flags) { _flags = flags; } void clearFlags() { _flags = 0; } const char *getName() { return _objectName; } @@ -153,7 +154,7 @@ class GameObject : public CObject { class PictureObject : public GameObject { public: Picture *_picture; - PtrList *_pictureObject2List; + Common::Array<GameObject *> *_pictureObject2List; int _ox2; int _oy2; @@ -178,7 +179,7 @@ class PictureObject : public GameObject { class Background : public CObject { public: - PtrList _picObjList; + Common::Array<PictureObject *> _picObjList; char *_bgname; int _x; diff --git a/engines/fullpipe/messagehandlers.cpp b/engines/fullpipe/messagehandlers.cpp index 15aa78d342..d4f79d1dd8 100644 --- a/engines/fullpipe/messagehandlers.cpp +++ b/engines/fullpipe/messagehandlers.cpp @@ -392,12 +392,10 @@ int global_messageHandler3(ExCommand *cmd) { } return result; case 29: - if (!g_fp->_currentScene) - return result; - - if (g_fp->_gameLoader->_interactionController->_flag24) { + if (g_fp->_gameLoader->_interactionController->_flag24 && g_fp->_currentScene) { ani = g_fp->_currentScene->getStaticANIObjectAtPos(cmd->_sceneClickX, cmd->_sceneClickY); ani2 = g_fp->_currentScene->getStaticANIObject1ById(g_fp->_gameLoader->_field_FA, -1); + if (ani) { if (g_fp->_msgObjectId2 == ani->_id && g_fp->_msgId == ani->_okeyCode) { cmd->_messageKind = 0; diff --git a/engines/fullpipe/messages.cpp b/engines/fullpipe/messages.cpp index 8257d1459f..b643ff9b8f 100644 --- a/engines/fullpipe/messages.cpp +++ b/engines/fullpipe/messages.cpp @@ -26,6 +26,7 @@ #include "fullpipe/messages.h" #include "fullpipe/modal.h" #include "fullpipe/statics.h" +#include "fullpipe/gameloader.h" namespace Fullpipe { @@ -394,8 +395,18 @@ void MessageQueue::update() { } void MessageQueue::messageQueueCallback1(int par) { - // Autosave - debug(3, "STUB: MessageQueue::messageQueueCallback1()"); + if (g_fp->_isSaveAllowed && par == 16) { + if (g_fp->_globalMessageQueueList->size() && (*g_fp->_globalMessageQueueList)[0] != 0) { + for (int i = 0; i < g_fp->_globalMessageQueueList->size(); i++) { + if ((*g_fp->_globalMessageQueueList)[i]->_flags & 1) + if ((*g_fp->_globalMessageQueueList)[i] != this && !(*g_fp->_globalMessageQueueList)[i]->_isFinished) + return; + } + } + + if (g_fp->_currentScene) + g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, "savetmp.sav"); + } } void MessageQueue::addExCommand(ExCommand *ex) { diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp index bba5df0cd5..8981cdb8e6 100644 --- a/engines/fullpipe/modal.cpp +++ b/engines/fullpipe/modal.cpp @@ -34,6 +34,8 @@ #include "graphics/palette.h" #include "video/avi_decoder.h" +#include "engines/savestate.h" + namespace Fullpipe { ModalIntro::ModalIntro() { @@ -1084,17 +1086,17 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) { b = 800 - dx; } - int32 pp = b * a; //(0x51EB851F * b * a) >> 32) >> 8; // TODO FIXME + int32 pp = b * a; - snd->setPanAndVolume(pan + (pp >> 31) + pp, par); + snd->setPanAndVolume(pan + pp / 800, par); return; } int dx = _screct.left - ani->_ox; if (dx <= 800) { - int32 s = 0x51EB851F * (800 - dx) * (g_fp->_sfxVolume - (-3500)); // TODO FIXME - int32 p = -3500 + (s >> 31) + (s >> 8); + int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500)); + int32 p = -3500 + s / 800; if (p > g_fp->_sfxVolume) p = g_fp->_sfxVolume; @@ -1103,8 +1105,6 @@ void ModalMainMenu::updateSoundVolume(Sound *snd) { } else { snd->setPanAndVolume(-3500, 0); } - - warning("STUB: ModalMainMenu::updateSoundVolume()"); } void ModalMainMenu::updateSliderPos() { @@ -1460,6 +1460,8 @@ ModalSaveGame::ModalSaveGame() { _rect = g_fp->_sceneRect; _queryDlg = 0; _mode = 1; + + _objtype = kObjTypeModalSaveGame; } ModalSaveGame::~ModalSaveGame() { @@ -1591,9 +1593,9 @@ void ModalSaveGame::setup(Scene *sc, int mode) { fileinfo = new FileInfo; memset(fileinfo, 0, sizeof(FileInfo)); - snprintf(fileinfo->filename, 160, "save%02d.sav", i); + strncpy(fileinfo->filename, getSavegameFile(i), 160); - if (!getFileInfo(fileinfo->filename, fileinfo)) { + if (!getFileInfo(i, fileinfo)) { fileinfo->empty = true; w = _emptyD->getDimensions(&point)->x; } else { @@ -1623,12 +1625,175 @@ char *ModalSaveGame::getSaveName() { return _files[_queryRes]->filename; } -bool ModalSaveGame::getFileInfo(char *filename, FileInfo *fileinfo) { - warning("STUB: ModalSaveGame::getFileInfo()"); +bool ModalSaveGame::getFileInfo(int slot, FileInfo *fileinfo) { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + Fullpipe::getSavegameFile(slot)); + + if (!f) + return false; + + Fullpipe::FullpipeSavegameHeader header; + Fullpipe::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + char res[17]; + + snprintf(res, 17, "%s %s", desc.getSaveDate().c_str(), desc.getSaveTime().c_str()); + + for (int i = 0; i < 16; i++) { + switch(res[i]) { + case '.': + fileinfo->date[i] = 11; + break; + case ' ': + fileinfo->date[i] = 12; + break; + case ':': + fileinfo->date[i] = 10; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + fileinfo->date[i] = res[i] - '0'; + break; + default: + error("Incorrect date format: %s", res); + } + } + + return true; +} + +void ModalSaveGame::update() { + if (_menuScene) + _menuScene->draw(); + + _bgr->draw(); + + if (_queryDlg) { + _queryDlg->update(); + + return; + } + + g_fp->_cursorId = PIC_CSR_DEFAULT; + + g_fp->setCursor(g_fp->_cursorId); + + Common::Point point; + + for (uint i = 0; i < _files.size(); i++) { + if (g_fp->_mouseScreenPos.x < _files[i]->fx1 || g_fp->_mouseScreenPos.x > _files[i]->fx2 || + g_fp->_mouseScreenPos.y < _files[i]->fy1 || g_fp->_mouseScreenPos.y > _files[i]->fy2 ) { + if (_files[i]->empty) { + _emptyD->setOXY(_files[i]->fx1, _files[i]->fy1); + _emptyD->draw(); + } else { + int x = _files[i]->fx1; + + for (int j = 0; j < 16; j++) { + _arrayL[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1); + _arrayL[_files[i]->date[j]]->draw(); + + x += _arrayL[_files[i]->date[j]]->getDimensions(&point)->x + 2; + } + } + } else { + if (_files[i]->empty) { + _emptyL->setOXY(_files[i]->fx1, _files[i]->fy1); + _emptyL->draw(); + } else { + int x = _files[i]->fx1; + + for (int j = 0; j < 16; j++) { + _arrayD[_files[i]->date[j]]->setOXY(x + 1, _files[i]->fy1); + _arrayD[_files[i]->date[j]]->draw(); + + x += _arrayD[_files[i]->date[j]]->getDimensions(&point)->x + 2; + } + } + } + } + if (_cancelL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _cancelL->draw(); + else if (_okL->isPixelHitAtPos(g_fp->_mouseScreenPos.x, g_fp->_mouseScreenPos.y)) + _okL->draw(); +} + +bool ModalSaveGame::handleMessage(ExCommand *cmd) { + if (_queryDlg) + return _queryDlg->handleMessage(cmd); + + if (cmd->_messageNum == 29) + processMouse(cmd->_x, cmd->_y); + else if (cmd->_messageNum == 36) + processKey(cmd->_keyCode); return false; } +void ModalSaveGame::processMouse(int x, int y) { + for (uint i = 0; i < _files.size(); i++) { + if (x >= _files[i]->fx1 && x <= _files[i]->fx2 && y >= _files[i]->fy1 && y <= _files[i]->fy2) { + _queryRes = i + 1; + + if (_mode) { + if (!_files[i]->empty) { + _queryDlg = new ModalQuery; + + _queryDlg->create(_menuScene, 0, PIC_MOV_BGR); + } + } + + return; + } + } + + if (_cancelL->isPixelHitAtPos(x, y)) + _queryRes = 0; +} + +void ModalSaveGame::saveload() { + if (_objtype != kObjTypeModalSaveGame) + return; + + if (_mode) { + if (getSaveName()) { + bool allowed = true; + + for (Common::Array<MessageQueue *>::iterator s = g_fp->_globalMessageQueueList->begin(); s != g_fp->_globalMessageQueueList->end(); ++s) { + if (!(*s)->_isFinished && ((*s)->getFlags() & 1)) + allowed = false; + } + + if (g_fp->_isSaveAllowed && allowed) + g_fp->_gameLoader->writeSavegame(g_fp->_currentScene, getSaveName()); + } + } else { + if (getSaveName()) { + if (_parentObj) { + delete _parentObj; + + _parentObj = 0; + } + + g_fp->stopAllSoundStreams(); + g_fp->stopSoundStream2(); + + g_fp->_gameLoader->readSavegame(getSaveName()); + } + } +} + void FullpipeEngine::openHelp() { if (!_modalObject) { ModalHelp *help = new ModalHelp; diff --git a/engines/fullpipe/modal.h b/engines/fullpipe/modal.h index a214b1c639..01d8e6b0ee 100644 --- a/engines/fullpipe/modal.h +++ b/engines/fullpipe/modal.h @@ -32,10 +32,7 @@ class Sound; struct FileInfo { char filename[260]; bool empty; - int day; - int month; - int year; - int time; + char date[16]; int fx1; int fx2; int fy1; @@ -46,9 +43,10 @@ class BaseModalObject { public: BaseModalObject *_parentObj; + ObjType _objtype; public: - BaseModalObject() : _parentObj(0) {} + BaseModalObject() : _parentObj(0) { _objtype = kObjTypeDefault; } virtual ~BaseModalObject() {} @@ -256,17 +254,19 @@ public: virtual ~ModalSaveGame(); virtual bool pollEvent() { return true; } - virtual bool handleMessage(ExCommand *message) { return false; } + virtual bool handleMessage(ExCommand *message); virtual bool init(int counterdiff); - virtual void update() {} - virtual void saveload() {} + virtual void update(); + virtual void saveload(); + + void processMouse(int x, int y); void setScene(Scene *sc); void setup(Scene *sc, int mode); void processKey(int key); char *getSaveName(); - bool getFileInfo(char *filename, FileInfo *fileinfo); + bool getFileInfo(int slot, FileInfo *fileinfo); Common::Rect _rect; int _oldBgX; diff --git a/engines/fullpipe/motion.cpp b/engines/fullpipe/motion.cpp index 35da154570..5b7419c7f4 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -125,9 +125,10 @@ void MctlCompound::addObject(StaticANIObject *obj) { } int MctlCompound::removeObject(StaticANIObject *obj) { - warning("STUB: MctlCompound::removeObject()"); + for (uint i = 0; i < _motionControllers.size(); i++) + _motionControllers[i]->_motionControllerObj->removeObject(obj); - return 0; + return 1; } void MctlCompound::initMovGraph2() { @@ -193,7 +194,8 @@ MessageQueue *MctlCompound::method34(StaticANIObject *ani, int sourceX, int sour if (idx == sourceIdx) return _motionControllers[idx]->_motionControllerObj->method34(ani, sourceX, sourceY, fuzzyMatch, staticsId); - MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &sourceIdx); + double dist; + MctlConnectionPoint *cp = findClosestConnectionPoint(ani->_ox, ani->_oy, idx, sourceX, sourceY, sourceIdx, &dist); if (!cp) return 0; @@ -261,7 +263,8 @@ MessageQueue *MctlCompound::doWalkTo(StaticANIObject *subj, int xpos, int ypos, if (match1 == match2) return _motionControllers[match1]->_motionControllerObj->doWalkTo(subj, xpos, ypos, fuzzyMatch, staticsId); - MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &match2); + double dist; + MctlConnectionPoint *closestP = findClosestConnectionPoint(subj->_ox, subj->_oy, match1, xpos, ypos, match2, &dist); if (!closestP) return 0; @@ -427,14 +430,75 @@ MessageQueue *MctlLadder::controllerWalkTo(StaticANIObject *ani, int off) { return doWalkTo(ani, _ladderX + off * _width, _ladderY + off * _height, 1, 0); } -MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr) { +MctlConnectionPoint *MctlCompound::findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr) { +#if 0 + if (destIndex == sourceIndex) { + *minDistancePtr = sqrt((double)((oy - connectionY) * (oy - connectionY) + (ox - connectionX) * (ox - connectionX))); + + return 0; + } + + v11 = this->_motionControllers.m_pData; + currDistance = 0.0; + v12 = 0; + v13 = (MctlCompoundArrayItem *)*(&v11->vmt + sourceIndex); + minDistance = 1.0e10; + minConnectionPoint = 0; + if (v13->mctlConnectionPointsArray.CObArray.m_nSize > 0) { + do { + v14 = 0; + for (currMctlIndex = 0; v14 < this->_motionControllers.m_nSize; currMctlIndex = v14) { + v15 = this->_motionControllers.m_pData; + v16 = *(MovGraphReact **)(*(&v15->vmt + v14) + offsetof(MctlCompoundArrayItem, movGraphReactObj)); + if (v16) { + v17 = *(MctlConnectionPoint **)(*(_DWORD *)(*(&v15->vmt + sourceIndex) + 0x10) + 4 * v12);// MctlCompoundArrayItem.mctlConnectionPointsArray.CObArray.m_pData + LOBYTE(v18) = (*(bool (__thiscall **)(MovGraphReact *, int, int))(v16->CObject.vmt + offsetof(MovGraphReactVmt, pointInRegion)))(v16, v17->_connectionX, v17->_connectionY); + if (v18) { + v14 = currMctlIndex; + v19 = *(MctlConnectionPoint **)(*(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x10) + 4 * v12); + v20 = MctlCompound_findClosestConnectionPoint(this, ox, oy, destIndex, v19->_connectionX, v19->_connectionY, currMctlIndex, (int *)&currDistance); + if (currDistance < minDistance) { + minDistance = currDistance; + if (v20) + minConnectionPoint = v20; + else + minConnectionPoint = *(MctlConnectionPoint **)(*(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x10) + 4 * v12); + } + } else { + v14 = currMctlIndex; + } + } + ++v14; + } + ++v12; + } while (v12 < *(_DWORD *)(*(&this->_motionControllers.m_pData->vmt + sourceIndex) + 0x14)); // MctlCompoundArrayItem.mctlConnectionPointsArray.CObArray.m_nSize + } + + *minDistancePtr = minDistance; + + return minConnectionPoint; +} +#endif warning("STUB: MctlCompound::findClosestConnectionPoint()"); return 0; } void MctlCompound::replaceNodeX(int from, int to) { - warning("STUB: MctlCompound::replaceNodeX()"); + for (uint i = 0; i < _motionControllers.size(); i++) { + if (_motionControllers[i]->_motionControllerObj->_objtype == kObjTypeMovGraph) { + MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj; + + for (ObList::iterator n = gr->_nodes.begin(); n != gr->_nodes.end(); ++n) { + MovGraphNode *node = (MovGraphNode *)*n; + + if (node->_x == from) + node->_x = to; + } + + gr->calcNodeDistancesAndAngles(); + } + } } MctlConnectionPoint::MctlConnectionPoint() { @@ -493,15 +557,7 @@ bool MctlCompoundArray::load(MfcArchive &file) { MovGraphItem::MovGraphItem() { ani = 0; field_4 = 0; - field_8 = 0; - field_C = 0; - field_10 = 0; - field_14 = 0; - field_18 = 0; - field_1C = 0; - field_20 = 0; - field_24 = 0; - items = 0; + movitems = 0; count = 0; field_30 = 0; field_34 = 0; @@ -509,16 +565,36 @@ MovGraphItem::MovGraphItem() { field_3C = 0; } +void MovGraphItem::free() { + for (uint i = 0; i < movitems->size(); i++) { + (*movitems)[i]->movarr->_movSteps.clear(); + delete (*movitems)[i]->movarr; + } + + delete movitems; + + movitems = 0; +} + int MovGraph_messageHandler(ExCommand *cmd); -int MovGraphCallback(int a1, int a2, int a3) { - warning("STUB: MovgraphCallback"); +MovArr *movGraphCallback(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter) { + int residx = 0; + int itemidx = 0; - return 0; + while (counter > 1) { + if ((*items)[itemidx]->_mfield_4 > (*items)[itemidx + 1]->_mfield_4) + residx = itemidx; + + counter--; + itemidx++; + } + + return (*items)[residx]->movarr; } MovGraph::MovGraph() { - _callback1 = MovGraphCallback; + _callback1 = movGraphCallback; _field_44 = 0; insertMessageHandler(MovGraph_messageHandler, getMessageHandlersCount() - 1, 129); @@ -562,54 +638,482 @@ int MovGraph::removeObject(StaticANIObject *obj) { } void MovGraph::freeItems() { - warning("STUB: MovGraph::freeItems()"); + for (uint i = 0; i < _items.size(); i++) { + _items[i]->free(); + + _items[i]->movarr._movSteps.clear(); + } + + _items.clear(); } +Common::Array<MovItem *> *MovGraph::method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { + *rescount = 0; + + if (_items.size() <= 0) + return 0; + + int idx = 0; -int MovGraph::method28() { - warning("STUB: MovGraph::method28()"); + while (_items[idx]->ani != ani) { + idx++; + + if (idx >= _items.size()) + return 0; + } + _items[idx]->free(); + + calcNodeDistancesAndAngles(); + + _items[idx]->movarr._movSteps.clear(); + + Common::Point point; + + point.x = ani->_ox; + point.y = ani->_oy; + + if (!calcChunk(idx, ani->_ox, ani->_oy, &_items[idx]->movarr, 0)) + findClosestLink(idx, &point, &_items[idx]->movarr); + + _items[idx]->count = 0; + + delete _items[idx]->movitems; + _items[idx]->movitems = 0; + + int arrSize; + Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, flag1, 0); + + if (movarr) { + for (int i = 0; i < arrSize; i++) { + int sz; + Common::Array<MovItem *> *movitems = calcMovItems(&_items[idx]->movarr, (*movarr)[i], &sz); + + if (sz > 0) { + for (uint j = 0; j < sz; j++) + _items[idx]->movitems->push_back(movitems[j]); + + delete movitems; + } + } + + delete movarr; + } + + if (_items[idx]->count) { + *rescount = _items[idx]->count; + + return _items[idx]->movitems; + } return 0; } -int MovGraph::method2C(StaticANIObject *obj, int x, int y) { +bool MovGraph::method2C(StaticANIObject *obj, int x, int y) { obj->setOXY(x, y); return method3C(obj, 1); } -MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - warning("STUB: MovGraph::method34()"); +MessageQueue *MovGraph::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { + if (!ani) { + if (!_items.size()) + return 0; - return 0; -} + ani = _items[0]->ani; + } + + if (ABS(ani->_ox - xpos) < 50 && ABS(ani->_oy - ypos) < 50) + return 0; -int MovGraph::changeCallback() { - warning("STUB: MovGraph::changeCallback()"); + if (!ani->isIdle()) + return 0; - return 0; + if (ani->_flags & 0x100) + return 0; + + int count; + Common::Array<MovItem *> *movitems = method28(ani, xpos, ypos, fuzzyMatch, &count); + + if (!movitems) + return 0; + + if (ani->_movement) { + Common::Point point; + + ani->calcStepLen(&point); + + MessageQueue *mq = sub1(ani, ani->_ox - point.x, ani->_oy - point.y, ani->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch); + + if (!mq || !mq->getExCommandByIndex(0)) + return 0; + + ExCommand *ex = mq->getExCommandByIndex(0); + + if ((ex->_messageKind != 1 && ex->_messageKind != 20) || ex->_messageNum != ani->_movement->_id || + (ex->_field_14 >= 1 && ex->_field_14 <= ani->_movement->_currDynamicPhaseIndex)) { + mq = new MessageQueue(g_fp->_globalMessageQueueList->compact()); + + ex = new ExCommand(ani->_id, 21, 0, 0, 0, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_field_3C = 1; + ex->_field_24 = 0; + mq->addExCommandToEnd(ex); + + ex = new ExCommand(ani->_id, 51, 0, xpos, ypos, 0, 1, 0, 0, 0); + ex->_keyCode = ani->_okeyCode; + ex->_field_3C = 1; + ex->_field_24 = 0; + ex->_field_20 = fuzzyMatch; + mq->addExCommandToEnd(ex); + + if (mq->chain(0)) + return mq; + + delete mq; + + return 0; + } + + int count2; + + ani->setSomeDynamicPhaseIndex(ex->_field_14); + method28(ani, xpos, ypos, fuzzyMatch, &count2); + + int idx = getItemIndexByStaticAni(ani); + count = _items[idx]->count; + movitems = _items[idx]->movitems; + } + + return method50(ani, _callback1(ani, movitems, count), staticsId); } -int MovGraph::method3C(StaticANIObject *ani, int flag) { - warning("STUB: MovGraph::method3C()"); +void MovGraph::changeCallback(MovArr *(*callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) { + _callback1 = callback1; +} - return 0; +bool MovGraph::method3C(StaticANIObject *ani, int flag) { + int idx = getItemIndexByStaticAni(ani); + + if (idx == -1) + return false; + + Common::Point point; + MovArr movarr; + + point.x = ani->_ox; + point.y = ani->_oy; + + findClosestLink(idx, &point, &movarr); + ani->setOXY(point.x, point.y); + + if (flag) { + Statics *st; + + if (ani->_statics) { + int t = _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44]); + if (t > _mgm.refreshOffsets(ani->_id, ani->_statics->_staticsId, movarr._link->_dwordArray2[_field_44 + 1])) + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44 + 1]); + else + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]); + } else { + ani->stopAnim_maybe(); + st = ani->getStaticsById(movarr._link->_dwordArray2[_field_44]); + } + + ani->_statics = st; + } + + return true; } -int MovGraph::method44() { - warning("STUB: MovGraph::method44()"); +bool MovGraph::method44(StaticANIObject *ani, int x, int y) { + int idx = getItemIndexByStaticAni(ani); + MovArr m; - return 0; + if (idx != -1) { + if (x != -1 || y != -1) { + int counter; + + Common::Array<MovItem *> *movitem = method28(ani, x, y, 0, &counter); + + if (movitem) { + MovArr *movarr = _callback1(ani, movitem, counter); + int cnt = movarr->_movStepCount; + + if (cnt > 0) { + if (movarr->_movSteps[cnt - 1]->link->_flags & 0x4000000) + return true; + } + } + } else if (calcChunk(idx, ani->_ox, ani->_oy, &m, 0) && m._link && (m._link->_flags & 0x4000000)) { + return true; + } + } + + return false; } MessageQueue *MovGraph::doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { - warning("STUB: MovGraph::doWalkTo()"); + PicAniInfo picAniInfo; + int ss; + + Common::Array<MovItem *> *movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss); + + subj->getPicAniInfo(&picAniInfo); + + if (movitem) { + MovArr *goal = _callback1(subj, movitem, ss); + int idx = getItemIndexByStaticAni(subj); + + for (int i = 0; i < _items[idx]->count; i++) { + if ((*_items[idx]->movitems)[i]->movarr == goal) { + if (subj->_movement) { + Common::Point point; + + subj->calcStepLen(&point); + + MessageQueue *mq = sub1(subj, subj->_ox - point.x, subj->_oy - point.y, subj->_movement->_staticsObj1->_staticsId, xpos, ypos, 0, fuzzyMatch); + + if (!mq || !mq->getExCommandByIndex(0)) + return 0; + + ExCommand *ex = mq->getExCommandByIndex(0); + + if ((ex->_messageKind != 1 && ex->_messageKind != 20) || + ex->_messageNum != subj->_movement->_id || + (ex->_field_14 >= 1 && ex->_field_14 <= subj->_movement->_currDynamicPhaseIndex)) + subj->playIdle(); + } + } + } + } + + movitem = method28(subj, xpos, ypos, fuzzyMatch, &ss); + if (movitem) { + MovArr *goal = _callback1(subj, movitem, ss); + int idx = getItemIndexByStaticAni(subj); + + if (_items[idx]->count > 0) { + int arridx = 0; + + while ((*_items[idx]->movitems)[arridx]->movarr != goal) { + arridx++; + + if (arridx >= _items[idx]->count) { + subj->setPicAniInfo(&picAniInfo); + return 0; + } + } + + _items[idx]->movarr._movSteps.clear(); + _items[idx]->movarr = *(*_items[idx]->movitems)[arridx]->movarr; + _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[arridx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, staticsId); + if (mq) { + ExCommand *ex = new ExCommand(); + ex->_messageKind = 17; + ex->_messageNum = 54; + ex->_parentId = subj->_id; + ex->_field_3C = 1; + mq->addExCommandToEnd(ex); + } + subj->setPicAniInfo(&picAniInfo); + + return mq; + } + } + + subj->setPicAniInfo(&picAniInfo); return 0; } -int MovGraph::method50() { - warning("STUB: MovGraph::method50()"); +MessageQueue *MovGraph::sub1(StaticANIObject *ani, int x, int y, int stid, int x1, int y1, int stid2, int flag1) { + PicAniInfo picinfo; - return 0; + ani->getPicAniInfo(&picinfo); + + ani->_statics = ani->getStaticsById(stid); + ani->_movement = 0; + ani->setOXY(x, y); + + int rescount; + + Common::Array<MovItem *> *movitems = method28(ani, x1, y1, flag1, &rescount); + + if (!movitems) { + ani->setPicAniInfo(&picinfo); + + return 0; + } + + MessageQueue *res = 0; + + MovArr *goal = _callback1(ani, movitems, rescount); + int idx = getItemIndexByStaticAni(ani); + + MovGraphItem *movgitem = _items[idx]; + int cnt = movgitem->count; + + for (int nidx = 0; nidx < cnt; nidx++) { + if ((*movgitem->movitems)[nidx]->movarr == goal) { + movgitem->movarr._movSteps.clear(); + _items[idx]->movarr = *(*movgitem->movitems)[nidx]->movarr; + _items[idx]->movarr._movSteps = (*movgitem->movitems)[nidx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + res = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, stid2); + } + } + + ani->setPicAniInfo(&picinfo); + + return res; +} + +MessageQueue *MovGraph::fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId) { + if (!movarr->_movStepCount) + return 0; + + MessageQueue *mq = 0; + int ox = ani->_ox; + int oy = ani->_oy; + int id1 = 0; + int id2; + + for (int i = 0; i < movarr->_movStepCount; i++) { + while (i < movarr->_movStepCount - 1) { + if (movarr->_movSteps[i ]->link->_dwordArray1[movarr->_movSteps[i - 1]->sfield_0 + _field_44] != + movarr->_movSteps[i + 1]->link->_dwordArray1[movarr->_movSteps[i ]->sfield_0 + _field_44]) + break; + i++; + } + + MovStep *st = movarr->_movSteps[i]; + + ani->getMovementById(st->link->_dwordArray1[_field_44 + st->sfield_0]); + + if (i == movarr->_movStepCount - 1 && staticsId) { + id2 = staticsId; + } else { + if (i < movarr->_movStepCount - 1) + id2 = ani->getMovementById(movarr->_movSteps[i + 1]->link->_dwordArray1[_field_44 + st->sfield_0])->_staticsObj1->_staticsId; + else + id2 = st->link->_dwordArray2[_field_44 + st->sfield_0]; + } + + int nx, ny, nd; + + if (i == movarr->_movStepCount - 1) { + nx = movarr->_point.x; + ny = movarr->_point.y; + nd = st->link->_movGraphNode1->_distance; + } else { + if (st->sfield_0) { + nx = st->link->_movGraphNode1->_x; + ny = st->link->_movGraphNode1->_y; + nd = st->link->_movGraphNode1->_distance; + } else { + nx = st->link->_movGraphNode2->_x; + ny = st->link->_movGraphNode2->_y; + nd = st->link->_movGraphNode2->_distance; + } + } + + MGMInfo mgminfo; + + memset(&mgminfo, 0, sizeof(mgminfo)); + mgminfo.ani = ani; + mgminfo.staticsId2 = id2; + mgminfo.staticsId1 = id1; + mgminfo.x1 = nx; + mgminfo.x2 = ox; + mgminfo.y2 = oy; + mgminfo.y1 = ny; + mgminfo.field_1C = nd; + mgminfo.movementId = st->link->_dwordArray1[_field_44 + st->sfield_0]; + + mgminfo.flags = 0xe; + if (mq) + mgminfo.flags |= 0x31; + + MessageQueue *newmq = _mgm.genMovement(&mgminfo); + + if (mq) { + if (newmq) { + mq->transferExCommands(newmq); + + delete newmq; + } + } else { + mq = newmq; + } + + ox = nx; + oy = ny; + id1 = id2; + } + + return mq; +} + +MessageQueue *MovGraph::method50(StaticANIObject *ani, MovArr *movarr, int staticsId) { + if (_items.size() == 0) + return 0; + + uint idx; + int movidx; + bool done = false; + + for (idx = 0; idx <= _items.size() && !done; idx++) { + if (idx == _items.size()) + return 0; + + if (_items[idx]->ani == ani) { + if (!_items[idx]->movitems) + return 0; + + if (_items[idx]->count < 1) + return 0; + + for (movidx = 0; movidx < _items[idx]->count; movidx++) { + if ((*_items[idx]->movitems)[movidx]->movarr == movarr) { + done = true; + + break; + } + } + } + } + + _items[idx]->movarr._movSteps.clear(); + _items[idx]->movarr = *(*_items[idx]->movitems)[movidx]->movarr; + _items[idx]->movarr._movSteps = (*_items[idx]->movitems)[movidx]->movarr->_movSteps; + _items[idx]->movarr._afield_8 = -1; + _items[idx]->movarr._link = 0; + + MessageQueue *mq = fillMGMinfo(_items[idx]->ani, &_items[idx]->movarr, 0); + + if (!mq) + return 0; + + ExCommand *ex = new ExCommand(); + + ex->_messageKind = 17; + ex->_messageNum = 54; + ex->_parentId = ani->_id; + ex->_field_3C = 1; + mq->addExCommandToEnd(ex); + + if (!mq->chain(ani)) { + delete mq; + + return 0; + } + + return mq; } double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch) { @@ -660,6 +1164,61 @@ void MovGraph::calcNodeDistancesAndAngles() { } } +bool MovGraph::findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr) { + MovGraphLink *link = 0; + double mindist = 1.0e20; + int resx = 0, resy = 0; + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *lnk = (MovGraphLink *)*i; + + if ((lnk->_flags & 0x10000000) && !(lnk->_flags & 0x20000000) ) { + double dx1 = lnk->_movGraphNode1->_x - p->x; + double dy1 = lnk->_movGraphNode1->_y - p->y; + double dx2 = lnk->_movGraphNode2->_x - p->x; + double dy2 = lnk->_movGraphNode2->_y - p->y; + double dx3 = lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x; + double dy3 = lnk->_movGraphNode2->_y - lnk->_movGraphNode1->_y; + double sq1 = sqrt(dy1 * dy1 + dx1 * dx1); + double sdist = (dy3 * dy1 + dx3 * dx1) / lnk->_distance / sq1; + double ldist = sdist * sq1; + double dist = sqrt(1.0 - sdist * sdist) * sq1; + + if (ldist < 0.0) { + ldist = 0.0; + dist = sqrt(dx1 * dx1 + dy1 * dy1); + } + + if (ldist > lnk->_distance) { + ldist = lnk->_distance; + dist = sqrt(dx2 * dx2 + dy2 * dy2); + } + + if (ldist >= 0.0 && ldist <= lnk->_distance && dist < mindist) { + resx = lnk->_movGraphNode1->_x + (int)(dx3 * ldist / lnk->_distance); + resy = lnk->_movGraphNode1->_y + (int)(dy3 * ldist / lnk->_distance); + + mindist = dist; + link = lnk; + } + } + } + + if (mindist < 1.0e20) { + if (movarr) + movarr->_link = link; + + if (p) { + p->x = resx; + p->y = resy; + } + + return true; + } + + return false; +} + int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) { for (uint i = 0; i < _items.size(); i++) if (_items[i]->ani == ani) @@ -668,6 +1227,209 @@ int MovGraph::getItemIndexByStaticAni(StaticANIObject *ani) { return -1; } +Common::Array<MovArr *> *MovGraph::genMovArr(int x, int y, int *arrSize, int flag1, int flag2) { + if (!_links.size()) { + *arrSize = 0; + + return 0; + } + + Common::Array<MovArr *> *arr = new Common::Array<MovArr *>; + MovArr *movarr; + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *lnk = (MovGraphLink *)*i; + + if (flag1) { + Common::Point point(x, y); + double dist = calcDistance(&point, lnk, 0); + + if (dist >= 0.0 && dist < 2.0) { + movarr = new MovArr; + + movarr->_link = lnk; + movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - point.y) + + (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(point.x - lnk->_movGraphNode1->_x)) / + lnk->_distance / lnk->_distance; + movarr->_point = point; + + arr->push_back(movarr); + } + } else { + if (lnk->_movGraphReact) { + if (lnk->_movGraphReact->pointInRegion(x, y)) { + if (!(lnk->_flags & 0x10000000) || lnk->_flags & 0x20000000) { + if (!flag2) { + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = 0.0; + movarr->_point.x = lnk->_movGraphNode1->_x; + movarr->_point.y = lnk->_movGraphNode1->_y; + arr->push_back(movarr); + + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = 1.0; + movarr->_point.x = lnk->_movGraphNode1->_x; + movarr->_point.y = lnk->_movGraphNode1->_y; + arr->push_back(movarr); + } + } else { + movarr = new MovArr; + movarr->_link = lnk; + movarr->_dist = ((double)(lnk->_movGraphNode1->_y - lnk->_movGraphNode2->_y) * (double)(lnk->_movGraphNode1->_y - y) + + (double)(lnk->_movGraphNode2->_x - lnk->_movGraphNode1->_x) * (double)(x - lnk->_movGraphNode1->_x)) / + lnk->_distance / lnk->_distance; + movarr->_point.x = x; + movarr->_point.y = y; + + calcDistance(&movarr->_point, lnk, 0); + + arr->push_back(movarr); + } + } + } + } + } + + *arrSize = arr->size(); + + return arr; +} + +void MovGraph::shuffleTree(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2) { + if (lnk == lnk2) { + for (uint i = 0; i < tempObList1.size(); i++) + tempObList2.push_back(tempObList1[i]); + + tempObList2.push_back(lnk); + } else { + lnk->_flags |= 0x80000000; + + tempObList1.push_back(lnk); + + for (ObList::iterator i = _links.begin(); i != _links.end(); ++i) { + MovGraphLink *l = (MovGraphLink *)*i; + + if (l->_movGraphNode1 != lnk->_movGraphNode1) { + if (l->_movGraphNode2 != lnk->_movGraphNode1) { + if (l->_movGraphNode1 != lnk->_movGraphNode2 && l->_movGraphNode2 != lnk->_movGraphNode2) + continue; + } + } + + if (!(l->_flags & 0xA0000000)) + shuffleTree(l, lnk2, tempObList1, tempObList2); + } + + lnk->_flags &= 0x7FFFFFFF; + } +} + +Common::Array<MovItem *> *MovGraph::calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount) { + Common::Array<MovGraphLink *> tempObList1; + Common::Array<MovGraphLink *> tempObList2; + + shuffleTree(movarr1->_link, movarr2->_link, tempObList1, tempObList2); + + *listCount = 0; + + if (!tempObList2.size()) + return 0; + + *listCount = tempObList2.size(); + + Common::Array<MovItem *> *res = new Common::Array<MovItem *>; + + for (int i = 0; i < *listCount; i++) { + MovItem *r = new MovItem; + + genMovItem(r, tempObList2[i], movarr1, movarr2); + + delete tempObList2[i]; + } + + movarr2->_link = movarr1->_link; + + return res; +} + +void MovGraph::genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2) { + warning("STUB: MovGraph::genMovItem()"); +} + +bool MovGraph::calcChunk(int idx, int x, int y, MovArr *arr, int a6) { + int staticsId; + + if (_items[idx]->ani->_statics) { + staticsId = _items[idx]->ani->_statics->_staticsId; + } else { + if (!_items[idx]->ani->_movement->_staticsObj2) + return 0; + + staticsId = _items[idx]->ani->_movement->_staticsObj2->_staticsId; + } + + int arrSize; + + Common::Array<MovArr *> *movarr = genMovArr(x, y, &arrSize, 0, 1); + + if (!movarr) + return findClosestLink(idx, 0, arr); + + bool res = false; + + int idxmin = -1; + int offmin = 100; + + for (int i = 0; i < arrSize; i++) { + int off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44]); + + if (off < offmin) { + offmin = off; + idxmin = i; + } + + off = _mgm.refreshOffsets(_items[idx]->ani->_id, staticsId, (*movarr)[i]->_link->_dwordArray2[_field_44 + 1]); + if (off < offmin) { + offmin = off; + idxmin = i; + } + } + + if (idxmin != -1) { + *arr = *(*movarr)[idxmin]; + + res = true; + } + + delete movarr; + + return res; +} + +void MovGraph::setEnds(MovStep *step1, MovStep *step2) { + if (step1->link->_movGraphNode1 == step2->link->_movGraphNode2) { + step1->sfield_0 = 1; + step2->sfield_0 = 1; + + return; + } + + if (step1->link->_movGraphNode1 == step2->link->_movGraphNode1) { + step1->sfield_0 = 1; + step2->sfield_0 = 0; + } else { + step1->sfield_0 = 0; + + if (step1->link->_movGraphNode2 != step2->link->_movGraphNode1) { + step2->sfield_0 = 1; + } else { + step2->sfield_0 = 0; + } + } +} + int MovGraph2::getItemIndexByGameObjectId(int objectId) { for (uint i = 0; i < _items2.size(); i++) if (_items2[i]->_objectId == objectId) @@ -1089,7 +1851,10 @@ int MovGraph2::removeObject(StaticANIObject *obj) { } void MovGraph2::freeItems() { - warning("STUB: MovGraph2::freeItems()"); + for (uint i = 0; i < _items2.size(); i++) + delete _items2[i]; + + _items2.clear(); } MessageQueue *MovGraph2::method34(StaticANIObject *ani, int xpos, int ypos, int fuzzyMatch, int staticsId) { @@ -1140,6 +1905,8 @@ MessageQueue *MovGraph2::doWalkTo(StaticANIObject *obj, int xpos, int ypos, int PicAniInfo picAniInfo; Common::Point point; + debug(0, "MovGraph2::doWalkTo(%d, %d, %d, %d, %d)", obj->_id, xpos, ypos, fuzzyMatch, staticsId); + int idx = getItemIndexByGameObjectId(obj->_id); if (idx < 0) @@ -2528,7 +3295,10 @@ MovGraphLink::MovGraphLink() { } MovGraphLink::~MovGraphLink() { - warning("STUB: MovGraphLink::~MovGraphLink()"); + delete _movGraphReact; + + _dwordArray1.clear(); + _dwordArray2.clear(); } @@ -2764,26 +3534,26 @@ bool MovGraphReact::pointInRegion(int x, int y) { } } -int startWalkTo(int objId, int objKey, int x, int y, int a5) { - MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fp->_currentScene->_sceneId); +int startWalkTo(int objId, int objKey, int x, int y, int fuzzyMatch) { + MctlCompound *mc = getCurrSceneSc2MotionController(); if (mc) - return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0); + return (mc->method34(g_fp->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, fuzzyMatch, 0) != 0); return 0; } -int doSomeAnimation(int objId, int objKey, int a3) { +bool doSomeAnimation(int objId, int objKey, int a3) { StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(objId, objKey); MctlCompound *cmp = getCurrSceneSc2MotionController(); if (ani && cmp) return cmp->method3C(ani, a3); - return 0; + return false; } -int doSomeAnimation2(int objId, int objKey) { +bool doSomeAnimation2(int objId, int objKey) { return doSomeAnimation(objId, objKey, 0); } diff --git a/engines/fullpipe/motion.h b/engines/fullpipe/motion.h index 4d92fd7fed..2b40791340 100644 --- a/engines/fullpipe/motion.h +++ b/engines/fullpipe/motion.h @@ -31,10 +31,12 @@ class MctlConnectionPoint; class MovGraphLink; class MessageQueue; class ExCommand2; +struct MovArr; +struct MovItem; int startWalkTo(int objId, int objKey, int x, int y, int a5); -int doSomeAnimation(int objId, int objKey, int a3); -int doSomeAnimation2(int objId, int objKey); +bool doSomeAnimation(int objId, int objKey, int a3); +bool doSomeAnimation2(int objId, int objKey); class MotionController : public CObject { public: @@ -52,14 +54,14 @@ public: virtual void addObject(StaticANIObject *obj) {} virtual int removeObject(StaticANIObject *obj) { return 0; } virtual void freeItems() {} - virtual int method28() { return 0; } - virtual int method2C(StaticANIObject *obj, int x, int y) { return 0; } + virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount) { return 0; } + virtual bool method2C(StaticANIObject *obj, int x, int y) { return false; } virtual int method30() { return 0; } virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } - virtual int changeCallback() { return 0; } - virtual int method3C(StaticANIObject *ani, int flag) { return 0; } + virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)) {} + virtual bool method3C(StaticANIObject *ani, int flag) { return 0; } virtual int method40() { return 0; } - virtual int method44() { return 0; } + virtual bool method44(StaticANIObject *ani, int x, int y) { return false; } virtual int method48() { return -1; } virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId) { return 0; } @@ -115,7 +117,7 @@ public: virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); void initMovGraph2(); - MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, int *minDistancePtr); + MctlConnectionPoint *findClosestConnectionPoint(int ox, int oy, int destIndex, int connectionX, int connectionY, int sourceIndex, double *minDistancePtr); void replaceNodeX(int from, int to); uint getMotionControllerCount() { return _motionControllers.size(); } @@ -299,18 +301,32 @@ class MovGraphLink : public CObject { void calcNodeDistanceAndAngle(); }; +struct MovStep { + int sfield_0; + MovGraphLink *link; +}; + +struct MovArr { + Common::Array<MovStep *> _movSteps; + int _movStepCount; + int _afield_8; + MovGraphLink *_link; + double _dist; + Common::Point _point; +}; + +struct MovItem { + MovArr *movarr; + int _mfield_4; + int _mfield_8; + int _mfield_C; +}; + struct MovGraphItem { StaticANIObject *ani; int field_4; - int field_8; - int field_C; - int field_10; - int field_14; - int field_18; - int field_1C; - int field_20; - int field_24; - int items; + MovArr movarr; + Common::Array<MovItem *> *movitems; int count; int field_30; int field_34; @@ -318,6 +334,7 @@ struct MovGraphItem { int field_3C; MovGraphItem(); + void free(); }; class MovGraph : public MotionController { @@ -326,7 +343,7 @@ public: ObList _links; int _field_44; Common::Array<MovGraphItem *> _items; - int (*_callback1)(int, int, int); + MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter); MGM _mgm; public: @@ -338,19 +355,28 @@ public: virtual void addObject(StaticANIObject *obj); virtual int removeObject(StaticANIObject *obj); virtual void freeItems(); - virtual int method28(); - virtual int method2C(StaticANIObject *obj, int x, int y); + virtual Common::Array<MovItem *> *method28(StaticANIObject *ani, int x, int y, int flag1, int *rescount); + virtual bool method2C(StaticANIObject *obj, int x, int y); virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual int changeCallback(); - virtual int method3C(StaticANIObject *ani, int flag); - virtual int method44(); + virtual void changeCallback(MovArr *(*_callback1)(StaticANIObject *ani, Common::Array<MovItem *> *items, signed int counter)); + virtual bool method3C(StaticANIObject *ani, int flag); + virtual bool method44(StaticANIObject *ani, int x, int y); virtual MessageQueue *doWalkTo(StaticANIObject *subj, int xpos, int ypos, int fuzzyMatch, int staticsId); - virtual int method50(); + virtual MessageQueue *method50(StaticANIObject *ani, MovArr *movarr, int staticsId); double calcDistance(Common::Point *point, MovGraphLink *link, int fuzzyMatch); void calcNodeDistancesAndAngles(); + bool findClosestLink(int unusedArg, Common::Point *p, MovArr *movarr); MovGraphNode *calcOffset(int ox, int oy); int getItemIndexByStaticAni(StaticANIObject *ani); + Common::Array<MovArr *> *genMovArr(int x, int y, int *arrSize, int flag1, int flag2); + void shuffleTree(MovGraphLink *lnk, MovGraphLink *lnk2, Common::Array<MovGraphLink *> &tempObList1, Common::Array<MovGraphLink *> &tempObList2); + Common::Array<MovItem *> *calcMovItems(MovArr *movarr1, MovArr *movarr2, int *listCount); + void genMovItem(MovItem *movitem, MovGraphLink *grlink, MovArr *movarr1, MovArr *movarr2); + bool calcChunk(int idx, int x, int y, MovArr *arr, int a6); + MessageQueue *sub1(StaticANIObject *ani, int x, int y, int a5, int x1, int y1, int a8, int a9); + MessageQueue *fillMGMinfo(StaticANIObject *ani, MovArr *movarr, int staticsId); + void setEnds(MovStep *step1, MovStep *step2); }; class Movement; diff --git a/engines/fullpipe/scene.cpp b/engines/fullpipe/scene.cpp index 462401b3b2..1247d9380e 100644 --- a/engines/fullpipe/scene.cpp +++ b/engines/fullpipe/scene.cpp @@ -133,7 +133,27 @@ Scene::Scene() { } Scene::~Scene() { - warning("STUB: Scene::~Scene()"); + delete _soundList; + delete _shadows; + delete _palette; + + // _faObjlist is not used + + for (uint i = 0; i < _messageQueueList.size(); i++) + delete _messageQueueList[i]; + + _messageQueueList.clear(); + + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + delete _staticANIObjectList1[i]; + + _staticANIObjectList1.clear(); + + delete _libHandle; + + // delete _field_BC; + + free(_sceneName); } bool Scene::load(MfcArchive &file) { @@ -249,7 +269,7 @@ bool Scene::load(MfcArchive &file) { void Scene::initStaticANIObjects() { for (uint i = 0; i < _staticANIObjectList1.size(); i++) - ((StaticANIObject *)_staticANIObjectList1[i])->initMovements(); + _staticANIObjectList1[i]->initMovements(); } void Scene::init() { @@ -262,13 +282,13 @@ void Scene::init() { ((PictureObject *)_picObjList[i])->clearFlags(); for (uint i = 0; i < _staticANIObjectList1.size(); i++) - ((StaticANIObject *)_staticANIObjectList1[i])->clearFlags(); + _staticANIObjectList1[i]->clearFlags(); if (_staticANIObjectList2.size() != _staticANIObjectList1.size()) { _staticANIObjectList2.clear(); - for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) - _staticANIObjectList2.push_back(*s); + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + _staticANIObjectList2.push_back(_staticANIObjectList1[i]); } } @@ -281,35 +301,33 @@ StaticANIObject *Scene::getAniMan() { } StaticANIObject *Scene::getStaticANIObject1ById(int obj, int a3) { - for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) { - StaticANIObject *o = (StaticANIObject *)*s; - if (o->_id == obj && (a3 == -1 || o->_okeyCode == a3)) - return o; + for (uint i = 0; i < _staticANIObjectList1.size(); i++) { + if (_staticANIObjectList1[i]->_id == obj && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3)) + return _staticANIObjectList1[i]; } return 0; } StaticANIObject *Scene::getStaticANIObject1ByName(char *name, int a3) { - for (uint n = 0; n < _staticANIObjectList1.size(); n++) { - StaticANIObject *o = (StaticANIObject *)_staticANIObjectList1[n]; - if (!strcmp(o->_objectName, name) && (a3 == -1 || o->_okeyCode == a3)) - return o; + for (uint i = 0; i < _staticANIObjectList1.size(); i++) { + if (!strcmp(_staticANIObjectList1[i]->_objectName, name) && (a3 == -1 || _staticANIObjectList1[i]->_okeyCode == a3)) + return _staticANIObjectList1[i]; } return 0; } void Scene::deleteStaticANIObject(StaticANIObject *obj) { - for (uint n = 0; n < _staticANIObjectList1.size(); n++) - if ((StaticANIObject *)_staticANIObjectList1[n] == obj) { - _staticANIObjectList1.remove_at(n); + for (uint i = 0; i < _staticANIObjectList1.size(); i++) + if (_staticANIObjectList1[i] == obj) { + _staticANIObjectList1.remove_at(i); break; } - for (uint n = 0; n < _staticANIObjectList2.size(); n++) - if ((StaticANIObject *)_staticANIObjectList2[n] == obj) { - _staticANIObjectList2.remove_at(n); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + if (_staticANIObjectList2[i] == obj) { + _staticANIObjectList2.remove_at(i); break; } } @@ -335,11 +353,12 @@ void Scene::setPictureObjectsFlag4() { } void Scene::stopAllSounds() { - warning("STUB: Scene:stopAllSounds()"); + for (int i = 0; i < _soundList->getCount(); i++) + _soundList->getSoundByIndex(i)->stop(); } PictureObject *Scene::getPictureObjectById(int objId, int flags) { - for (uint i = 0; i < _picObjList.size(); i++) { + for (uint i = 1; i < _picObjList.size(); i++) { if (((PictureObject *)_picObjList[i])->_id == objId && ((PictureObject *)_picObjList[i])->_okeyCode == flags) return (PictureObject *)_picObjList[i]; } @@ -369,16 +388,16 @@ void Scene::deletePictureObject(PictureObject *obj) { MessageQueue *Scene::getMessageQueueById(int messageId) { for (uint i = 0; i < _messageQueueList.size(); i++) - if (((MessageQueue *)_messageQueueList[i])->_dataId == messageId) - return (MessageQueue *)_messageQueueList[i]; + if (_messageQueueList[i]->_dataId == messageId) + return _messageQueueList[i]; return 0; } MessageQueue *Scene::getMessageQueueByName(char *name) { for (uint i = 0; i < _messageQueueList.size(); i++) - if (!strcmp(((MessageQueue *)_messageQueueList[i])->_queueName, name)) - return (MessageQueue *)_messageQueueList[i]; + if (!strcmp(_messageQueueList[i]->_queueName, name)) + return _messageQueueList[i]; return 0; } @@ -447,15 +466,27 @@ void Scene::initObjectCursors(const char *varname) { } bool Scene::compareObjPriority(const void *p1, const void *p2) { - if (((const StaticANIObject *)p1)->_priority > ((const StaticANIObject *)p2)->_priority) + if (((const GameObject *)p1)->_priority > ((const GameObject *)p2)->_priority) return true; return false; } -void Scene::objectList_sortByPriority(PtrList &list, bool skipFirst) { +void Scene::objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst) { if (skipFirst) { - PtrList::iterator s = list.begin(); + Common::Array<StaticANIObject *>::iterator s = list.begin(); + + ++s; + + Common::sort(s, list.end(), Scene::compareObjPriority); + } else { + Common::sort(list.begin(), list.end(), Scene::compareObjPriority); + } +} + +void Scene::objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst) { + if (skipFirst) { + Common::Array<PictureObject *>::iterator s = list.begin(); ++s; @@ -476,16 +507,15 @@ void Scene::draw() { objectList_sortByPriority(_staticANIObjectList2); - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) { - ((StaticANIObject *)*s)->draw2(); - } + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + _staticANIObjectList2[i]->draw2(); int priority = -1; - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) { - drawContent(((StaticANIObject *)*s)->_priority, priority, false); - ((StaticANIObject *)*s)->draw(); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) { + drawContent(_staticANIObjectList2[i]->_priority, priority, false); + _staticANIObjectList2[i]->draw(); - priority = ((StaticANIObject *)*s)->_priority; + priority = _staticANIObjectList2[i]->_priority; } drawContent(-1, priority, false); @@ -566,7 +596,7 @@ StaticANIObject *Scene::getStaticANIObjectAtPos(int x, int y) { StaticANIObject *res = 0; for (uint i = 0; i < _staticANIObjectList1.size(); i++) { - StaticANIObject *p = (StaticANIObject *)_staticANIObjectList1[i]; + StaticANIObject *p = _staticANIObjectList1[i]; int pixel; if ((p->_field_8 & 0x100) && (p->_flags & 4) && @@ -612,8 +642,8 @@ int Scene::getPictureObjectIdAtPos(int x, int y) { void Scene::update(int counterdiff) { debug(6, "Scene::update(%d)", counterdiff); - for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) - ((StaticANIObject *)*s)->update(counterdiff); + for (uint i = 0; i < _staticANIObjectList2.size(); i++) + _staticANIObjectList2[i]->update(counterdiff); } void Scene::drawContent(int minPri, int maxPri, bool drawBg) { diff --git a/engines/fullpipe/scene.h b/engines/fullpipe/scene.h index 8306974f7b..1e2dae81fe 100644 --- a/engines/fullpipe/scene.h +++ b/engines/fullpipe/scene.h @@ -31,10 +31,10 @@ class MessageQueue; class Scene : public Background { public: - PtrList _staticANIObjectList1; - PtrList _staticANIObjectList2; - PtrList _messageQueueList; - PtrList _faObjectList; + Common::Array<StaticANIObject *> _staticANIObjectList1; + Common::Array<StaticANIObject *> _staticANIObjectList2; + Common::Array<MessageQueue *> _messageQueueList; + // PtrList _faObjectList; // not used Shadows *_shadows; SoundList *_soundList; int16 _sceneId; @@ -82,7 +82,8 @@ class Scene : public Background { private: static bool compareObjPriority(const void *p1, const void *p2); - void objectList_sortByPriority(PtrList &list, bool skipFirst = false); + void objectList_sortByPriority(Common::Array<StaticANIObject *> &list, bool skipFirst = false); + void objectList_sortByPriority(Common::Array<PictureObject *> &list, bool skipFirst = false); }; class SceneTag : public CObject { diff --git a/engines/fullpipe/scenes.cpp b/engines/fullpipe/scenes.cpp index 7420c1b1cf..b346bf3a17 100644 --- a/engines/fullpipe/scenes.cpp +++ b/engines/fullpipe/scenes.cpp @@ -590,10 +590,8 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) { scene->setPictureObjectsFlag4(); - for (PtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) { - StaticANIObject *o = (StaticANIObject *)*s; - o->setFlags(o->_flags & 0xFE7F); - } + for (uint i = 0; i < scene->_staticANIObjectList1.size(); i++) + scene->_staticANIObjectList1[i]->_flags &= 0xFE7F; PictureObject *p = accessScene(SC_INV)->getPictureObjectById(PIC_INV_MENU, 0); p->setFlags(p->_flags & 0xFFFB); @@ -1456,9 +1454,28 @@ void BallChain::init(Ball **ball) { } Ball *BallChain::sub04(Ball *ballP, Ball *ballN) { - warning("STUB: BallChain::sub04"); + if (!pTail) { + cPlex = (byte *)calloc(cPlexLen, sizeof(Ball)); + + Ball *runPtr = (Ball *)&cPlex[(cPlexLen - 1) * sizeof(Ball)]; + + for (int i = 0; i < cPlexLen; i++) { + runPtr->p0 = pTail; + pTail = runPtr; + + runPtr -= sizeof(Ball); + } + } + + Ball *res = pTail; + + pTail = res->p0; + res->p1 = ballP; + res->p0 = ballN; + numBalls++; + res->ani = 0; - return pTail; + return res; } void BallChain::removeBall(Ball *ball) { diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index 3c13bad854..65c9bf84ca 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -27,6 +27,8 @@ #include "fullpipe/sound.h" #include "fullpipe/ngiarchive.h" #include "fullpipe/messages.h" +#include "fullpipe/statics.h" + #include "common/memstream.h" #include "audio/audiostream.h" #include "audio/decoders/vorbis.h" @@ -132,7 +134,75 @@ void Sound::updateVolume() { } void Sound::setPanAndVolumeByStaticAni() { - debug(3, "STUB Sound::setPanAndVolumeByStaticAni()"); + if (!_objectId) + return; + + StaticANIObject *ani = g_fp->_currentScene->getStaticANIObject1ById(_objectId, -1); + if (!ani) + return; + + int a, b; + + if (ani->_ox >= g_fp->_sceneRect.left) { + int par, pan; + + if (ani->_ox <= g_fp->_sceneRect.right) { + int dx; + + if (ani->_oy <= g_fp->_sceneRect.bottom) { + if (ani->_oy >= g_fp->_sceneRect.top) { + setPanAndVolume(g_fp->_sfxVolume, 0); + + return; + } + dx = g_fp->_sceneRect.top - ani->_oy; + } else { + dx = ani->_oy - g_fp->_sceneRect.bottom; + } + + par = 0; + + if (dx > 800) { + setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } else { + int dx = ani->_ox - g_fp->_sceneRect.right; + + if (dx > 800) { + setPanAndVolume(-3500, 0); + return; + } + + pan = -3500; + par = dx * (-3500) / -800; + a = g_fp->_sfxVolume - (-3500); + b = 800 - dx; + } + + int32 pp = b * a; + + setPanAndVolume(pan + pp / 800, par); + + return; + } + + int dx = g_fp->_sceneRect.left - ani->_ox; + if (dx <= 800) { + int32 s = (800 - dx) * (g_fp->_sfxVolume - (-3500)); + int32 p = -3500 + s / 800; + + if (p > g_fp->_sfxVolume) + p = g_fp->_sfxVolume; + + setPanAndVolume(p, dx * (-3500) / 800); + } else { + setPanAndVolume(-3500, 0); + } } void Sound::setPanAndVolume(int vol, int pan) { @@ -298,8 +368,12 @@ void FullpipeEngine::startSoundStream1(char *trackName) { } void FullpipeEngine::stopAllSounds() { - // TODO: Differences from stopAllSoundStreams() - _mixer->stopAll(); + // _mixer->stopAll(); + + for (int i = 0; i < _currSoundListCount; i++) + for (int j = 0; j < _currSoundList1[i]->getCount(); j++) { + _currSoundList1[i]->getSoundByIndex(j)->stop(); + } } void FullpipeEngine::toggleMute() { @@ -447,7 +521,7 @@ void FullpipeEngine::updateSoundVolume() { void FullpipeEngine::setMusicVolume(int vol) { _musicVolume = vol; - debug(3, "STUB FullpipeEngine::setMusicVolume()"); + g_fp->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); } } // End of namespace Fullpipe diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp index e36b196517..41641457d3 100644 --- a/engines/fullpipe/stateloader.cpp +++ b/engines/fullpipe/stateloader.cpp @@ -55,9 +55,8 @@ bool FullpipeEngine::loadGam(const char *fname, int scene) { _inventory->rebuildItemRects(); - for (PtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) { - ((MemoryObject *)((PictureObject *)*p)->_picture)->load(); - } + for (uint i = 0; i < _inventory->getScene()->_picObjList.size(); i++) + ((MemoryObject *)_inventory->getScene()->_picObjList[i]->_picture)->load(); // _sceneSwitcher = sceneSwitcher; // substituted with direct call _gameLoader->_preloadCallback = preloadCallback; diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index f1abac5778..b6b312ab85 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -141,7 +141,17 @@ StaticANIObject::StaticANIObject() { } StaticANIObject::~StaticANIObject() { - warning("STUB: StaticANIObject::~StaticANIObject()"); + for (uint i = 0; i < _staticsList.size(); i++) + delete _staticsList[i]; + + _staticsList.clear(); + + for (uint i = 0; i < _movements.size(); i++) + delete _movements[i]; + + _movements.clear(); + + g_fp->_mgm->clear(); } StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { @@ -164,22 +174,21 @@ StaticANIObject::StaticANIObject(StaticANIObject *src) : GameObject(src) { _objtype = kObjTypeStaticANIObject; for (uint i = 0; i < src->_staticsList.size(); i++) - _staticsList.push_back(new Statics((Statics *)src->_staticsList[i], 0)); + _staticsList.push_back(new Statics(src->_staticsList[i], 0)); _movement = 0; _statics = 0; for (uint i = 0; i < src->_movements.size(); i++) { Movement *newmov; - Movement *mov = (Movement *)src->_movements[i]; - if (mov->_currMovement) { + if (src->_movements[i]->_currMovement) { // WORKAROUND: Original uses weird construction here: // new Movement(getMovementById(src->getMovementIdById(mov->_id)), this); - newmov = new Movement(src->getMovementById(src->getMovementIdById(mov->_id)), this); - newmov->_id = mov->_id; + newmov = new Movement(src->getMovementById(src->getMovementIdById(src->_movements[i]->_id)), this); + newmov->_id = src->_movements[i]->_id; } else { - newmov = new Movement(mov, 0, -1, this); + newmov = new Movement(src->_movements[i], 0, -1, this); } _movements.push_back(newmov); @@ -224,7 +233,7 @@ bool StaticANIObject::load(MfcArchive &file) { Common::Point pt; if (count) { // We have movements - ((Movement *)_movements[0])->getCurrDynamicPhaseXY(pt); + _movements[0]->getCurrDynamicPhaseXY(pt); } else { pt.x = pt.y = 100; } @@ -392,34 +401,36 @@ bool StaticANIObject::isIdle() { Statics *StaticANIObject::getStaticsById(int itemId) { for (uint i = 0; i < _staticsList.size(); i++) - if (((Statics *)_staticsList[i])->_staticsId == itemId) - return (Statics *)_staticsList[i]; + if (_staticsList[i]->_staticsId == itemId) + return _staticsList[i]; return 0; } Statics *StaticANIObject::getStaticsByName(char *name) { for (uint i = 0; i < _staticsList.size(); i++) - if (!strcmp(((Statics *)_staticsList[i])->_staticsName, name)) - return (Statics *)_staticsList[i]; + if (!strcmp(_staticsList[i]->_staticsName, name)) + return _staticsList[i]; return 0; } Movement *StaticANIObject::getMovementById(int itemId) { for (uint i = 0; i < _movements.size(); i++) - if (((Movement *)_movements[i])->_id == itemId) - return (Movement *)_movements[i]; + if (_movements[i]->_id == itemId) + return _movements[i]; return 0; } int StaticANIObject::getMovementIdById(int itemId) { for (uint i = 0; i < _movements.size(); i++) { - Movement *mov = (Movement *)_movements[i]; + Movement *mov = _movements[i]; + if (mov->_currMovement) { if (mov->_id == itemId) return mov->_id; + if (mov->_currMovement->_id == itemId) return mov->_id; } @@ -430,8 +441,8 @@ int StaticANIObject::getMovementIdById(int itemId) { Movement *StaticANIObject::getMovementByName(char *name) { for (uint i = 0; i < _movements.size(); i++) - if (!strcmp(((Movement *)_movements[i])->_objectName, name)) - return (Movement *)_movements[i]; + if (!strcmp(_movements[i]->_objectName, name)) + return _movements[i]; return 0; } @@ -551,12 +562,12 @@ void Movement::draw(bool flipFlag, int angle) { void StaticANIObject::loadMovementsPixelData() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->loadPixelData(); + _movements[i]->loadPixelData(); } void StaticANIObject::freeMovementsPixelData() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->freePixelData(); + _movements[i]->freePixelData(); } Statics *StaticANIObject::addReverseStatics(Statics *st) { @@ -665,11 +676,10 @@ MovTable *StaticANIObject::countMovements() { movTable->movs = (int16 *)calloc(_movements.size(), sizeof(int16)); for (uint i = 0; i < _movements.size(); i++) { - GameObject *obj = (GameObject *)_movements[i]; movTable->movs[i] = 2; for (GameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) { - if (scumm_stricmp(obj->getName(), sub->_varName) == 0) { + if (scumm_stricmp(_movements[i]->getName(), sub->_varName) == 0) { movTable->movs[i] = 1; break; } @@ -702,21 +712,21 @@ void StaticANIObject::setSpeed(int speed) { void StaticANIObject::setAlpha(int alpha) { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->setAlpha(alpha); + _movements[i]->setAlpha(alpha); for (uint i = 0; i < _staticsList.size(); i++) - ((Statics *)_staticsList[i])->setAlpha(alpha); + _staticsList[i]->setAlpha(alpha); } void StaticANIObject::initMovements() { for (uint i = 0; i < _movements.size(); i++) - ((Movement *)_movements[i])->removeFirstPhase(); + _movements[i]->removeFirstPhase(); } void StaticANIObject::preloadMovements(MovTable *mt) { - if ( mt ) { + if (mt) { for (uint i = 0; i < _movements.size(); i++) { - Movement *mov = (Movement *)_movements[i]; + Movement *mov = _movements[i]; if (mt->movs[i] == 1) mov->loadPixelData(); @@ -1177,8 +1187,8 @@ void StaticANIObject::startAnimSteps(int movementId, int messageQueueId, int x, if (!(_flags & 0x80)) { if (!_messageQueueId) for (uint i = 0; i < _movements.size(); i++) { - if (((Movement *)_movements[i])->_id == movementId) { - mov = (Movement *)_movements[i]; + if (_movements[i]->_id == movementId) { + mov = _movements[i]; break; } } @@ -1266,7 +1276,7 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase if (_flags & 0x80) return false; - debug(0, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); + debug(4, "StaticANIObject::startAnim(%d, %d, %d) (%s [%d]) [%d, %d]", movementId, messageQueueId, dynPhaseIdx, transCyrillic((byte *)_objectName), _id, _ox, _oy); if (_messageQueueId) { updateGlobalMessageQueue(messageQueueId, _id); @@ -1276,9 +1286,8 @@ bool StaticANIObject::startAnim(int movementId, int messageQueueId, int dynPhase Movement *mov = 0; for (uint i = 0; i < _movements.size(); i++) { - - if (((Movement *)_movements[i])->_id == movementId) { - mov = (Movement *)_movements[i]; + if (_movements[i]->_id == movementId) { + mov = _movements[i]; break; } } @@ -1441,6 +1450,19 @@ bool Statics::load(MfcArchive &file) { return true; } +void Statics::init() { + Picture::init(); + + if (_staticsId & 0x4000) { + Bitmap *bmp = _bitmap->reverseImage(); + + freePixelData(); + + _bitmap = bmp; + _data = bmp->_pixels; + } +} + Common::Point *Statics::getSomeXY(Common::Point &p) { p.x = _someX; p.y = _someY; @@ -1493,7 +1515,17 @@ Movement::Movement() { } Movement::~Movement() { - warning("STUB: Movement::~Movement()"); + for (uint i = 0; i < _dynamicPhases.size(); i++) + delete _framePosOffsets[i]; + + if (!_currMovement ) { + if (_updateFlag1) + _dynamicPhases.remove_at(0); + + _dynamicPhases.clear(); + } + + free(_framePosOffsets); } Movement::Movement(Movement *src, StaticANIObject *ani) { @@ -1748,11 +1780,11 @@ Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) { void Movement::setAlpha(int alpha) { if (_currMovement) for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) { - ((DynamicPhase *)_currMovement->_dynamicPhases[i])->setAlpha(alpha); + _currMovement->_dynamicPhases[i]->setAlpha(alpha); } else for (uint i = 0; i < _dynamicPhases.size(); i++) { - ((DynamicPhase *)_dynamicPhases[i])->setAlpha(alpha); + _dynamicPhases[i]->setAlpha(alpha); } } @@ -1765,9 +1797,9 @@ Common::Point *Movement::getDimensionsOfPhase(Common::Point *p, int phaseIndex) DynamicPhase *dyn; if (_currMovement) - dyn = (DynamicPhase *)_currMovement->_dynamicPhases[idx]; + dyn = _currMovement->_dynamicPhases[idx]; else - dyn = (DynamicPhase *)_dynamicPhases[idx]; + dyn = _dynamicPhases[idx]; Common::Point point; @@ -1816,13 +1848,13 @@ void Movement::updateCurrDynamicPhase() { return; if (_currMovement->_dynamicPhases[_currDynamicPhaseIndex]) - _currDynamicPhase = (DynamicPhase *)_currMovement->_dynamicPhases[_currDynamicPhaseIndex]; + _currDynamicPhase = _currMovement->_dynamicPhases[_currDynamicPhaseIndex]; } else { if (_dynamicPhases.size() == 0 || (uint)_currDynamicPhaseIndex >= _dynamicPhases.size()) return; if (_dynamicPhases[_currDynamicPhaseIndex]) - _currDynamicPhase = (DynamicPhase *)_dynamicPhases[_currDynamicPhaseIndex]; + _currDynamicPhase = _dynamicPhases[_currDynamicPhaseIndex]; } } @@ -1831,11 +1863,11 @@ int Movement::calcDuration() { if (_currMovement) for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) { - res += ((DynamicPhase *)_currMovement->_dynamicPhases[i])->_initialCountdown; + res += _currMovement->_dynamicPhases[i]->_initialCountdown; } else for (uint i = 0; i < _dynamicPhases.size(); i++) { - res += ((DynamicPhase *)_dynamicPhases[i])->_initialCountdown; + res += _dynamicPhases[i]->_initialCountdown; } return res; @@ -1876,12 +1908,12 @@ DynamicPhase *Movement::getDynamicPhaseByIndex(int idx) { if (_currMovement->_dynamicPhases.size() == 0 || (uint)idx >= _currMovement->_dynamicPhases.size()) return 0; - return (DynamicPhase *)_currMovement->_dynamicPhases[idx]; + return _currMovement->_dynamicPhases[idx]; } else { if (_dynamicPhases.size() == 0 || (uint)idx >= _dynamicPhases.size()) return 0; - return (DynamicPhase *)_dynamicPhases[idx]; + return _dynamicPhases[idx]; } } @@ -1892,7 +1924,7 @@ void Movement::loadPixelData() { for (uint i = 0; i < _dynamicPhases.size(); i++) { if ((Statics *)_dynamicPhases[i] != mov->_staticsObj2 || !(mov->_staticsObj2->_staticsId & 0x4000)) - ((Statics *)_dynamicPhases[i])->getPixelData(); + _dynamicPhases[i]->getPixelData(); } if (!(mov->_staticsObj1->_staticsId & 0x4000)) @@ -1902,7 +1934,7 @@ void Movement::loadPixelData() { void Movement::freePixelData() { if (!_currMovement) for (uint i = 0; i < _dynamicPhases.size(); i++) - ((DynamicPhase *)_dynamicPhases[i])->freePixelData(); + _dynamicPhases[i]->freePixelData(); if (_staticsObj1) _staticsObj1->freePixelData(); @@ -1934,11 +1966,11 @@ bool Movement::gotoNextFrame(void (*callback1)(int, Common::Point *point, int, i if (!callback2) { if (_currMovement) { if ((uint)_currDynamicPhaseIndex == _currMovement->_dynamicPhases.size() - 1 - && !(((DynamicPhase *)(_currMovement->_dynamicPhases.back()))->_countdown)) { + && !(_currMovement->_dynamicPhases.back()->_countdown)) { return false; } } else if ((uint)_currDynamicPhaseIndex == _dynamicPhases.size() - 1 - && !(((DynamicPhase *)(_dynamicPhases.back()))->_countdown)) { + && !(_dynamicPhases.back()->_countdown)) { return false; } } diff --git a/engines/fullpipe/statics.h b/engines/fullpipe/statics.h index d678957163..63661157b2 100644 --- a/engines/fullpipe/statics.h +++ b/engines/fullpipe/statics.h @@ -98,6 +98,7 @@ class Statics : public DynamicPhase { virtual ~Statics(); virtual bool load(MfcArchive &file); + virtual void init(); Statics *getStaticsById(int itemId); Common::Point *getSomeXY(Common::Point &p); @@ -121,7 +122,7 @@ class Movement : public GameObject { int _field_50; int _counterMax; int _counter; - PtrList _dynamicPhases; + Common::Array<DynamicPhase *> _dynamicPhases; int _field_78; Common::Point **_framePosOffsets; Movement *_currMovement; @@ -181,8 +182,8 @@ class StaticANIObject : public GameObject { int _initialCounter; void (*_callback1)(int, Common::Point *point, int, int); void (*_callback2)(int *); - PtrList _movements; - PtrList _staticsList; + Common::Array<Movement *> _movements; + Common::Array<Statics *> _staticsList; StepArray _stepArray; int16 _field_96; int _messageQueueId; diff --git a/engines/fullpipe/utils.h b/engines/fullpipe/utils.h index 72e746cd03..da3ab7ee4f 100644 --- a/engines/fullpipe/utils.h +++ b/engines/fullpipe/utils.h @@ -68,6 +68,7 @@ enum ObjType { kObjTypeDefault, kObjTypeExCommand, kObjTypeExCommand2, + kObjTypeModalSaveGame, kObjTypeMovGraph, kObjTypeMovGraphLink, kObjTypeMovGraphNode, @@ -148,8 +149,6 @@ class DWordArray : public Common::Array<int32>, public CObject { virtual bool load(MfcArchive &file); }; -typedef Common::Array<void *> PtrList; - char *genFileName(int superId, int sceneId, const char *ext); byte *transCyrillic(byte *s); diff --git a/engines/gob/cheater_geisha.cpp b/engines/gob/cheater_geisha.cpp index 8c4deec370..ec6fe09d59 100644 --- a/engines/gob/cheater_geisha.cpp +++ b/engines/gob/cheater_geisha.cpp @@ -61,7 +61,7 @@ bool Cheater_Geisha::cheat(GUI::Debugger &console) { uint32 digit5 = READ_VARO_UINT32(0x778); if (digit1 && digit2 && digit3 && digit4 && digit5) - console.DebugPrintf("Mastermind solution: %d %d %d %d %d\n", + console.debugPrintf("Mastermind solution: %d %d %d %d %d\n", digit1, digit2, digit3, digit4, digit5); return true; diff --git a/engines/gob/console.cpp b/engines/gob/console.cpp index b0f6006284..2252606243 100644 --- a/engines/gob/console.cpp +++ b/engines/gob/console.cpp @@ -29,14 +29,14 @@ namespace Gob { GobConsole::GobConsole(GobEngine *vm) : GUI::Debugger(), _vm(vm), _cheater(0) { - DCmd_Register("varSize", WRAP_METHOD(GobConsole, cmd_varSize)); - DCmd_Register("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars)); - DCmd_Register("var8", WRAP_METHOD(GobConsole, cmd_var8)); - DCmd_Register("var16", WRAP_METHOD(GobConsole, cmd_var16)); - DCmd_Register("var32", WRAP_METHOD(GobConsole, cmd_var32)); - DCmd_Register("varString", WRAP_METHOD(GobConsole, cmd_varString)); - DCmd_Register("cheat", WRAP_METHOD(GobConsole, cmd_cheat)); - DCmd_Register("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives)); + registerCmd("varSize", WRAP_METHOD(GobConsole, cmd_varSize)); + registerCmd("dumpVars", WRAP_METHOD(GobConsole, cmd_dumpVars)); + registerCmd("var8", WRAP_METHOD(GobConsole, cmd_var8)); + registerCmd("var16", WRAP_METHOD(GobConsole, cmd_var16)); + registerCmd("var32", WRAP_METHOD(GobConsole, cmd_var32)); + registerCmd("varString", WRAP_METHOD(GobConsole, cmd_varString)); + registerCmd("cheat", WRAP_METHOD(GobConsole, cmd_cheat)); + registerCmd("listArchives", WRAP_METHOD(GobConsole, cmd_listArchives)); } GobConsole::~GobConsole() { @@ -51,7 +51,7 @@ void GobConsole::unregisterCheater() { } bool GobConsole::cmd_varSize(int argc, const char **argv) { - DebugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize()); + debugPrintf("Size of the variable space: %d bytes\n", _vm->_inter->_variables->getSize()); return true; } @@ -74,14 +74,14 @@ bool GobConsole::cmd_dumpVars(int argc, const char **argv) { bool GobConsole::cmd_var8(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var8 <var offset> (<value>)\n"); + debugPrintf("Usage: var8 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if (varNum >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -90,21 +90,21 @@ bool GobConsole::cmd_var8(int argc, const char **argv) { _vm->_inter->_variables->writeOff8(varNum, varVal); } - DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum)); + debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff8(varNum)); return true; } bool GobConsole::cmd_var16(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var16 <var offset> (<value>)\n"); + debugPrintf("Usage: var16 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if ((varNum + 1) >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -113,21 +113,21 @@ bool GobConsole::cmd_var16(int argc, const char **argv) { _vm->_inter->_variables->writeOff16(varNum, varVal); } - DebugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum)); + debugPrintf("var16_%d = %d\n", varNum, _vm->_inter->_variables->readOff16(varNum)); return true; } bool GobConsole::cmd_var32(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var32 <var offset> (<value>)\n"); + debugPrintf("Usage: var32 <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if ((varNum + 3) >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -136,21 +136,21 @@ bool GobConsole::cmd_var32(int argc, const char **argv) { _vm->_inter->_variables->writeOff32(varNum, varVal); } - DebugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum)); + debugPrintf("var8_%d = %d\n", varNum, _vm->_inter->_variables->readOff32(varNum)); return true; } bool GobConsole::cmd_varString(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: varString <var offset> (<value>)\n"); + debugPrintf("Usage: varString <var offset> (<value>)\n"); return true; } uint32 varNum = atoi(argv[1]); if (varNum >= _vm->_inter->_variables->getSize()) { - DebugPrintf("Variable offset out of range\n"); + debugPrintf("Variable offset out of range\n"); return true; } @@ -160,7 +160,7 @@ bool GobConsole::cmd_varString(int argc, const char **argv) { Common::strlcpy(_vm->_inter->_variables->getAddressOffString(varNum), argv[2], maxLength); } - DebugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum)); + debugPrintf("varString_%d = \"%s\"\n", varNum, _vm->_inter->_variables->getAddressOffString(varNum)); return true; } @@ -177,11 +177,11 @@ bool GobConsole::cmd_listArchives(int argc, const char **argv) { _vm->_dataIO->getArchiveInfo(info); - DebugPrintf(" Archive | Base | FileCount\n"); - DebugPrintf("--------------------------------\n"); + debugPrintf(" Archive | Base | FileCount\n"); + debugPrintf("--------------------------------\n"); for (Common::Array<ArchiveInfo>::const_iterator it = info.begin(); it != info.end(); ++it) if (!it->name.empty()) - DebugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount); + debugPrintf("%13s | %d | %d\n", it->name.c_str(), it->base, it->fileCount); return true; } diff --git a/engines/groovie/debug.cpp b/engines/groovie/debug.cpp index 8103e4f4c6..16db20413f 100644 --- a/engines/groovie/debug.cpp +++ b/engines/groovie/debug.cpp @@ -36,16 +36,16 @@ Debugger::Debugger(GroovieEngine *vm) : _vm(vm), _script(_vm->_script) { // Register the debugger comands - DCmd_Register("step", WRAP_METHOD(Debugger, cmd_step)); - DCmd_Register("go", WRAP_METHOD(Debugger, cmd_go)); - DCmd_Register("pc", WRAP_METHOD(Debugger, cmd_pc)); - DCmd_Register("fg", WRAP_METHOD(Debugger, cmd_fg)); - DCmd_Register("bg", WRAP_METHOD(Debugger, cmd_bg)); - DCmd_Register("mem", WRAP_METHOD(Debugger, cmd_mem)); - DCmd_Register("load", WRAP_METHOD(Debugger, cmd_loadgame)); - DCmd_Register("save", WRAP_METHOD(Debugger, cmd_savegame)); - DCmd_Register("playref", WRAP_METHOD(Debugger, cmd_playref)); - DCmd_Register("dumppal", WRAP_METHOD(Debugger, cmd_dumppal)); + registerCmd("step", WRAP_METHOD(Debugger, cmd_step)); + registerCmd("go", WRAP_METHOD(Debugger, cmd_go)); + registerCmd("pc", WRAP_METHOD(Debugger, cmd_pc)); + registerCmd("fg", WRAP_METHOD(Debugger, cmd_fg)); + registerCmd("bg", WRAP_METHOD(Debugger, cmd_bg)); + registerCmd("mem", WRAP_METHOD(Debugger, cmd_mem)); + registerCmd("load", WRAP_METHOD(Debugger, cmd_loadgame)); + registerCmd("save", WRAP_METHOD(Debugger, cmd_savegame)); + registerCmd("playref", WRAP_METHOD(Debugger, cmd_playref)); + registerCmd("dumppal", WRAP_METHOD(Debugger, cmd_dumppal)); } Debugger::~Debugger() { @@ -81,7 +81,7 @@ bool Debugger::cmd_pc(int argc, const char **argv) { int val = getNumber(argv[1]); _script->_currentInstruction = val; } - DebugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction); + debugPrintf("pc = 0x%04X (%d)\n", _script->_currentInstruction, _script->_currentInstruction); return true; } @@ -97,9 +97,9 @@ bool Debugger::cmd_mem(int argc, const char **argv) { // Get val = _script->_variables[pos]; } - DebugPrintf("mem[0x%04X] = 0x%02X\n", pos, val); + debugPrintf("mem[0x%04X] = 0x%02X\n", pos, val); } else { - DebugPrintf("Syntax: mem <addr> [<val>]\n"); + debugPrintf("Syntax: mem <addr> [<val>]\n"); } return true; } @@ -109,7 +109,7 @@ bool Debugger::cmd_loadgame(int argc, const char **argv) { int slot = getNumber(argv[1]); _script->loadgame(slot); } else { - DebugPrintf("Syntax: load <slot>\n"); + debugPrintf("Syntax: load <slot>\n"); } return true; } @@ -119,7 +119,7 @@ bool Debugger::cmd_savegame(int argc, const char **argv) { int slot = getNumber(argv[1]); _script->savegame(slot); } else { - DebugPrintf("Syntax: save <slot>\n"); + debugPrintf("Syntax: save <slot>\n"); } return true; } @@ -129,7 +129,7 @@ bool Debugger::cmd_playref(int argc, const char **argv) { int ref = getNumber(argv[1]); _script->playvideofromref(ref); } else { - DebugPrintf("Syntax: playref <videorefnum>\n"); + debugPrintf("Syntax: playref <videorefnum>\n"); } return true; } @@ -140,7 +140,7 @@ bool Debugger::cmd_dumppal(int argc, const char **argv) { _vm->_system->getPaletteManager()->grabPalette(palettedump, 0, 256); for (i = 0; i < 256; i++) { - DebugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]); + debugPrintf("%3d: %3d,%3d,%3d\n", i, palettedump[(i * 3)], palettedump[(i * 3) + 1], palettedump[(i * 3) + 2]); } return true; } diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp index 1307cd5796..84d5c631c7 100644 --- a/engines/hopkins/computer.cpp +++ b/engines/hopkins/computer.cpp @@ -38,10 +38,9 @@ namespace Hopkins { ComputerManager::ComputerManager(HopkinsEngine *vm) { _vm = vm; - for (int i = 0; i < 50; i++) { - _menuText[i]._actvFl = false; + for (int i = 0; i < ARRAYSIZE(_menuText); i++) { _menuText[i]._lineSize = 0; - memset(_menuText[i]._line, 0, 90); + memset(_menuText[i]._line, 0, ARRAYSIZE(_menuText[0]._line)); } Common::fill(&_inputBuf[0], &_inputBuf[200], '\0'); _breakoutSpr = NULL; @@ -346,6 +345,7 @@ static const char _spanishText[] = * Load Menu data */ void ComputerManager::loadMenu() { + debug(9, "ComputerManager::loadMenu()"); char *ptr; if (_vm->_fileIO->fileExists("COMPUTAN.TXT")) { ptr = (char *)_vm->_fileIO->loadFile("COMPUTAN.TXT"); @@ -353,46 +353,52 @@ void ComputerManager::loadMenu() { switch (_vm->_globals->_language) { case LANG_FR: ptr = (char *)_vm->_globals->allocMemory(sizeof(_frenchText)); - strcpy(ptr, _frenchText); + Common::strlcpy(ptr, _frenchText, sizeof(_frenchText)); break; case LANG_SP: ptr = (char *)_vm->_globals->allocMemory(sizeof(_spanishText)); - strcpy(ptr, _spanishText); + Common::strlcpy(ptr, _spanishText, sizeof(_spanishText)); break; default: ptr = (char *)_vm->_globals->allocMemory(sizeof(_englishText)); - strcpy(ptr, _englishText); + Common::strlcpy(ptr, _englishText, sizeof(_englishText)); break; } } char *tmpPtr = ptr; int lineNum = 0; - int strPos; - bool loopCond = false; - do { - if (tmpPtr[0] == '%') { - if (tmpPtr[1] == '%') { - loopCond = true; - break; - } - _menuText[lineNum]._actvFl = 1; - strPos = 0; - while (strPos <= 89) { + const char lineSep = tmpPtr[0]; + + while (tmpPtr[0] != '\0' && lineNum < ARRAYSIZE(_menuText)) { + if (tmpPtr[0] == '%' && tmpPtr[1] == '%') { + // End of file marker found - Break out of parse loop + break; + } + + if (tmpPtr[0] == lineSep) { + int strPos = 0; + while (strPos < ARRAYSIZE(_menuText[0]._line)) { char curChar = tmpPtr[strPos + 2]; - if (curChar == '%' || curChar == 10) + if (curChar == '\0' || curChar == lineSep || curChar == 0x0a) // Line Feed break; _menuText[lineNum]._line[strPos++] = curChar; } - if (strPos <= 89) { + + if (strPos < ARRAYSIZE(_menuText[0]._line)) { _menuText[lineNum]._line[strPos] = 0; _menuText[lineNum]._lineSize = strPos - 1; } - ++lineNum; + + if (strPos != 0) { + debug(9, "_menuText[%d]._line (size: %d): \"%s\"", lineNum, _menuText[lineNum]._lineSize, _menuText[lineNum]._line); + ++lineNum; + } } ++tmpPtr; - } while (!loopCond); + } + _vm->_globals->freeMemory((byte *)ptr); } diff --git a/engines/hopkins/computer.h b/engines/hopkins/computer.h index e8857a234b..ba50dca4cf 100644 --- a/engines/hopkins/computer.h +++ b/engines/hopkins/computer.h @@ -31,22 +31,22 @@ namespace Hopkins { class HopkinsEngine; -struct MenuItem { - bool _actvFl; - int _lineSize; - char _line[90]; -}; - -struct ScoreItem { - Common::String _name; - Common::String _score; -}; - enum ComputerEnum { COMPUTER_HOPKINS = 1, COMPUTER_SAMANTHA = 2, COMPUTER_PUBLIC = 3 }; class ComputerManager { private: HopkinsEngine *_vm; + + struct MenuItem { + int _lineSize; + char _line[90]; + }; + + struct ScoreItem { + Common::String _name; + Common::String _score; + }; + MenuItem _menuText[50]; char _inputBuf[200]; ScoreItem _score[6]; @@ -84,14 +84,14 @@ private: void displayLives(); void displayBricks(); void displayGamesSubMenu(); - int displayHiscores(); + int displayHiscores(); void displayHiscoreLine(const byte *objectData, int x, int y, int curChar); void displayMessage(int xp, int yp, int textIdx); void displayScore(); void displayScoreChar(int charPos, int charDisp); void getScoreName(); void playBreakout(); - int moveBall(); + int moveBall(); void saveScore(); void checkBallCollisions(); diff --git a/engines/hopkins/debugger.cpp b/engines/hopkins/debugger.cpp index 14b1c183a8..3dcfdfea7b 100644 --- a/engines/hopkins/debugger.cpp +++ b/engines/hopkins/debugger.cpp @@ -30,18 +30,18 @@ namespace Hopkins { Debugger::Debugger(HopkinsEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("rects", WRAP_METHOD(Debugger, cmd_DirtyRects)); - DCmd_Register("teleport", WRAP_METHOD(Debugger, cmd_Teleport)); - DCmd_Register("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom)); - DCmd_Register("zones", WRAP_METHOD(Debugger, cmd_Zones)); - DCmd_Register("lines", WRAP_METHOD(Debugger, cmd_Lines)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("rects", WRAP_METHOD(Debugger, cmd_DirtyRects)); + registerCmd("teleport", WRAP_METHOD(Debugger, cmd_Teleport)); + registerCmd("show_room", WRAP_METHOD(Debugger, cmd_ShowCurrentRoom)); + registerCmd("zones", WRAP_METHOD(Debugger, cmd_Zones)); + registerCmd("lines", WRAP_METHOD(Debugger, cmd_Lines)); } // Turns dirty rects on or off bool Debugger::cmd_DirtyRects(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showDirtyRects = !strcmp(argv[1], "on"); @@ -52,7 +52,7 @@ bool Debugger::cmd_DirtyRects(int argc, const char **argv) { // Change room number bool Debugger::cmd_Teleport(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [Room number]\n", argv[0]); + debugPrintf("%s: [Room number]\n", argv[0]); return true; } else { _vm->_globals->_exitId = atoi(argv[1]); @@ -62,13 +62,13 @@ bool Debugger::cmd_Teleport(int argc, const char **argv) { // Display room number bool Debugger::cmd_ShowCurrentRoom(int argc, const char **argv) { - DebugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum); + debugPrintf("Current room: %d\n", _vm->_globals->_curRoomNum); return true; } bool Debugger::cmd_Zones(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showZones = !strcmp(argv[1], "on"); @@ -78,7 +78,7 @@ if (argc != 2) { bool Debugger::cmd_Lines(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("%s: [on | off]\n", argv[0]); + debugPrintf("%s: [on | off]\n", argv[0]); return true; } else { _vm->_graphicsMan->_showLines = !strcmp(argv[1], "on"); diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp index 75f429f860..6620f2878c 100644 --- a/engines/hopkins/files.cpp +++ b/engines/hopkins/files.cpp @@ -51,12 +51,13 @@ byte *FileManager::loadFile(const Common::String &file) { // Allocate space for the file contents size_t filesize = f.size(); - byte *data = _vm->_globals->allocMemory(filesize); + byte *data = _vm->_globals->allocMemory(filesize+1); if (!data) error("Error allocating space for file being loaded - %s", file.c_str()); readStream(f, data, filesize); f.close(); + data[filesize] = '\0'; return data; } diff --git a/engines/hugo/console.cpp b/engines/hugo/console.cpp index 56025bfbfd..d02c42658f 100644 --- a/engines/hugo/console.cpp +++ b/engines/hugo/console.cpp @@ -30,12 +30,12 @@ namespace Hugo { HugoConsole::HugoConsole(HugoEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens)); - DCmd_Register("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects)); - DCmd_Register("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject)); - DCmd_Register("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects)); - DCmd_Register("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen)); - DCmd_Register("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries)); + registerCmd("listscreens", WRAP_METHOD(HugoConsole, Cmd_listScreens)); + registerCmd("listobjects", WRAP_METHOD(HugoConsole, Cmd_listObjects)); + registerCmd("getobject", WRAP_METHOD(HugoConsole, Cmd_getObject)); + registerCmd("getallobjects", WRAP_METHOD(HugoConsole, Cmd_getAllObjects)); + registerCmd("gotoscreen", WRAP_METHOD(HugoConsole, Cmd_gotoScreen)); + registerCmd("Boundaries", WRAP_METHOD(HugoConsole, Cmd_boundaries)); } HugoConsole::~HugoConsole() { @@ -62,7 +62,7 @@ static int strToInt(const char *s) { */ bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) { if ((argc != 2) || (strToInt(argv[1]) > _vm->_numScreens)){ - DebugPrintf("Usage: %s <screen number>\n", argv[0]); + debugPrintf("Usage: %s <screen number>\n", argv[0]); return true; } @@ -75,13 +75,13 @@ bool HugoConsole::Cmd_gotoScreen(int argc, const char **argv) { */ bool HugoConsole::Cmd_listScreens(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available screens for this game are:\n"); + debugPrintf("Available screens for this game are:\n"); for (int i = 0; i < _vm->_numScreens; i++) - DebugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i)); + debugPrintf("%2d - %s\n", i, _vm->_text->getScreenNames(i)); return true; } @@ -90,14 +90,14 @@ bool HugoConsole::Cmd_listScreens(int argc, const char **argv) { */ bool HugoConsole::Cmd_listObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); + debugPrintf("Available objects for this game are:\n"); for (int i = 0; i < _vm->_object->_numObj; i++) { if (_vm->_object->_objects[i]._genericCmd & TAKE) - DebugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2)); + debugPrintf("%2d - %s\n", i, _vm->_text->getNoun(_vm->_object->_objects[i]._nounIndex, 2)); } return true; } @@ -107,14 +107,14 @@ bool HugoConsole::Cmd_listObjects(int argc, const char **argv) { */ bool HugoConsole::Cmd_getObject(int argc, const char **argv) { if ((argc != 2) || (strToInt(argv[1]) > _vm->_object->_numObj)) { - DebugPrintf("Usage: %s <object number>\n", argv[0]); + debugPrintf("Usage: %s <object number>\n", argv[0]); return true; } if (_vm->_object->_objects[strToInt(argv[1])]._genericCmd & TAKE) _vm->_parser->takeObject(&_vm->_object->_objects[strToInt(argv[1])]); else - DebugPrintf("Object not available\n"); + debugPrintf("Object not available\n"); return true; } @@ -124,7 +124,7 @@ bool HugoConsole::Cmd_getObject(int argc, const char **argv) { */ bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } @@ -141,7 +141,7 @@ bool HugoConsole::Cmd_getAllObjects(int argc, const char **argv) { */ bool HugoConsole::Cmd_boundaries(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index e4806afb70..4a90722a35 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -40,45 +40,45 @@ Debugger::Debugger(KyraEngine_v1 *vm) } void Debugger::initialize() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("screen_debug_mode", WRAP_METHOD(Debugger, cmd_setScreenDebug)); - DCmd_Register("load_palette", WRAP_METHOD(Debugger, cmd_loadPalette)); - DCmd_Register("facings", WRAP_METHOD(Debugger, cmd_showFacings)); - DCmd_Register("gamespeed", WRAP_METHOD(Debugger, cmd_gameSpeed)); - DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags)); - DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag)); - DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag)); - DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers)); - DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown)); -} - -bool Debugger::cmd_setScreenDebug(int argc, const char **argv) { + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("screen_debug_mode", WRAP_METHOD(Debugger, cmdSetScreenDebug)); + registerCmd("load_palette", WRAP_METHOD(Debugger, cmdLoadPalette)); + registerCmd("facings", WRAP_METHOD(Debugger, cmdShowFacings)); + registerCmd("gamespeed", WRAP_METHOD(Debugger, cmdGameSpeed)); + registerCmd("flags", WRAP_METHOD(Debugger, cmdListFlags)); + registerCmd("toggleflag", WRAP_METHOD(Debugger, cmdToggleFlag)); + registerCmd("queryflag", WRAP_METHOD(Debugger, cmdQueryFlag)); + registerCmd("timers", WRAP_METHOD(Debugger, cmdListTimers)); + registerCmd("settimercountdown", WRAP_METHOD(Debugger, cmdSetTimerCountdown)); +} + +bool Debugger::cmdSetScreenDebug(int argc, const char **argv) { if (argc > 1) { if (scumm_stricmp(argv[1], "enable") == 0) _vm->screen()->enableScreenDebug(true); else if (scumm_stricmp(argv[1], "disable") == 0) _vm->screen()->enableScreenDebug(false); else - DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); + debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); } else { - DebugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled")); - DebugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); + debugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled")); + debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n"); } return true; } -bool Debugger::cmd_loadPalette(int argc, const char **argv) { +bool Debugger::cmdLoadPalette(int argc, const char **argv) { Palette palette(_vm->screen()->getPalette(0).getNumColors()); if (argc <= 1) { - DebugPrintf("Use load_palette <file> [start_col] [end_col]\n"); + debugPrintf("Use load_palette <file> [start_col] [end_col]\n"); return true; } if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) { uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)]; if (!buffer) { - DebugPrintf("ERROR: Cannot allocate buffer for screen region!\n"); + debugPrintf("ERROR: Cannot allocate buffer for screen region!\n"); return true; } @@ -89,7 +89,7 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { delete[] buffer; } else if (!_vm->screen()->loadPalette(argv[1], palette)) { - DebugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); + debugPrintf("ERROR: Palette '%s' not found!\n", argv[1]); return true; } @@ -111,87 +111,87 @@ bool Debugger::cmd_loadPalette(int argc, const char **argv) { return true; } -bool Debugger::cmd_showFacings(int argc, const char **argv) { - DebugPrintf("Facing directions:\n"); - DebugPrintf("7 0 1\n"); - DebugPrintf(" \\ | / \n"); - DebugPrintf("6--*--2\n"); - DebugPrintf(" / | \\\n"); - DebugPrintf("5 4 3\n"); +bool Debugger::cmdShowFacings(int argc, const char **argv) { + debugPrintf("Facing directions:\n"); + debugPrintf("7 0 1\n"); + debugPrintf(" \\ | / \n"); + debugPrintf("6--*--2\n"); + debugPrintf(" / | \\\n"); + debugPrintf("5 4 3\n"); return true; } -bool Debugger::cmd_gameSpeed(int argc, const char **argv) { +bool Debugger::cmdGameSpeed(int argc, const char **argv) { if (argc == 2) { int val = atoi(argv[1]); if (val < 1 || val > 1000) { - DebugPrintf("speed must lie between 1 and 1000 (default: 60)\n"); + debugPrintf("speed must lie between 1 and 1000 (default: 60)\n"); return true; } _vm->_tickLength = (uint8)(1000.0 / val); } else { - DebugPrintf("Syntax: gamespeed <value>\n"); + debugPrintf("Syntax: gamespeed <value>\n"); } return true; } -bool Debugger::cmd_listFlags(int argc, const char **argv) { +bool Debugger::cmdListFlags(int argc, const char **argv) { for (int i = 0, p = 0; i < (int)sizeof(_vm->_flagsTable) * 8; i++, ++p) { - DebugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i)); + debugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i)); if (p == 5) { - DebugPrintf("\n"); + debugPrintf("\n"); p -= 6; } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger::cmd_toggleFlag(int argc, const char **argv) { +bool Debugger::cmdToggleFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); if (_vm->queryGameFlag(flag)) _vm->resetGameFlag(flag); else _vm->setGameFlag(flag); - DebugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag)); + debugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag)); } else { - DebugPrintf("Syntax: toggleflag <flag>\n"); + debugPrintf("Syntax: toggleflag <flag>\n"); } return true; } -bool Debugger::cmd_queryFlag(int argc, const char **argv) { +bool Debugger::cmdQueryFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); - DebugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag)); + debugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag)); } else { - DebugPrintf("Syntax: queryflag <flag>\n"); + debugPrintf("Syntax: queryflag <flag>\n"); } return true; } -bool Debugger::cmd_listTimers(int argc, const char **argv) { - DebugPrintf("Current time: %-8u\n", g_system->getMillis()); +bool Debugger::cmdListTimers(int argc, const char **argv) { + debugPrintf("Current time: %-8u\n", g_system->getMillis()); for (int i = 0; i < _vm->timer()->count(); i++) - DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i)); + debugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i)); return true; } -bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { +bool Debugger::cmdSetTimerCountdown(int argc, const char **argv) { if (argc > 2) { uint timer = atoi(argv[1]); uint countdown = atoi(argv[2]); _vm->timer()->setCountdown(timer, countdown); - DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer)); + debugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer)); } else { - DebugPrintf("Syntax: settimercountdown <timer> <countdown>\n"); + debugPrintf("Syntax: settimercountdown <timer> <countdown>\n"); } return true; @@ -204,21 +204,21 @@ Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm) } void Debugger_LoK::initialize() { - DCmd_Register("enter", WRAP_METHOD(Debugger_LoK, cmd_enterRoom)); - DCmd_Register("scenes", WRAP_METHOD(Debugger_LoK, cmd_listScenes)); - DCmd_Register("give", WRAP_METHOD(Debugger_LoK, cmd_giveItem)); - DCmd_Register("birthstones", WRAP_METHOD(Debugger_LoK, cmd_listBirthstones)); + registerCmd("enter", WRAP_METHOD(Debugger_LoK, cmdEnterRoom)); + registerCmd("scenes", WRAP_METHOD(Debugger_LoK, cmdListScenes)); + registerCmd("give", WRAP_METHOD(Debugger_LoK, cmdGiveItem)); + registerCmd("birthstones", WRAP_METHOD(Debugger_LoK, cmdListBirthstones)); Debugger::initialize(); } -bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { +bool Debugger_LoK::cmdEnterRoom(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int room = atoi(argv[1]); // game will crash if entering a non-existent room if (room >= _vm->_roomTableSize) { - DebugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1); + debugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1); return true; } @@ -246,44 +246,44 @@ bool Debugger_LoK::cmd_enterRoom(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: room <roomnum> <direction>\n"); + debugPrintf("Syntax: room <roomnum> <direction>\n"); return true; } -bool Debugger_LoK::cmd_listScenes(int argc, const char **argv) { +bool Debugger_LoK::cmdListScenes(int argc, const char **argv) { for (int i = 0; i < _vm->_roomTableSize; i++) { - DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); + debugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); if (!(i % 8)) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); - DebugPrintf("Current room: %i\n", _vm->_currentRoom); + debugPrintf("\n"); + debugPrintf("Current room: %i\n", _vm->_currentRoom); return true; } -bool Debugger_LoK::cmd_giveItem(int argc, const char **argv) { +bool Debugger_LoK::cmdGiveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); // Kyrandia 1 has only 108 items (-1 to 106), otherwise it will crash if (item < -1 || item > 106) { - DebugPrintf("'itemid' must be any value between (including) -1 and 106\n"); + debugPrintf("'itemid' must be any value between (including) -1 and 106\n"); return true; } _vm->setMouseItem(item); _vm->_itemInHand = item; } else { - DebugPrintf("Syntax: give <itemid>\n"); + debugPrintf("Syntax: give <itemid>\n"); } return true; } -bool Debugger_LoK::cmd_listBirthstones(int argc, const char **argv) { - DebugPrintf("Needed birthstone gems:\n"); +bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) { + debugPrintf("Needed birthstone gems:\n"); for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i) - DebugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); + debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]); return true; } @@ -293,23 +293,23 @@ Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) { } void Debugger_v2::initialize() { - DCmd_Register("character_info", WRAP_METHOD(Debugger_v2, cmd_characterInfo)); - DCmd_Register("enter", WRAP_METHOD(Debugger_v2, cmd_enterScene)); - DCmd_Register("scenes", WRAP_METHOD(Debugger_v2, cmd_listScenes)); - DCmd_Register("scene_info", WRAP_METHOD(Debugger_v2, cmd_sceneInfo)); - DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v2, cmd_sceneToFacing)); - DCmd_Register("give", WRAP_METHOD(Debugger_v2, cmd_giveItem)); + registerCmd("character_info", WRAP_METHOD(Debugger_v2, cmdCharacterInfo)); + registerCmd("enter", WRAP_METHOD(Debugger_v2, cmdEnterScene)); + registerCmd("scenes", WRAP_METHOD(Debugger_v2, cmdListScenes)); + registerCmd("scene_info", WRAP_METHOD(Debugger_v2, cmdSceneInfo)); + registerCmd("scene_to_facing", WRAP_METHOD(Debugger_v2, cmdSceneToFacing)); + registerCmd("give", WRAP_METHOD(Debugger_v2, cmdGiveItem)); Debugger::initialize(); } -bool Debugger_v2::cmd_enterScene(int argc, const char **argv) { +bool Debugger_v2::cmdEnterScene(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int scene = atoi(argv[1]); // game will crash if entering a non-existent scene if (scene >= _vm->_sceneListSize) { - DebugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1); + debugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1); return true; } @@ -337,40 +337,40 @@ bool Debugger_v2::cmd_enterScene(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]); + debugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]); return true; } -bool Debugger_v2::cmd_listScenes(int argc, const char **argv) { +bool Debugger_v2::cmdListScenes(int argc, const char **argv) { int shown = 1; for (int i = 0; i < _vm->_sceneListSize; ++i) { if (_vm->_sceneList[i].filename1[0]) { - DebugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1); + debugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1); if (!(shown % 5)) - DebugPrintf("\n"); + debugPrintf("\n"); ++shown; } } - DebugPrintf("\n"); - DebugPrintf("Current scene: %i\n", _vm->_currentScene); + debugPrintf("\n"); + debugPrintf("Current scene: %i\n", _vm->_currentScene); return true; } -bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) { - DebugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1); - DebugPrintf("\n"); - DebugPrintf("Exit information:\n"); - DebugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); - DebugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); - DebugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); - DebugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); - DebugPrintf("Special exit information:\n"); +bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) { + debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1); + debugPrintf("\n"); + debugPrintf("Exit information:\n"); + debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); + debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); + debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); + debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); + debugPrintf("Special exit information:\n"); if (!_vm->_specialExitCount) { - DebugPrintf("No special exits.\n"); + debugPrintf("No special exits.\n"); } else { - DebugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); + debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); for (int i = 0; i < _vm->_specialExitCount; ++i) { - DebugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, + debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, _vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i], _vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]); } @@ -379,20 +379,20 @@ bool Debugger_v2::cmd_sceneInfo(int argc, const char **argv) { return true; } -bool Debugger_v2::cmd_characterInfo(int argc, const char **argv) { - DebugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1); - DebugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1); - DebugPrintf("Facing: %d\n", _vm->_mainCharacter.facing); - DebugPrintf("Inventory:\n"); +bool Debugger_v2::cmdCharacterInfo(int argc, const char **argv) { + debugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1); + debugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1); + debugPrintf("Facing: %d\n", _vm->_mainCharacter.facing); + debugPrintf("Inventory:\n"); for (int i = 0; i < 20; ++i) { - DebugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i])); + debugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i])); if (i == 9 || i == 19) - DebugPrintf("\n"); + debugPrintf("\n"); } return true; } -bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) { +bool Debugger_v2::cmdSceneToFacing(int argc, const char **argv) { if (argc == 2) { int facing = atoi(argv[1]); int16 exit = -1; @@ -418,26 +418,26 @@ bool Debugger_v2::cmd_sceneToFacing(int argc, const char **argv) { break; } - DebugPrintf("Exit to facing %d leads to room %d.\n", facing, exit); + debugPrintf("Exit to facing %d leads to room %d.\n", facing, exit); } else { - DebugPrintf("Usage: %s <facing>\n", argv[0]); + debugPrintf("Usage: %s <facing>\n", argv[0]); } return true; } -bool Debugger_v2::cmd_giveItem(int argc, const char **argv) { +bool Debugger_v2::cmdGiveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); if (item < -1 || item > _vm->engineDesc().maxItemId) { - DebugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId); + debugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId); return true; } _vm->setHandItem(item); } else { - DebugPrintf("Syntax: give <itemid>\n"); + debugPrintf("Syntax: give <itemid>\n"); } return true; @@ -449,22 +449,22 @@ Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) { } void Debugger_HoF::initialize() { - DCmd_Register("pass_codes", WRAP_METHOD(Debugger_HoF, cmd_passcodes)); + registerCmd("pass_codes", WRAP_METHOD(Debugger_HoF, cmdPasscodes)); Debugger_v2::initialize(); } -bool Debugger_HoF::cmd_passcodes(int argc, const char **argv) { +bool Debugger_HoF::cmdPasscodes(int argc, const char **argv) { if (argc == 2) { int val = atoi(argv[1]); if (val < 0 || val > 1) { - DebugPrintf("value must be either 1 (on) or 0 (off)\n"); + debugPrintf("value must be either 1 (on) or 0 (off)\n"); return true; } _vm->_dbgPass = val; } else { - DebugPrintf("Syntax: pass_codes <0/1>\n"); + debugPrintf("Syntax: pass_codes <0/1>\n"); } return true; @@ -482,43 +482,43 @@ Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) { } void Debugger_EoB::initialize() { - DCmd_Register("import_savefile", WRAP_METHOD(Debugger_EoB, cmd_importSaveFile)); - DCmd_Register("save_original", WRAP_METHOD(Debugger_EoB, cmd_saveOriginal)); - DCmd_Register("list_monsters", WRAP_METHOD(Debugger_EoB, cmd_listMonsters)); - DCmd_Register("show_position", WRAP_METHOD(Debugger_EoB, cmd_showPosition)); - DCmd_Register("set_position", WRAP_METHOD(Debugger_EoB, cmd_setPosition)); - DCmd_Register("open_door", WRAP_METHOD(Debugger_EoB, cmd_openDoor)); - DCmd_Register("close_door", WRAP_METHOD(Debugger_EoB, cmd_closeDoor)); - DCmd_Register("list_flags", WRAP_METHOD(Debugger_EoB, cmd_listFlags)); - DCmd_Register("set_flag", WRAP_METHOD(Debugger_EoB, cmd_setFlag)); - DCmd_Register("clear_flag", WRAP_METHOD(Debugger_EoB, cmd_clearFlag)); -} - -bool Debugger_EoB::cmd_importSaveFile(int argc, const char **argv) { + registerCmd("import_savefile", WRAP_METHOD(Debugger_EoB, cmdImportSaveFile)); + registerCmd("save_original", WRAP_METHOD(Debugger_EoB, cmdSaveOriginal)); + registerCmd("list_monsters", WRAP_METHOD(Debugger_EoB, cmdListMonsters)); + registerCmd("show_position", WRAP_METHOD(Debugger_EoB, cmdShowPosition)); + registerCmd("set_position", WRAP_METHOD(Debugger_EoB, cmdSetPosition)); + registerCmd("open_door", WRAP_METHOD(Debugger_EoB, cmdOpenDoor)); + registerCmd("close_door", WRAP_METHOD(Debugger_EoB, cmdCloseDoor)); + registerCmd("list_flags", WRAP_METHOD(Debugger_EoB, cmdListFlags)); + registerCmd("set_flag", WRAP_METHOD(Debugger_EoB, cmdSetFlag)); + registerCmd("clear_flag", WRAP_METHOD(Debugger_EoB, cmdClearFlag)); +} + +bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) { if (!_vm->_allowImport) { - DebugPrintf("This command only works from the main menu.\n"); + debugPrintf("This command only works from the main menu.\n"); return true; } if (argc == 3) { int slot = atoi(argv[1]); if (slot < -1 || slot > 989) { - DebugPrintf("slot must be between (including) -1 and 989 \n"); + debugPrintf("slot must be between (including) -1 and 989 \n"); return true; } - DebugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n"); + debugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n"); _vm->loadItemDefs(); } else { - DebugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n"); + debugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and puts them into the first available slots.)\n\n"); } return true; } -bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) { +bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) { if (!_vm->_runFlag) { - DebugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n"); + debugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n"); return true; } @@ -535,57 +535,57 @@ bool Debugger_EoB::cmd_saveOriginal(int argc, const char **argv) { if (_vm->saveAsOriginalSaveFile()) { Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV")); if (nf.isReadable()) - DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); + debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); else - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } else { - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } } else { - DebugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n"); + debugPrintf("Syntax: save_original\n (Saves game in original file format to a file which can be used with the orginal game executable.)\n\n"); } return true; } else if (argc == 2) { int slot = atoi(argv[1]); if (slot < 0 || slot > 5) { - DebugPrintf("Slot must be between (including) 0 and 5.\n"); + debugPrintf("Slot must be between (including) 0 and 5.\n"); } else if (_vm->saveAsOriginalSaveFile(slot)) { Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot)); if (nf.isReadable()) - DebugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); + debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str()); else - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } else { - DebugPrintf("Failure.\n"); + debugPrintf("Failure.\n"); } return true; } - DebugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n"); + debugPrintf("Syntax: save_original <slot>\n (Saves game in original file format to a file which can be used with the orginal game executable.\n A save slot between 0 and 5 must be specified.)\n\n"); return true; } -bool Debugger_EoB::cmd_listMonsters(int, const char **) { - DebugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel); - DebugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n"); +bool Debugger_EoB::cmdListMonsters(int, const char **) { + debugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel); + debugPrintf("Id Type Unit Block Position Direction Sub Level Mode Dst.block HP Flags\n--------------------------------------------------------------------------------------------------------------\n"); for (int i = 0; i < 30; i++) { EoBMonsterInPlay *m = &_vm->_monsters[i]; - DebugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags); + debugPrintf("%.02d %.02d %.02d 0x%.04x %d %d %d %.02d 0x%.04x %.03d/%.03d 0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger_EoB::cmd_showPosition(int, const char **) { - DebugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection); +bool Debugger_EoB::cmdShowPosition(int, const char **) { + debugPrintf("\nCurrent level: %d\nCurrent Sub Level: %d\nCurrent block: %d (0x%.04x)\nNext block: %d (0x%.04x)\nCurrent direction: %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection); return true; } -bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { +bool Debugger_EoB::cmdSetPosition(int argc, const char **argv) { if (argc == 4) { _vm->_currentBlock = atoi(argv[3]); int sub = atoi(argv[2]); @@ -593,7 +593,7 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { int maxLevel = (_vm->game() == GI_EOB1) ? 12 : 16; if (level < 1 || level > maxLevel) { - DebugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel); + debugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel); return true; } @@ -613,83 +613,83 @@ bool Debugger_EoB::cmd_setPosition(int argc, const char **argv) { _vm->_sceneUpdateRequired = true; _vm->gui_drawAllCharPortraitsWithStats(); - DebugPrintf("Success.\n\n"); + debugPrintf("Success.\n\n"); } else { - DebugPrintf("Syntax: set_position <level>, <sub level>, <block>\n"); - DebugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n"); + debugPrintf("Syntax: set_position <level>, <sub level>, <block>\n"); + debugPrintf(" (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n"); } return true; } -bool Debugger_EoB::cmd_openDoor(int, const char **) { - DebugPrintf("Warning: Using this command may cause glitches.\n"); +bool Debugger_EoB::cmdOpenDoor(int, const char **) { + debugPrintf("Warning: Using this command may cause glitches.\n"); uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection); int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1; int v = _vm->_levelBlockProperties[block].walls[c]; int flg = (_vm->_flags.gameID == GI_EOB1) ? 1 : 0x10; if (_vm->_wllWallFlags[v] & flg) { - DebugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n"); + debugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n"); } else { _vm->openDoor(block); - DebugPrintf("Trying to open door at block %d.\n\n", block); + debugPrintf("Trying to open door at block %d.\n\n", block); } return true; } -bool Debugger_EoB::cmd_closeDoor(int, const char **) { - DebugPrintf("Warning: Using this command may cause glitches.\n"); +bool Debugger_EoB::cmdCloseDoor(int, const char **) { + debugPrintf("Warning: Using this command may cause glitches.\n"); uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection); int c = (_vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1; int v = _vm->_levelBlockProperties[block].walls[c]; if ((_vm->_flags.gameID == GI_EOB1 && !(_vm->_wllWallFlags[v] & 1)) || (_vm->_flags.gameID == GI_EOB2 && (_vm->_wllWallFlags[v] & 0x20))) { - DebugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n"); + debugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n"); } else { _vm->closeDoor(block); - DebugPrintf("Trying to close door at block %d.\n\n", block); + debugPrintf("Trying to close door at block %d.\n\n", block); } return true; } -bool Debugger_EoB::cmd_listFlags(int, const char **) { - DebugPrintf("Flag Status\n----------------------\n\n"); +bool Debugger_EoB::cmdListFlags(int, const char **) { + debugPrintf("Flag Status\n----------------------\n\n"); for (int i = 0; i < 32; i++) { uint32 flag = 1 << i; - DebugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE"); + debugPrintf("%.2d %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } -bool Debugger_EoB::cmd_setFlag(int argc, const char **argv) { +bool Debugger_EoB::cmdSetFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: set_flag <flag>\n\n"); + debugPrintf("Syntax: set_flag <flag>\n\n"); return true; } int flag = atoi(argv[1]); if (flag < 0 || flag > 31) { - DebugPrintf("<flag> must be a value from 0 to 31.\n\n"); + debugPrintf("<flag> must be a value from 0 to 31.\n\n"); } else { _vm->setScriptFlags(1 << flag); - DebugPrintf("Flag '%.2d' has been set.\n\n", flag); + debugPrintf("Flag '%.2d' has been set.\n\n", flag); } return true; } -bool Debugger_EoB::cmd_clearFlag(int argc, const char **argv) { +bool Debugger_EoB::cmdClearFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: clear_flag <flag>\n\n"); + debugPrintf("Syntax: clear_flag <flag>\n\n"); return true; } int flag = atoi(argv[1]); if (flag < 0 || flag > 31) { - DebugPrintf("<flag> must be a value from 0 to 31.\n\n"); + debugPrintf("<flag> must be a value from 0 to 31.\n\n"); } else { _vm->clearScriptFlags(1 << flag); - DebugPrintf("Flag '%.2d' has been cleared.\n\n", flag); + debugPrintf("Flag '%.2d' has been cleared.\n\n", flag); } return true; diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index aaf7c51c18..15cee2d592 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -42,15 +42,15 @@ public: protected: KyraEngine_v1 *_vm; - bool cmd_setScreenDebug(int argc, const char **argv); - bool cmd_loadPalette(int argc, const char **argv); - bool cmd_showFacings(int argc, const char **argv); - bool cmd_gameSpeed(int argc, const char **argv); - bool cmd_listFlags(int argc, const char **argv); - bool cmd_toggleFlag(int argc, const char **argv); - bool cmd_queryFlag(int argc, const char **argv); - bool cmd_listTimers(int argc, const char **argv); - bool cmd_setTimerCountdown(int argc, const char **argv); + bool cmdSetScreenDebug(int argc, const char **argv); + bool cmdLoadPalette(int argc, const char **argv); + bool cmdShowFacings(int argc, const char **argv); + bool cmdGameSpeed(int argc, const char **argv); + bool cmdListFlags(int argc, const char **argv); + bool cmdToggleFlag(int argc, const char **argv); + bool cmdQueryFlag(int argc, const char **argv); + bool cmdListTimers(int argc, const char **argv); + bool cmdSetTimerCountdown(int argc, const char **argv); }; class Debugger_LoK : public Debugger { @@ -62,10 +62,10 @@ public: protected: KyraEngine_LoK *_vm; - bool cmd_enterRoom(int argc, const char **argv); - bool cmd_listScenes(int argc, const char **argv); - bool cmd_giveItem(int argc, const char **argv); - bool cmd_listBirthstones(int argc, const char **argv); + bool cmdEnterRoom(int argc, const char **argv); + bool cmdListScenes(int argc, const char **argv); + bool cmdGiveItem(int argc, const char **argv); + bool cmdListBirthstones(int argc, const char **argv); }; class Debugger_v2 : public Debugger { @@ -77,12 +77,12 @@ public: protected: KyraEngine_v2 *_vm; - bool cmd_enterScene(int argc, const char **argv); - bool cmd_listScenes(int argc, const char **argv); - bool cmd_sceneInfo(int argc, const char **argv); - bool cmd_characterInfo(int argc, const char **argv); - bool cmd_sceneToFacing(int argc, const char **argv); - bool cmd_giveItem(int argc, const char **argv); + bool cmdEnterScene(int argc, const char **argv); + bool cmdListScenes(int argc, const char **argv); + bool cmdSceneInfo(int argc, const char **argv); + bool cmdCharacterInfo(int argc, const char **argv); + bool cmdSceneToFacing(int argc, const char **argv); + bool cmdGiveItem(int argc, const char **argv); }; class Debugger_HoF : public Debugger_v2 { @@ -93,7 +93,7 @@ public: protected: KyraEngine_HoF *_vm; - bool cmd_passcodes(int argc, const char **argv); + bool cmdPasscodes(int argc, const char **argv); }; #ifdef ENABLE_LOL @@ -119,16 +119,16 @@ public: protected: EoBCoreEngine *_vm; - bool cmd_importSaveFile(int argc, const char **argv); - bool cmd_saveOriginal(int argc, const char **argv); - bool cmd_listMonsters(int argc, const char **argv); - bool cmd_showPosition(int argc, const char **argv); - bool cmd_setPosition(int argc, const char **argv); - bool cmd_openDoor(int argc, const char **argv); - bool cmd_closeDoor(int argc, const char **argv); - bool cmd_listFlags(int argc, const char **argv); - bool cmd_setFlag(int argc, const char **argv); - bool cmd_clearFlag(int argc, const char **argv); + bool cmdImportSaveFile(int argc, const char **argv); + bool cmdSaveOriginal(int argc, const char **argv); + bool cmdListMonsters(int argc, const char **argv); + bool cmdShowPosition(int argc, const char **argv); + bool cmdSetPosition(int argc, const char **argv); + bool cmdOpenDoor(int argc, const char **argv); + bool cmdCloseDoor(int argc, const char **argv); + bool cmdListFlags(int argc, const char **argv); + bool cmdSetFlag(int argc, const char **argv); + bool cmdClearFlag(int argc, const char **argv); }; #endif // ENABLE_EOB diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index 6c2d833271..57943f9a8d 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -60,33 +60,33 @@ Debugger::Debugger(LastExpressEngine *engine) : _engine(engine), _command(NULL), // Register the debugger commands // General - DCmd_Register("help", WRAP_METHOD(Debugger, cmdHelp)); + registerCmd("help", WRAP_METHOD(Debugger, cmdHelp)); // Data - DCmd_Register("ls", WRAP_METHOD(Debugger, cmdListFiles)); - DCmd_Register("dump", WRAP_METHOD(Debugger, cmdDumpFiles)); + registerCmd("ls", WRAP_METHOD(Debugger, cmdListFiles)); + registerCmd("dump", WRAP_METHOD(Debugger, cmdDumpFiles)); - DCmd_Register("showframe", WRAP_METHOD(Debugger, cmdShowFrame)); - DCmd_Register("showbg", WRAP_METHOD(Debugger, cmdShowBg)); - DCmd_Register("playseq", WRAP_METHOD(Debugger, cmdPlaySeq)); - DCmd_Register("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd)); - DCmd_Register("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe)); - DCmd_Register("playnis", WRAP_METHOD(Debugger, cmdPlayNis)); + registerCmd("showframe", WRAP_METHOD(Debugger, cmdShowFrame)); + registerCmd("showbg", WRAP_METHOD(Debugger, cmdShowBg)); + registerCmd("playseq", WRAP_METHOD(Debugger, cmdPlaySeq)); + registerCmd("playsnd", WRAP_METHOD(Debugger, cmdPlaySnd)); + registerCmd("playsbe", WRAP_METHOD(Debugger, cmdPlaySbe)); + registerCmd("playnis", WRAP_METHOD(Debugger, cmdPlayNis)); // Scene & interaction - DCmd_Register("loadscene", WRAP_METHOD(Debugger, cmdLoadScene)); - DCmd_Register("fight", WRAP_METHOD(Debugger, cmdFight)); - DCmd_Register("beetle", WRAP_METHOD(Debugger, cmdBeetle)); + registerCmd("loadscene", WRAP_METHOD(Debugger, cmdLoadScene)); + registerCmd("fight", WRAP_METHOD(Debugger, cmdFight)); + registerCmd("beetle", WRAP_METHOD(Debugger, cmdBeetle)); // Game - DCmd_Register("delta", WRAP_METHOD(Debugger, cmdTimeDelta)); - DCmd_Register("time", WRAP_METHOD(Debugger, cmdTime)); - DCmd_Register("show", WRAP_METHOD(Debugger, cmdShow)); - DCmd_Register("entity", WRAP_METHOD(Debugger, cmdEntity)); + registerCmd("delta", WRAP_METHOD(Debugger, cmdTimeDelta)); + registerCmd("time", WRAP_METHOD(Debugger, cmdTime)); + registerCmd("show", WRAP_METHOD(Debugger, cmdShow)); + registerCmd("entity", WRAP_METHOD(Debugger, cmdEntity)); // Misc - DCmd_Register("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter)); - DCmd_Register("clear", WRAP_METHOD(Debugger, cmdClear)); + registerCmd("chapter", WRAP_METHOD(Debugger, cmdSwitchChapter)); + registerCmd("clear", WRAP_METHOD(Debugger, cmdClear)); resetCommand(); @@ -146,7 +146,7 @@ void Debugger::copyCommand(int argc, const char **argv) { } // Exit the debugger! - Cmd_Exit(0, 0); + cmdExit(0, 0); } void Debugger::callCommand() { @@ -156,7 +156,7 @@ void Debugger::callCommand() { bool Debugger::loadArchive(int index) { if (index < 1 || index > 3) { - DebugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index); + debugPrintf("Invalid cd number (was: %d, valid: [1-3])\n", index); return false; } @@ -198,36 +198,36 @@ void Debugger::restoreArchive() const { // Debugger commands ////////////////////////////////////////////////////////////////////////// bool Debugger::cmdHelp(int, const char **) { - DebugPrintf("Debug flags\n"); - DebugPrintf("-----------\n"); - DebugPrintf(" debugflag_list - Lists the available debug flags and their status\n"); - DebugPrintf(" debugflag_enable - Enables a debug flag\n"); - DebugPrintf(" debugflag_disable - Disables a debug flag\n"); - DebugPrintf("\n"); - DebugPrintf("Commands\n"); - DebugPrintf("--------\n"); - DebugPrintf(" ls - list files in the archive\n"); - DebugPrintf(" dump - dump a list of files in all archives\n"); - DebugPrintf("\n"); - DebugPrintf(" showframe - show a frame from a sequence\n"); - DebugPrintf(" showbg - show a background\n"); - DebugPrintf(" playseq - play a sequence\n"); - DebugPrintf(" playsnd - play a sound\n"); - DebugPrintf(" playsbe - play a subtitle\n"); - DebugPrintf(" playnis - play an animation\n"); - DebugPrintf("\n"); - DebugPrintf(" loadscene - load a scene\n"); - DebugPrintf(" fight - start a fight\n"); - DebugPrintf(" beetle - start the beetle game\n"); - DebugPrintf("\n"); - DebugPrintf(" delta - Adjust the time delta\n"); - DebugPrintf(" show - show game data\n"); - DebugPrintf(" entity - show entity data\n"); - DebugPrintf("\n"); - DebugPrintf(" loadgame - load a saved game\n"); - DebugPrintf(" chapter - switch to a specific chapter\n"); - DebugPrintf(" clear - clear the screen\n"); - DebugPrintf("\n"); + debugPrintf("Debug flags\n"); + debugPrintf("-----------\n"); + debugPrintf(" debugflag_list - Lists the available debug flags and their status\n"); + debugPrintf(" debugflag_enable - Enables a debug flag\n"); + debugPrintf(" debugflag_disable - Disables a debug flag\n"); + debugPrintf("\n"); + debugPrintf("Commands\n"); + debugPrintf("--------\n"); + debugPrintf(" ls - list files in the archive\n"); + debugPrintf(" dump - dump a list of files in all archives\n"); + debugPrintf("\n"); + debugPrintf(" showframe - show a frame from a sequence\n"); + debugPrintf(" showbg - show a background\n"); + debugPrintf(" playseq - play a sequence\n"); + debugPrintf(" playsnd - play a sound\n"); + debugPrintf(" playsbe - play a subtitle\n"); + debugPrintf(" playnis - play an animation\n"); + debugPrintf("\n"); + debugPrintf(" loadscene - load a scene\n"); + debugPrintf(" fight - start a fight\n"); + debugPrintf(" beetle - start the beetle game\n"); + debugPrintf("\n"); + debugPrintf(" delta - Adjust the time delta\n"); + debugPrintf(" show - show game data\n"); + debugPrintf(" entity - show entity data\n"); + debugPrintf("\n"); + debugPrintf(" loadgame - load a saved game\n"); + debugPrintf(" chapter - switch to a specific chapter\n"); + debugPrintf(" clear - clear the screen\n"); + debugPrintf("\n"); return true; } @@ -252,15 +252,15 @@ bool Debugger::cmdListFiles(int argc, const char **argv) { Common::ArchiveMemberList list; int count = _engine->getResourceManager()->listMatchingMembers(list, filter); - DebugPrintf("Number of matches: %d\n", count); + debugPrintf("Number of matches: %d\n", count); for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) - DebugPrintf(" %s\n", (*it)->getName().c_str()); + debugPrintf(" %s\n", (*it)->getName().c_str()); // Restore archive if (argc == 3) restoreArchive(); } else { - DebugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n"); + debugPrintf("Syntax: ls <filter> (use * for all) (<cd number>)\n"); } return true; @@ -287,7 +287,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) { for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { \ Common::SeekableReadStream *stream = getArchive((*it)->getName()); \ if (!stream) { \ - DebugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \ + debugPrintf("ERROR: Cannot create stream for file: %s\n", (*it)->getName().c_str()); \ restoreArchive(); \ return true; \ } \ @@ -311,7 +311,7 @@ bool Debugger::cmdDumpFiles(int argc, const char **) { // Restore current loaded archive restoreArchive(); } else { - DebugPrintf("Syntax: dump"); + debugPrintf("Syntax: dump"); } return true; @@ -336,7 +336,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -345,7 +345,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdShowFrame); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { Sequence sequence(filename); if (sequence.load(getArchive(filename))) { @@ -354,7 +354,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { AnimFrame *frame = sequence.getFrame((uint16)getNumber(argv[2])); if (!frame) { - DebugPrintf("Invalid frame index '%s'\n", argv[2]); + debugPrintf("Invalid frame index '%s'\n", argv[2]); resetCommand(); return true; } @@ -375,7 +375,7 @@ bool Debugger::cmdShowFrame(int argc, const char **argv) { restoreArchive(); } } else { - DebugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n"); + debugPrintf("Syntax: cmd_showframe <seqname> <index> (<cd number>)\n"); } return true; } @@ -398,7 +398,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename + ".BG")) { - DebugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str()); + debugPrintf("Cannot find file: %s\n", (filename + ".BG").c_str()); return true; } @@ -407,7 +407,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdShowBg); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { clearBg(GraphicsManager::kBackgroundC); @@ -429,7 +429,7 @@ bool Debugger::cmdShowBg(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: showbg <bgname> (<cd number>)\n"); + debugPrintf("Syntax: showbg <bgname> (<cd number>)\n"); } return true; } @@ -453,7 +453,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { } if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -462,7 +462,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlaySeq); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { Sequence *sequence = new Sequence(filename); if (sequence->load(getArchive(filename))) { @@ -510,7 +510,7 @@ bool Debugger::cmdPlaySeq(int argc, const char **argv) { restoreArchive(); } } else { - DebugPrintf("Syntax: playseq <seqname> (<cd number>)\n"); + debugPrintf("Syntax: playseq <seqname> (<cd number>)\n"); } return true; } @@ -537,7 +537,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) { name += ".SND"; if (!_engine->getResourceManager()->hasFile(name)) { - DebugPrintf("Cannot find file: %s\n", name.c_str()); + debugPrintf("Cannot find file: %s\n", name.c_str()); return true; } @@ -548,7 +548,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) { if (argc == 3) restoreArchive(); } else { - DebugPrintf("Syntax: playsnd <sndname> (<cd number>)\n"); + debugPrintf("Syntax: playsnd <sndname> (<cd number>)\n"); } return true; } @@ -573,7 +573,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { filename += ".sbe"; if (!_engine->getResourceManager()->hasFile(filename)) { - DebugPrintf("Cannot find file: %s\n", filename.c_str()); + debugPrintf("Cannot find file: %s\n", filename.c_str()); return true; } @@ -582,7 +582,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlaySbe); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { SubtitleManager subtitle(_engine->getFont()); if (subtitle.load(getArchive(filename))) { @@ -615,7 +615,7 @@ bool Debugger::cmdPlaySbe(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: playsbe <sbename> (<cd number>)\n"); + debugPrintf("Syntax: playsbe <sbename> (<cd number>)\n"); } return true; } @@ -639,7 +639,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { // If we got a nis filename, check that the file exists if (name.contains('.') && !_engine->getResourceManager()->hasFile(name)) { - DebugPrintf("Cannot find file: %s\n", name.c_str()); + debugPrintf("Cannot find file: %s\n", name.c_str()); return true; } @@ -648,7 +648,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdPlayNis); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { // Make sure we are not called in a loop _numParams = 0; @@ -672,7 +672,7 @@ bool Debugger::cmdPlayNis(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n"); + debugPrintf("Syntax: playnis <nisname.nis or animation index> (<cd number>)\n"); } return true; } @@ -697,7 +697,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { } if (index > 2500) { - DebugPrintf("Error: invalid index value (0-2500)"); + debugPrintf("Error: invalid index value (0-2500)"); return true; } @@ -706,7 +706,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { _command = WRAP_METHOD(Debugger, cmdLoadScene); copyCommand(argc, argv); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { clearBg(GraphicsManager::kBackgroundAll); @@ -718,7 +718,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { // loadSceneObject(scene, i); // if (scene.getHeader() && scene.getHeader()->car == 5 && scene.getHeader()->position == 81) { - // DebugPrintf("Found scene: %d", i); + // debugPrintf("Found scene: %d", i); // // Draw scene found // _engine->getGraphicsManager()->draw(&scene, GraphicsManager::kBackgroundC); @@ -738,7 +738,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { /*********************************************/ Scene *scene = getScenes()->get(index); if (!scene) { - DebugPrintf("Cannot load scene %i from CD %i", index, cd); + debugPrintf("Cannot load scene %i from CD %i", index, cd); resetCommand(); return true; @@ -758,7 +758,7 @@ bool Debugger::cmdLoadScene(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: loadscene <scene index> (<cd number>)\n"); + debugPrintf("Syntax: loadscene <scene index> (<cd number>)\n"); } return true; } @@ -814,7 +814,7 @@ bool Debugger::cmdFight(int argc, const char **argv) { SceneIndex lastScene = getState()->scene; - getFight()->setup(type) ? DebugPrintf("Lost fight!\n") : DebugPrintf("Won fight!\n"); + getFight()->setup(type) ? debugPrintf("Lost fight!\n") : debugPrintf("Won fight!\n"); // Pause for a second to be able to see the final scene _engine->_system->delayMillis(1000); @@ -837,7 +837,7 @@ bool Debugger::cmdFight(int argc, const char **argv) { } } else { error: - DebugPrintf("Syntax: fight <id> (id=2001-2005)\n"); + debugPrintf("Syntax: fight <id> (id=2001-2005)\n"); } return true; @@ -968,7 +968,7 @@ bool Debugger::cmdBeetle(int argc, const char **argv) { resetCommand(); } } else { - DebugPrintf("Syntax: beetle\n"); + debugPrintf("Syntax: beetle\n"); } return true; @@ -992,7 +992,7 @@ bool Debugger::cmdTimeDelta(int argc, const char **argv) { getState()->timeDelta = (uint)delta; } else { label_error: - DebugPrintf("Syntax: delta <time delta> (delta=1-500)\n"); + debugPrintf("Syntax: delta <time delta> (delta=1-500)\n"); } return true; @@ -1018,10 +1018,10 @@ bool Debugger::cmdTime(int argc, const char **argv) { uint8 minutes = 0; State::getHourMinutes((uint32)time, &hours, &minutes); - DebugPrintf("%02d:%02d\n", hours, minutes); + debugPrintf("%02d:%02d\n", hours, minutes); } else { label_error: - DebugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n"); + debugPrintf("Syntax: time <time to convert> (time=0-INT_MAX)\n"); } return true; @@ -1037,10 +1037,10 @@ label_error: */ bool Debugger::cmdShow(int argc, const char **argv) { #define OUTPUT_DUMP(name, text) \ - DebugPrintf(#name "\n"); \ - DebugPrintf("--------------------------------------------------------------------\n\n"); \ - DebugPrintf("%s", text); \ - DebugPrintf("\n"); + debugPrintf(#name "\n"); \ + debugPrintf("--------------------------------------------------------------------\n\n"); \ + debugPrintf("%s", text); \ + debugPrintf("\n"); if (argc == 2) { @@ -1066,14 +1066,14 @@ bool Debugger::cmdShow(int argc, const char **argv) { } else { label_error: - DebugPrintf("Syntax: state <option>\n"); - DebugPrintf(" state / st\n"); - DebugPrintf(" progress / pr\n"); - DebugPrintf(" flags / fl\n"); - DebugPrintf(" inventory / inv\n"); - DebugPrintf(" objects / obj\n"); - DebugPrintf(" savepoints / pt\n"); - DebugPrintf(" scene / sc\n"); + debugPrintf("Syntax: state <option>\n"); + debugPrintf(" state / st\n"); + debugPrintf(" progress / pr\n"); + debugPrintf(" flags / fl\n"); + debugPrintf(" inventory / inv\n"); + debugPrintf(" objects / obj\n"); + debugPrintf(" savepoints / pt\n"); + debugPrintf(" scene / sc\n"); } return true; @@ -1096,26 +1096,26 @@ bool Debugger::cmdEntity(int argc, const char **argv) { if (index > 39) goto label_error; - DebugPrintf("Entity %s\n", ENTITY_NAME(index)); - DebugPrintf("--------------------------------------------------------------------\n\n"); - DebugPrintf("%s", getEntities()->getData(index)->toString().c_str()); + debugPrintf("Entity %s\n", ENTITY_NAME(index)); + debugPrintf("--------------------------------------------------------------------\n\n"); + debugPrintf("%s", getEntities()->getData(index)->toString().c_str()); // The Player entity does not have any callback data if (index != kEntityPlayer) { EntityData *data = getEntities()->get(index)->getParamData(); for (uint callback = 0; callback < 9; callback++) { - DebugPrintf("Call parameters %d:\n", callback); + debugPrintf("Call parameters %d:\n", callback); for (byte ix = 0; ix < 4; ix++) - DebugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str()); + debugPrintf(" %s", data->getParameters(callback, ix)->toString().c_str()); } } - DebugPrintf("\n"); + debugPrintf("\n"); } else { label_error: - DebugPrintf("Syntax: entity <index>\n"); + debugPrintf("Syntax: entity <index>\n"); for (int i = 0; i < 40; i += 4) - DebugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3); + debugPrintf(" %s - %d %s - %d %s - %d %s - %d\n", ENTITY_NAME(i), i, ENTITY_NAME(i+1), i+1, ENTITY_NAME(i+2), i+2, ENTITY_NAME(i+3), i+3); } return true; @@ -1152,7 +1152,7 @@ bool Debugger::cmdSwitchChapter(int argc, const char **argv) { } } else { error: - DebugPrintf("Syntax: chapter <id> (id=2-6)\n"); + debugPrintf("Syntax: chapter <id> (id=2-6)\n"); } return true; @@ -1172,7 +1172,7 @@ bool Debugger::cmdClear(int argc, const char **) { askForRedraw(); redrawScreen(); } else { - DebugPrintf("Syntax: clear - clear the screen\n"); + debugPrintf("Syntax: clear - clear the screen\n"); } return true; diff --git a/engines/lure/debugger.cpp b/engines/lure/debugger.cpp index bbaa68befa..032186717d 100644 --- a/engines/lure/debugger.cpp +++ b/engines/lure/debugger.cpp @@ -35,20 +35,20 @@ namespace Lure { Debugger::Debugger(): GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); - DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); - DCmd_Register("fields", WRAP_METHOD(Debugger, cmd_listFields)); - DCmd_Register("setfield", WRAP_METHOD(Debugger, cmd_setField)); - DCmd_Register("queryfield", WRAP_METHOD(Debugger, cmd_queryField)); - DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); - DCmd_Register("hotspot", WRAP_METHOD(Debugger, cmd_hotspot)); - DCmd_Register("room", WRAP_METHOD(Debugger, cmd_room)); - DCmd_Register("showanim", WRAP_METHOD(Debugger, cmd_showAnim)); - DCmd_Register("strings", WRAP_METHOD(Debugger, cmd_saveStrings)); - DCmd_Register("debug", WRAP_METHOD(Debugger, cmd_debug)); - DCmd_Register("script", WRAP_METHOD(Debugger, cmd_script)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); + registerCmd("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); + registerCmd("fields", WRAP_METHOD(Debugger, cmd_listFields)); + registerCmd("setfield", WRAP_METHOD(Debugger, cmd_setField)); + registerCmd("queryfield", WRAP_METHOD(Debugger, cmd_queryField)); + registerCmd("give", WRAP_METHOD(Debugger, cmd_giveItem)); + registerCmd("hotspots", WRAP_METHOD(Debugger, cmd_hotspots)); + registerCmd("hotspot", WRAP_METHOD(Debugger, cmd_hotspot)); + registerCmd("room", WRAP_METHOD(Debugger, cmd_room)); + registerCmd("showanim", WRAP_METHOD(Debugger, cmd_showAnim)); + registerCmd("strings", WRAP_METHOD(Debugger, cmd_saveStrings)); + registerCmd("debug", WRAP_METHOD(Debugger, cmd_debug)); + registerCmd("script", WRAP_METHOD(Debugger, cmd_script)); } static int strToInt(const char *s) { @@ -88,7 +88,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { // Validate that it's an existing room if (res.getRoom(roomNumber) == NULL) { - DebugPrintf("specified number was not a valid room\n"); + debugPrintf("specified number was not a valid room\n"); return true; } @@ -105,9 +105,9 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: room <roomnum> [<remoteview>]\n"); - DebugPrintf("A non-zero value for reomteview will change the room without "); - DebugPrintf("moving the player.\n"); + debugPrintf("Syntax: room <roomnum> [<remoteview>]\n"); + debugPrintf("A non-zero value for reomteview will change the room without "); + debugPrintf("moving the player.\n"); return true; } @@ -117,7 +117,7 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) { char buffer[MAX_DESC_SIZE]; int ctr = 0; - DebugPrintf("Available rooms are:\n"); + debugPrintf("Available rooms are:\n"); for (RoomDataList::iterator i = rooms.begin(); i != rooms.end(); ++i) { RoomData const &room = **i; // Explictly note the second drawbridge room as "Alt" @@ -128,20 +128,20 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) { strings.getString(room.roomNumber, buffer); } - DebugPrintf("#%d - %s", room.roomNumber, buffer); + debugPrintf("#%d - %s", room.roomNumber, buffer); - if (++ctr % 3 == 0) DebugPrintf("\n"); + if (++ctr % 3 == 0) debugPrintf("\n"); else { // Write out spaces between columns int numSpaces = 25 - strlen(buffer) - (room.roomNumber >= 10 ? 2 : 1); char *s = buffer; while (numSpaces-- > 0) *s++ = ' '; *s = '\0'; - DebugPrintf("%s", buffer); + debugPrintf("%s", buffer); } } - DebugPrintf("\n"); - DebugPrintf("Current room: %d\n", Room::getReference().roomNumber()); + debugPrintf("\n"); + debugPrintf("Current room: %d\n", Room::getReference().roomNumber()); return true; } @@ -150,11 +150,11 @@ bool Debugger::cmd_listFields(int argc, const char **argv) { ValueTableData &fields = Resources::getReference().fieldList(); for (int ctr = 0; ctr < fields.size(); ++ctr) { - DebugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr)); + debugPrintf("(%-2d): %-5d", ctr, fields.getField(ctr)); if (!((ctr + 1) % 7)) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -167,13 +167,13 @@ bool Debugger::cmd_setField(int argc, const char **argv) { if ((fieldNum < 0) || (fieldNum >= fields.size())) { // Invalid field number - DebugPrintf("Invalid field number specified\n"); + debugPrintf("Invalid field number specified\n"); } else { // Set the field value fields.setField(fieldNum, value); } } else { - DebugPrintf("Syntax: setfield <field_number> <value>\n"); + debugPrintf("Syntax: setfield <field_number> <value>\n"); } return true; @@ -186,14 +186,14 @@ bool Debugger::cmd_queryField(int argc, const char **argv) { int fieldNum = strToInt(argv[1]); if ((fieldNum < 0) || (fieldNum >= fields.size())) { // Invalid field number - DebugPrintf("Invalid field number specified\n"); + debugPrintf("Invalid field number specified\n"); } else { // Get the field value - DebugPrintf("Field %d is %d (%xh)\n", fieldNum, + debugPrintf("Field %d is %d (%xh)\n", fieldNum, fields.getField(fieldNum), fields.getField(fieldNum)); } } else { - DebugPrintf("Syntax: queryfield <field_num>\n"); + debugPrintf("Syntax: queryfield <field_num>\n"); } return true; @@ -215,18 +215,18 @@ bool Debugger::cmd_giveItem(int argc, const char **argv) { charHotspot = res.getHotspot(charNum); if (itemHotspot == NULL) { - DebugPrintf("The specified item does not exist\n"); + debugPrintf("The specified item does not exist\n"); } else if (itemNum < 0x408) { - DebugPrintf("The specified item number is not an object\n"); + debugPrintf("The specified item number is not an object\n"); } else if ((charNum < PLAYER_ID) || (charNum >= 0x408) || (charHotspot == NULL)) { - DebugPrintf("The specified character does not exist"); + debugPrintf("The specified character does not exist"); } else { // Set the item's room number to be the destination character itemHotspot->roomNumber = charNum; } } else { - DebugPrintf("Syntax: give <item_id> [<character_id>]\n"); + debugPrintf("Syntax: give <item_id> [<character_id>]\n"); } return true; @@ -248,7 +248,7 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (hotspot.nameId() == 0) strcpy(buffer, "none"); else strings.getString(hotspot.nameId(), buffer); - DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer, + debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId(), buffer, hotspot.x(), hotspot.y(), hotspot.roomNumber()); } } else { @@ -263,16 +263,16 @@ bool Debugger::cmd_hotspots(int argc, const char **argv) { if (hotspot.nameId == 0) strcpy(buffer, "none"); else strings.getString(hotspot.nameId, buffer); - DebugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer, + debugPrintf("%4xh - %s pos=(%d,%d,%d)\n", hotspot.hotspotId, buffer, hotspot.startX, hotspot.startY, hotspot.roomNumber); } } } } else { - DebugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n"); - DebugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n"); - DebugPrintf("present in either the current room or a designated one\n"); + debugPrintf("Syntax: hotspots ['active' | ['room' | 'room' '<room_number>']]\n"); + debugPrintf("Gives a list of all the currently active hotspots, or the hotspots\n"); + debugPrintf("present in either the current room or a designated one\n"); } return true; @@ -287,12 +287,12 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { Hotspot *h; if (argc < 2) { - DebugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n"); + debugPrintf("hotspot <hotspot_id> ['paths' | 'schedule' | 'actions' | 'activate' | 'deactivate' | 'setpos']\n"); return true; } hs = res.getHotspot(strToInt(argv[1])); if (!hs) { - DebugPrintf("Unknown hotspot specified\n"); + debugPrintf("Unknown hotspot specified\n"); return true; } @@ -300,26 +300,26 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { if (argc == 2) { // Show the hotspot properties strings.getString(hs->nameId, buffer); - DebugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer, + debugPrintf("name = %d - %s, descs = (%d,%d)\n", hs->nameId, buffer, hs->descId, hs->descId2); - DebugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset); - DebugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer); - DebugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber); - DebugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n", + debugPrintf("actions = %xh, offset = %xh\n", hs->actions, hs->actionsOffset); + debugPrintf("flags = %xh, layer = %d\n", hs->flags, hs->layer); + debugPrintf("position = %d,%d,%d\n", hs->startX, hs->startY, hs->roomNumber); + debugPrintf("size = %d,%d, alt = %d,%d, yCorrection = %d\n", hs->width, hs->height, hs->widthCopy, hs->heightCopy, hs->yCorrection); - DebugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY); - DebugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag); - DebugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset); - DebugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n", + debugPrintf("Talk bubble offset = %d,%d\n", hs->talkX, hs->talkY); + debugPrintf("load offset = %xh, script load = %d\n", hs->loadOffset, hs->scriptLoadFlag); + debugPrintf("Animation Id = %xh, Color offset = %d\n", hs->animRecordId, hs->colorOffset); + debugPrintf("Talk Script offset = %xh, Tick Script offset = %xh\n", hs->talkScriptOffset, hs->tickScriptOffset); - DebugPrintf("Tick Proc offset = %xh\n", hs->tickProcId); - DebugPrintf("Tick timeout = %d\n", hs->tickTimeout); - DebugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n", + debugPrintf("Tick Proc offset = %xh\n", hs->tickProcId); + debugPrintf("Tick timeout = %d\n", hs->tickTimeout); + debugPrintf("Character mode = %d, delay ctr = %d, pause ctr = %d\n", hs->characterMode, hs->delayCtr, hs->pauseCtr); if (h != NULL) { - DebugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames()); - DebugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false"); + debugPrintf("Frame Number = %d of %d\n", h->frameNumber(), h->numFrames()); + debugPrintf("Persistent = %s\n", h->persistant() ? "true" : "false"); } } else if (strcmp(argv[2], "actions") == 0) { @@ -329,42 +329,42 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { const char *actionStr = stringList.getString(action); if (offset >= 0x8000) { - DebugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff); + debugPrintf("%s - Message %xh\n", actionStr, offset & 0x7ff); } else if (offset != 0) { - DebugPrintf("%s - Script %xh\n", actionStr, offset); + debugPrintf("%s - Script %xh\n", actionStr, offset); } } } else if (strcmp(argv[2], "activate") == 0) { // Activate the hotspot res.activateHotspot(hs->hotspotId); hs->flags &= ~HOTSPOTFLAG_MENU_EXCLUSION; - DebugPrintf("Activated\n"); + debugPrintf("Activated\n"); } else if (strcmp(argv[2], "deactivate") == 0) { // Deactivate the hotspot res.deactivateHotspot(hs->hotspotId); hs->flags |= HOTSPOTFLAG_MENU_EXCLUSION; - DebugPrintf("Deactivated\n"); + debugPrintf("Deactivated\n"); } else { if (strcmp(argv[2], "schedule") == 0) { // List any current schedule for the character - DebugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str()); + debugPrintf("%s", hs->npcSchedule.getDebugInfo().c_str()); } if (!h) - DebugPrintf("The specified hotspot is not currently active\n"); + debugPrintf("The specified hotspot is not currently active\n"); else if (strcmp(argv[2], "paths") == 0) { // List any paths for a charcter - DebugPrintf("%s", h->pathFinder().getDebugInfo().c_str()); + debugPrintf("%s", h->pathFinder().getDebugInfo().c_str()); } else if (strcmp(argv[2], "pixels") == 0) { // List the pixel data for the hotspot HotspotAnimData &pData = h->anim(); - DebugPrintf("Record Id = %xh\n", pData.animRecordId); - DebugPrintf("Flags = %d\n", pData.flags); - DebugPrintf("Frames: up=%d down=%d left=%d right=%d\n", + debugPrintf("Record Id = %xh\n", pData.animRecordId); + debugPrintf("Flags = %d\n", pData.flags); + debugPrintf("Frames: up=%d down=%d left=%d right=%d\n", pData.upFrame, pData.downFrame, pData.leftFrame, pData.rightFrame); - DebugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames()); + debugPrintf("Current frame = %d of %d\n", h->frameNumber(), h->numFrames()); } else if (strcmp(argv[2], "setpos") == 0) { // Set the hotspot position @@ -372,11 +372,11 @@ bool Debugger::cmd_hotspot(int argc, const char **argv) { h->setPosition(strToInt(argv[3]), strToInt(argv[4])); if (argc >= 6) h->setRoomNumber(strToInt(argv[5])); - DebugPrintf("Done.\n"); + debugPrintf("Done.\n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -388,56 +388,56 @@ bool Debugger::cmd_room(int argc, const char **argv) { char buffer[MAX_DESC_SIZE]; if (argc < 2) { - DebugPrintf("room <room_number>\n"); + debugPrintf("room <room_number>\n"); return true; } int roomNumber = strToInt(argv[1]); RoomData *room = res.getRoom(roomNumber); if (!room) { - DebugPrintf("Unknown room specified\n"); + debugPrintf("Unknown room specified\n"); return true; } // Show the room details strings.getString(roomNumber, buffer); - DebugPrintf("room #%d - %s\n", roomNumber, buffer); + debugPrintf("room #%d - %s\n", roomNumber, buffer); strings.getString(room->descId, buffer); - DebugPrintf("%s\n", buffer); - DebugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n", + debugPrintf("%s\n", buffer); + debugPrintf("Horizontal clipping = %d->%d walk area=(%d,%d)-(%d,%d)\n", room->clippingXStart, room->clippingXEnd, room->walkBounds.left, room->walkBounds.top, room->walkBounds.right, room->walkBounds.bottom); - DebugPrintf("Exit hotspots:"); + debugPrintf("Exit hotspots:"); RoomExitHotspotList &exits = room->exitHotspots; if (exits.empty()) - DebugPrintf(" none\n"); + debugPrintf(" none\n"); else { RoomExitHotspotList::iterator i; for (i = exits.begin(); i != exits.end(); ++i) { RoomExitHotspotData const &rec = **i; - DebugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh", + debugPrintf("\nArea - (%d,%d)-(%d,%d) Room=%d Cursor=%d Hotspot=%xh", rec.xs, rec.ys, rec.xe, rec.ye, rec.destRoomNumber, rec.cursorNum, rec.hotspotId); } - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("Room exits:"); + debugPrintf("Room exits:"); if (room->exits.empty()) - DebugPrintf(" none\n"); + debugPrintf(" none\n"); else { RoomExitList::iterator i2; for (i2 = room->exits.begin(); i2 != room->exits.end(); ++i2) { RoomExitData const &rec2 = **i2; - DebugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh", + debugPrintf("\nExit - (%d,%d)-(%d,%d) Dest=%d,(%d,%d) Dir=%s Sequence=%xh", rec2.xs, rec2.ys, rec2.xe, rec2.ye, rec2.roomNumber, rec2.x, rec2.y, directionList[rec2.direction], rec2.sequenceOffset); } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -446,7 +446,7 @@ bool Debugger::cmd_room(int argc, const char **argv) { bool Debugger::cmd_showAnim(int argc, const char **argv) { Resources &res = Resources::getReference(); if (argc < 2) { - DebugPrintf("showAnim animId [[frame_width frame_height] | list]\n"); + debugPrintf("showAnim animId [[frame_width frame_height] | list]\n"); return true; } @@ -454,7 +454,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { int animId = strToInt(argv[1]); HotspotAnimData *data = res.getAnimation(animId); if (data == NULL) { - DebugPrintf("No such animation Id exists\n"); + debugPrintf("No such animation Id exists\n"); return true; } @@ -500,7 +500,7 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { height = strToInt(argv[3]); if ((width * height) != (frameSize * 2)) { - DebugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n", + debugPrintf("Warning: Total size = %d, Frame size (%d,%d) * %d frames = %d bytes\n", destSize, width, height, numFrames, width * height * numFrames / 2); } } else { @@ -511,25 +511,25 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { width = frameSize * 3 / 4; bool descFlag = (argc == 3); - if (descFlag) DebugPrintf("Target size = %d\n", frameSize * 2); + if (descFlag) debugPrintf("Target size = %d\n", frameSize * 2); while ((width > 0) && (descFlag || (((frameSize * 2) % width) != 0))) { if (((frameSize * 2) % width) == 0) - DebugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width); + debugPrintf("Frame size (%d,%d) found\n", width, frameSize * 2 / width); --width; } if (argc == 3) { - DebugPrintf("Done\n"); + debugPrintf("Done\n"); return true; } else if (width == 0) { - DebugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n", + debugPrintf("Total size = %d, # frames = %d, frame Size = %d - No valid frame dimensions\n", destSize, numFrames, frameSize); return true; } height = (frameSize * 2) / width; - DebugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n", + debugPrintf("# frames = %d, guestimated frame size = (%d,%d)\n", numFrames, width, height); } @@ -544,13 +544,13 @@ bool Debugger::cmd_showAnim(int argc, const char **argv) { hotspot->setAnimation(animId); - DebugPrintf("Done\n"); + debugPrintf("Done\n"); return true; } bool Debugger::cmd_saveStrings(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("strings <stringId>\n"); + debugPrintf("strings <stringId>\n"); return true; } @@ -558,13 +558,13 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) { char *buffer = (char *)malloc(32768); if (!buffer) { - DebugPrintf("Cannot allocate strings buffer\n"); + debugPrintf("Cannot allocate strings buffer\n"); return true; } uint16 id = strToInt(argv[1]); - strings.getString(id, buffer, NULL, NULL); - DebugPrintf("%s\n", buffer); + strings.getString(id, buffer); + debugPrintf("%s\n", buffer); /* Commented out code for saving all text strings - note that 0x1000 is chosen * arbitrarily, so there'll be a bunch of garbage at the end, or the game will crash @@ -580,7 +580,7 @@ bool Debugger::cmd_saveStrings(int argc, const char **argv) { fclose(f); - DebugPrintf("Done\n"); + debugPrintf("Done\n"); */ free(buffer); @@ -593,16 +593,16 @@ bool Debugger::cmd_debug(int argc, const char **argv) { Room &room = Room::getReference(); if ((argc == 2) && (strcmp(argv[1], "on") == 0)) { - DebugPrintf("debug keys are on\n"); + debugPrintf("debug keys are on\n"); game.debugFlag() = true; } else if ((argc == 2) && (strcmp(argv[1], "off") == 0)) { - DebugPrintf("debug keys are off\n"); + debugPrintf("debug keys are off\n"); game.debugFlag() = false; room.setShowInfo(false); } else { - DebugPrintf("debug [on | off]]\n"); + debugPrintf("debug [on | off]]\n"); } return true; @@ -610,13 +610,13 @@ bool Debugger::cmd_debug(int argc, const char **argv) { bool Debugger::cmd_script(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n"); + debugPrintf("script <script number> [param 1] [param 2] [param 3] [exit flag]\n"); return true; } int scriptNumber = strToInt(argv[1]); if ((scriptNumber < 0) || (scriptNumber > 66)) { - DebugPrintf("An invalid script number was specified\n"); + debugPrintf("An invalid script number was specified\n"); return true; } @@ -629,7 +629,7 @@ bool Debugger::cmd_script(int argc, const char **argv) { param3 = strToInt(argv[4]); Script::executeMethod(scriptNumber, param1, param2, param3); - DebugPrintf("Script executed\n"); + debugPrintf("Script executed\n"); return true; } diff --git a/engines/mads/action.cpp b/engines/mads/action.cpp new file mode 100644 index 0000000000..80480cbdfd --- /dev/null +++ b/engines/mads/action.cpp @@ -0,0 +1,708 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/action.h" +#include "mads/inventory.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/staticres.h" + +namespace MADS { + +void ActionDetails::synchronize(Common::Serializer &s) { + s.syncAsUint16LE(_verbId); + s.syncAsUint16LE(_objectNameId); + s.syncAsUint16LE(_indirectObjectId); +} + +void ActionSavedFields::synchronize(Common::Serializer &s) { + s.syncAsByte(_commandError); + s.syncAsSint16LE(_commandSource); + s.syncAsSint16LE(_command); + s.syncAsSint16LE(_mainObject); + s.syncAsSint16LE(_secondObject); + s.syncAsSint16LE(_mainObjectSource); + s.syncAsSint16LE(_secondObjectSource); + s.syncAsSint16LE(_articleNumber); + s.syncAsSint16LE(_lookFlag); +} + +/*------------------------------------------------------------------------*/ + +MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) { + clear(); + _statusTextIndex = -1; + _selectedAction = 0; + _inProgress = false; + _pickedWord = -1; + + _savedFields._commandSource = 0; + _savedFields._mainObjectSource = 0; + _savedFields._command = -1; + _savedFields._mainObject = 0; + _savedFields._secondObject = 0; + _savedFields._secondObjectSource = 0; + _savedFields._articleNumber = PREP_NONE; + _savedFields._lookFlag = false; + + _activeAction._verbId = VERB_NONE; + _activeAction._objectNameId = -1; + _activeAction._indirectObjectId = -1; + _savedFields._commandError = false; + _verbType = VERB_INIT; + _prepType = PREP_NONE; +} + +void MADSAction::clear() { + _interAwaiting = AWAITING_COMMAND; + _commandSource = CAT_NONE; + _mainObjectSource = CAT_NONE; + _secondObjectSource = CAT_NONE; + _recentCommandSource = CAT_NONE; + _articleNumber = 0; + _lookFlag = false; + _pointEstablished = 0; + _statusText.clear(); + _selectedRow = -1; + _hotspotId = -1; + _secondObject = -1; + _recentCommand = -1; + _action._verbId = VERB_NONE; + _action._objectNameId = -1; + _action._indirectObjectId = -1; + _textChanged = true; +} + +void MADSAction::appendVocab(int vocabId, bool capitalize) { + Common::String vocabStr = _vm->_game->_scene.getVocab(vocabId); + if (capitalize) + vocabStr.setChar(toupper(vocabStr[0]), 0); + + _statusText += vocabStr; + _statusText += " "; +} + +void MADSAction::startWalkingDirectly(int walkType) { + Scene &scene = _vm->_game->_scene; + Player &player = _vm->_game->_player; + + if (_pointEstablished && (walkType == -3 || _savedFields._command < 0)) { + player._needToWalk = true; + player._prepareWalkPos = scene._customDest; + } +} + +void MADSAction::set() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + _statusText = ""; + + _action._verbId = VERB_NONE; + _action._objectNameId = -1; + _action._indirectObjectId = -1; + + if (_commandSource == CAT_TALK_ENTRY) { + // Handle showing the conversation selection. Rex at least doesn't actually seem to use this + if (_selectedRow >= 0) { + _action._verbId = userInterface._talkIds[_selectedRow]; + Common::String desc = userInterface._talkStrings[_selectedRow]; + if (!desc.empty()) + _statusText = desc; + } + } else if (_lookFlag && (_selectedRow == 0)) { + // Two 'look' actions in succession, so the action becomes 'Look around' + _statusText = kLookAroundStr; + } else { + bool flag = false; + if ((_commandSource == CAT_INV_VOCAB) && (_selectedRow >= 0) + && (_verbType == VERB_THAT) && (_prepType == PREP_NONE)) { + // Use/to action + int invIndex = userInterface._selectedInvIndex; + InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); + + _action._objectNameId = objEntry._descId; + _action._verbId = objEntry._vocabList[_selectedRow]._vocabId; + + // Set up the status text string + _statusText = kUseStr; + appendVocab(_action._objectNameId); + _statusText += kToStr; + appendVocab(_action._verbId); + } else { + // Handling for if an action has been selected + if (_selectedRow >= 0) { + if (_commandSource == CAT_COMMAND) { + // Standard verb action + _action._verbId = scene._verbList[_selectedRow]._id; + } else { + // Selected action on an inventory object + int invIndex = userInterface._selectedInvIndex; + InventoryObject &objEntry = _vm->_game->_objects.getItem(invIndex); + + _action._verbId = objEntry._vocabList[_selectedRow]._vocabId; + } + + appendVocab(_action._verbId, true); + + if (_action._verbId == VERB_LOOK) { + // Add in the word 'add' + _statusText += kArticleList[PREP_AT]; + _statusText += " "; + } + } + + // Add in any necessary article if necessary + if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_verbType == VERB_THAT)) { + flag = true; + + _statusText += kArticleList[_articleNumber]; + _statusText += " "; + } + + // Handling for hotspot + if (_hotspotId >= 0) { + if (_selectedRow < 0) { + int verbId; + + if (_hotspotId < (int)scene._hotspots.size()) { + // Get the verb Id from the hotspot + verbId = scene._hotspots[_hotspotId]._verbId; + } else { + // Get the verb Id from the scene object + verbId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._verbId; + } + + if (verbId > 0) { + // Set the specified action + _action._verbId = verbId; + appendVocab(_action._verbId, true); + } else { + // Default to a standard 'walk to' + _action._verbId = VERB_WALKTO; + _statusText += kWalkToStr; + } + } + + if ((_mainObjectSource == CAT_INV_LIST) || (_mainObjectSource == CAT_INV_ANIM)) { + // Get name from given inventory object + InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); + _action._objectNameId = invObject._descId; + } else if (_hotspotId < (int)scene._hotspots.size()) { + // Get name from scene hotspot + _action._objectNameId = scene._hotspots[_hotspotId]._vocabId; + } else { + // Get name from temporary scene hotspot + _action._objectNameId = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._descId; + } + appendVocab(_action._objectNameId); + } + } + + if (_secondObject >= 0) { + if (_secondObjectSource == CAT_INV_LIST || _secondObjectSource == CAT_INV_ANIM) { + InventoryObject &invObject = _vm->_game->_objects.getItem(_secondObject); + _action._indirectObjectId = invObject._descId; + } else if (_secondObject < (int)scene._hotspots.size()) { + _action._indirectObjectId = scene._hotspots[_secondObject]._vocabId; + } else { + _action._indirectObjectId = scene._dynamicHotspots[_secondObject - scene._hotspots.size()]._descId; + } + } + + if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) { + if (_articleNumber == PREP_RELATIONAL) { + if (_secondObject >= 0) { + int articleNum = 0; + + if ((_secondObjectSource == 2) || (_secondObjectSource == 5)) { + InventoryObject &invObject = _vm->_game->_objects.getItem(_hotspotId); + articleNum = invObject._article; + } else if (_hotspotId < (int)scene._hotspots.size()) { + articleNum = scene._hotspots[_hotspotId]._articleNumber; + } else { + articleNum = scene._dynamicHotspots[_hotspotId - scene._hotspots.size()]._articleNumber; + } + + _statusText += kArticleList[articleNum]; + } + } else if ((_articleNumber == VERB_LOOK) || (_vm->getGameID() != GType_RexNebular) || + (_action._indirectObjectId >= 0 && scene._vocabStrings[_action._indirectObjectId] != kFenceStr)) { + // Write out the article + _statusText += kArticleList[_articleNumber]; + } else { + // Special case for a 'fence' entry in Rex Nebular + _statusText += kOverStr; + } + + _statusText += " "; + } + + // Append object description if necessary + if (_secondObject >= 0) + appendVocab(_action._indirectObjectId); + + // Remove any trailing space character + if (_statusText.hasSuffix(" ")) + _statusText.deleteLastChar(); + } + + _textChanged = true; +} + +void MADSAction::refresh() { + Scene &scene = _vm->_game->_scene; + + // Exit immediately if nothing has changed + if (!_textChanged) + return; + + // Remove any old copy of the status text + if (_statusTextIndex >= 0) { + scene._textDisplay.expire(_statusTextIndex); + _statusTextIndex = -1; + } + + if (!_statusText.empty()) { + if ((_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) || + (_vm->_game->_screenObjects._inputMode == kInputLimitedSentences)) { + Font *font = _vm->_font->getFont(FONT_MAIN); + int textSpacing = -1; + + int strWidth = font->getWidth(_statusText); + if (strWidth > MADS_SCREEN_WIDTH) { + // Too large to fit, so fall back on interface font + font = _vm->_font->getFont(FONT_INTERFACE); + strWidth = font->getWidth(_statusText, 0); + textSpacing = 0; + } + + // Add a new text display entry to display the status text at the bottom of the screen area + _statusTextIndex = scene._textDisplay.add(160 - (strWidth / 2), + MADS_SCENE_HEIGHT + scene._posAdjust.y - 13, 3, textSpacing, _statusText, font); + } + } + + _textChanged = false; +} + +void MADSAction::startAction() { + Game &game = *_vm->_game; + Player &player = game._player; + Scene &scene = _vm->_game->_scene; + DynamicHotspots &dynHotspots = scene._dynamicHotspots; + Hotspots &hotspots = scene._hotspots; + + player.cancelCommand(); + + _inProgress = true; + _savedFields._commandError = false; + _savedFields._command = _selectedRow; + _savedFields._mainObject = _hotspotId; + _savedFields._secondObject = _secondObject; + _savedFields._articleNumber = _articleNumber; + _savedFields._commandSource = _commandSource; + _savedFields._mainObjectSource = _mainObjectSource; + _savedFields._secondObjectSource = _secondObjectSource; + _savedFields._lookFlag = _lookFlag; + _activeAction = _action; + + // Copy the action to be active + _activeAction = _action; + _sentence = _statusText; + + if ((_mainObjectSource == CAT_HOTSPOT) && (_secondObjectSource == 4)) + _savedFields._commandError = true; + + player._needToWalk = false; + int hotspotId = -1; + + if (!_savedFields._lookFlag && (_vm->_game->_screenObjects._inputMode != kInputConversation)) { + if (_savedFields._mainObjectSource == CAT_HOTSPOT) + hotspotId = _savedFields._mainObject; + else if (_secondObjectSource == 4) + hotspotId = _savedFields._secondObject; + + if (hotspotId >= (int)hotspots.size()) { + DynamicHotspot &hs = dynHotspots[hotspotId - hotspots.size()]; + if ((hs._feetPos.x == -1) || (hs._feetPos.x == -3)) { + startWalkingDirectly(hs._feetPos.x); + } else if (hs._feetPos.x == 0) { + player._prepareWalkFacing = hs._facing; + } else if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) { + player._needToWalk = true; + player._prepareWalkPos = hs._feetPos; + } + + player._prepareWalkFacing = hs._facing; + hotspotId = -1; + } + } + + if (hotspotId >= 0) { + Hotspot &hs = hotspots[hotspotId]; + + if (hs._feetPos.x == -1 || hs._feetPos.x == -3) { + startWalkingDirectly(hs._feetPos.x); + } else if (hs._feetPos.x >= 0) { + if (_savedFields._commandSource == CAT_NONE || hs._cursor < CURSOR_WAIT) { + player._needToWalk = true; + player._prepareWalkPos = hs._feetPos; + } + } + + player._prepareWalkFacing = hs._facing; + } + + player._readyToWalk = player._needToWalk; +} + +void MADSAction::checkAction() { + if (isAction(VERB_LOOK) || isAction(VERB_THROW)) + _vm->_game->_player._needToWalk = false; +} + +bool MADSAction::isAction(int verbId, int objectNameId, int indirectObjectId) { + if (_activeAction._verbId != verbId) + return false; + if ((objectNameId != 0) && (_activeAction._objectNameId != objectNameId)) + return false; + if ((indirectObjectId != 0) && (_activeAction._indirectObjectId != indirectObjectId)) + return false; + + return true; +} + +bool MADSAction::isObject(int objectNameId) { + return _activeAction._objectNameId == objectNameId; +} + +bool MADSAction::isTarget(int objectNameId) { + return _activeAction._indirectObjectId == objectNameId; +} + +void MADSAction::checkActionAtMousePos() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) && + _interAwaiting != AWAITING_COMMAND && _pickedWord >= 0) { + if (_recentCommandSource == userInterface._category || _recentCommand != _pickedWord || + (_interAwaiting != AWAITING_THIS && _interAwaiting != 3)) + clear(); + else if (_selectedRow != 0 || userInterface._category != CAT_COMMAND) + scene._lookFlag = false; + else + scene._lookFlag = true; + } + + if (_vm->_events->_rightMousePressed && _vm->_events->_mouseButtons) { + switch (userInterface._category) { + case CAT_COMMAND: + case CAT_INV_VOCAB: + return; + + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_interAwaiting != AWAITING_THAT) { + if (userInterface._selectedActionIndex >= 0) { + _commandSource = CAT_COMMAND; + _selectedRow = userInterface._selectedActionIndex; + _verbType = scene._verbList[_selectedRow]._verbType; + _prepType = scene._verbList[_selectedRow]._prepType; + _interAwaiting = AWAITING_THIS; + } else if (userInterface._selectedItemVocabIdx >= 0) { + _commandSource = CAT_INV_VOCAB; + _selectedRow = userInterface._selectedItemVocabIdx; + int objectId = _vm->_game->_objects._inventoryList[_selectedRow]; + InventoryObject &invObject = _vm->_game->_objects[objectId]; + + _verbType = invObject._vocabList[_selectedRow - 1]._verbType; + _prepType = invObject._vocabList[_selectedRow - 1]._prepType; + _mainObjectSource = CAT_INV_LIST; + _hotspotId = userInterface._selectedInvIndex; + _articleNumber = _prepType; + + if ((_verbType == VERB_THIS && _prepType == PREP_NONE) || + (_verbType == VERB_THAT && _prepType != PREP_NONE)) + _interAwaiting = AWAITING_RIGHT_MOUSE; + else + _interAwaiting = AWAITING_THAT; + } + } + break; + + default: + break; + } + } + + switch (_interAwaiting) { + case AWAITING_COMMAND: + _articleNumber = 0; + switch (userInterface._category) { + case CAT_COMMAND: + _commandSource = CAT_COMMAND; + _selectedRow = _pickedWord; + if (_selectedRow >= 0) { + _verbType = scene._verbList[_selectedRow]._verbType; + _prepType = scene._verbList[_selectedRow]._prepType; + } + break; + + case CAT_INV_VOCAB: + _commandSource = CAT_INV_VOCAB; + _selectedRow = _pickedWord; + if (_selectedRow < 0) { + _hotspotId = -1; + _mainObjectSource = CAT_NONE; + } else { + InventoryObject &invObject = _vm->_game->_objects.getItem(userInterface._selectedInvIndex); + _verbType = invObject._vocabList[_selectedRow]._verbType; + _prepType = invObject._vocabList[_selectedRow]._prepType; + _hotspotId = userInterface._selectedInvIndex; + _mainObjectSource = CAT_INV_LIST; + + if (_verbType == VERB_THAT) + _articleNumber = _prepType; + } + break; + + case CAT_HOTSPOT: + _selectedRow = -1; + _commandSource = CAT_NONE; + _mainObjectSource = CAT_HOTSPOT; + _hotspotId = _pickedWord; + break; + + case CAT_TALK_ENTRY: + _commandSource = CAT_TALK_ENTRY; + _selectedRow = _pickedWord; + break; + + default: + break; + } + break; + + case AWAITING_THIS: + _articleNumber = 0; + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + _mainObjectSource = userInterface._category; + _hotspotId = _pickedWord; + break; + default: + break; + } + break; + + case AWAITING_THAT: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + _secondObjectSource = userInterface._category; + _secondObject = _pickedWord; + break; + default: + break; + } + break; + + default: + break; + } +} + +void MADSAction::leftClick() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + bool abortFlag = false; + + if ((userInterface._category == CAT_COMMAND || userInterface._category == CAT_INV_VOCAB) && + _interAwaiting != 1 && _pickedWord >= 0 && + _recentCommandSource == userInterface._category && _recentCommand == _pickedWord && + (_interAwaiting == 2 || userInterface._category == CAT_INV_VOCAB)) { + abortFlag = true; + if (_selectedRow == 0 && userInterface._category == CAT_COMMAND) { + _selectedAction = CAT_COMMAND; + scene._lookFlag = true; + } else { + _selectedAction = CAT_NONE; + scene._lookFlag = false; + clear(); + } + } + + if (abortFlag || (_vm->_events->_rightMousePressed && (userInterface._category == CAT_COMMAND || + userInterface._category == CAT_INV_VOCAB))) + return; + + switch (_interAwaiting) { + case AWAITING_COMMAND: + switch (userInterface._category) { + case CAT_COMMAND: + if (_selectedRow >= 0) { + if (_verbType == VERB_ONLY) { + _selectedAction = -1; + } + else { + _recentCommand = _selectedRow; + _recentCommandSource = _commandSource; + _interAwaiting = AWAITING_THIS; + } + } + break; + + case CAT_INV_LIST: + if (_pickedWord >= 0) { + userInterface.selectObject(_pickedWord); + } + break; + + case CAT_INV_VOCAB: + if (_selectedRow >= 0) { + if (_verbType != VERB_THIS || _prepType != PREP_NONE) { + if (_verbType != VERB_THAT || _prepType == PREP_NONE) { + _interAwaiting = AWAITING_THAT; + _articleNumber = _prepType; + } else { + _articleNumber = _prepType; + _selectedAction = -1; + } + } else { + _selectedAction = -1; + } + + _recentCommand = _selectedRow; + _recentCommandSource = _commandSource; + } + break; + + case CAT_HOTSPOT: + _recentCommand = -1; + _recentCommandSource = CAT_NONE; + + if (_vm->_events->currentPos().y < MADS_SCENE_HEIGHT) { + scene._customDest = _vm->_events->currentPos() + scene._posAdjust; + _selectedAction = -1; + _pointEstablished = true; + } + break; + + case CAT_TALK_ENTRY: + if (_selectedRow >= 0) + _selectedAction = -1; + break; + + default: + break; + } + break; + + case AWAITING_THIS: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_hotspotId >= 0) { + if (_prepType) { + _articleNumber = _prepType; + _interAwaiting = AWAITING_THAT; + } else { + _selectedAction = -1; + } + + if (userInterface._category == CAT_HOTSPOT) { + scene._customDest = _vm->_events->mousePos() + scene._posAdjust; + _pointEstablished = true; + } + } + break; + default: + break; + } + break; + + case AWAITING_THAT: + switch (userInterface._category) { + case CAT_INV_LIST: + case CAT_HOTSPOT: + case CAT_INV_ANIM: + if (_secondObject >= 0) { + _selectedAction = -1; + + if (userInterface._category == CAT_HOTSPOT) { + if (!_pointEstablished) { + scene._customDest = _vm->_events->mousePos() + scene._posAdjust; + _pointEstablished = true; + } + } + } + break; + default: + break; + } + break; + + default: + break; + } +} + +void MADSAction::synchronize(Common::Serializer &s) { + _action.synchronize(s); + _activeAction.synchronize(s); + s.syncAsSint16LE(_articleNumber); + s.syncAsByte(_lookFlag); + s.syncAsByte(_textChanged); + s.syncAsSint16LE(_selectedRow); + s.syncAsSint16LE(_selectedAction); + s.syncAsSint16LE(_statusTextIndex); + s.syncAsSint16LE(_hotspotId); + _savedFields.synchronize(s); + + // TODO: When saving in Rex Village Hut, _senetence size() doesn't match + // string length. Find out why not + _sentence = Common::String(_sentence.c_str()); + s.syncString(_sentence); + + s.syncAsSint16LE(_verbType); + s.syncAsSint16LE(_prepType); + s.syncAsSint16LE(_commandSource); + s.syncAsSint16LE(_mainObjectSource); + s.syncAsSint16LE(_secondObject); + s.syncAsSint16LE(_secondObjectSource); + s.syncAsSint16LE(_recentCommandSource); + s.syncAsSint16LE(_recentCommand); + s.syncAsSint16LE(_interAwaiting); + s.syncAsSint16LE(_pickedWord); + s.syncAsByte(_pointEstablished); + s.syncAsByte(_inProgress); +} + +} // End of namespace MADS diff --git a/engines/mads/action.h b/engines/mads/action.h new file mode 100644 index 0000000000..cfd5a3be3f --- /dev/null +++ b/engines/mads/action.h @@ -0,0 +1,176 @@ +/* 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 MADS_ACTION_H +#define MADS_ACTION_H + +#include "common/scummsys.h" +#include "common/serializer.h" +#include "common/str.h" + +namespace MADS { + +enum TriggerMode { + SEQUENCE_TRIGGER_PARSER = 0, // Triggers parser + SEQUENCE_TRIGGER_DAEMON = 1, // Triggers step/daemon code + SEQUENCE_TRIGGER_PREPARE = 2 // Triggers preparser +}; + +enum InterAwaiting { + AWAITING_NONE = 0, + AWAITING_COMMAND = 1, // Initial state: waiting for a command verb + AWAITING_THIS = 2, // Waiting for object + AWAITING_THAT = 3, // Waiting for a second object + AWAITING_RIGHT_MOUSE = 4 // Waiting for mouse button release +}; + +enum { + VERB_NONE = 0, + VERB_LOOK = 3, + VERB_TAKE = 4, + VERB_PUSH = 5, + VERB_OPEN = 6, + VERB_PUT = 7, + VERB_TALKTO = 8, + VERB_GIVE = 9, + VERB_PULL = 10, + VERB_CLOSE = 11, + VERB_THROW = 12, + VERB_WALKTO = 13 +}; + +enum VerbType { VERB_ONLY, VERB_THIS, VERB_THAT, VERB_INIT }; + +enum PrepType { + PREP_NONE, PREP_WITH, PREP_TO, PREP_AT, PREP_FROM, PREP_ON, PREP_IN, + PREP_UNDER, PREP_BEHIND, PREP_RELATIONAL = 0xff +}; + +enum ScrCategory { + CAT_NONE = 0, CAT_COMMAND = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB = 3, + CAT_HOTSPOT = 4, CAT_INV_ANIM = 5, CAT_TALK_ENTRY = 6, CAT_INV_SCROLLER = 7, + CAT_12 = 12 +}; + +class MADSEngine; + +struct ActionDetails { + int _verbId; + int _objectNameId; + int _indirectObjectId; + + /** + * Synchronize the action details + */ + void synchronize(Common::Serializer &s); +}; + +struct ActionSavedFields { + bool _commandError; + int _commandSource; + int _command; + int _mainObject; + int _secondObject; + int _mainObjectSource; + int _secondObjectSource; + int _articleNumber; + int _lookFlag; + + /** + * Synchronize the saved action details + */ + void synchronize(Common::Serializer &s); +}; + +class MADSAction { +private: + MADSEngine *_vm; + Common::String _statusText; + + void appendVocab(int vocabId, bool capitalize = false); + + void startWalkingDirectly(int walkType); +public: + ActionDetails _action, _activeAction; + int _articleNumber; + bool _lookFlag; + int _selectedRow; + bool _textChanged; + int _selectedAction; + int _statusTextIndex; + int _hotspotId; + ActionSavedFields _savedFields; + Common::String _sentence; + + VerbType _verbType; + PrepType _prepType; + ScrCategory _commandSource; + ScrCategory _mainObjectSource; + int _secondObject; + ScrCategory _secondObjectSource; + ScrCategory _recentCommandSource; + bool _pointEstablished; + int _recentCommand; + InterAwaiting _interAwaiting; + bool _inProgress; + int _pickedWord; + +public: + MADSAction(MADSEngine *vm); + + void clear(); + void set(); + const Common::String &statusText() const { return _statusText; } + void refresh(); + + /** + * Accepts the currently defined sentence from the ScreenObjects parser. + * Copies the data, and checks to see if the action requires the player + * to walk to the given hotspot. + */ + void startAction(); + + void checkAction(); + bool isAction(int verbId, int objectNameId = 0, int indirectObjectId = 0); + bool isObject(int objectNameId); + bool isTarget(int objectNameId); + + /** + * Check the result of the current action on the sentence + * with the provision that the action is not yet complete. + */ + void checkActionAtMousePos(); + + /** + * Execute a click within the scene + */ + void leftClick(); + + /** + * Synchronize the saved action details + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_ACTION_H */ diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp new file mode 100644 index 0000000000..6af8a9ae5f --- /dev/null +++ b/engines/mads/animation.cpp @@ -0,0 +1,591 @@ +/* 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 "mads/animation.h" +#include "mads/compression.h" + +#define FILENAME_SIZE 13 + +namespace MADS { + +void AAHeader::load(Common::SeekableReadStream *f) { + _spriteSetsCount = f->readUint16LE(); + _miscEntriesCount = f->readUint16LE(); + _frameEntriesCount = f->readUint16LE(); + _messagesCount = f->readUint16LE(); + f->skip(1); + _flags = f->readByte(); + + f->skip(2); + _bgType = (AnimBgType)f->readUint16LE(); + _roomNumber = f->readUint16LE(); + f->skip(2); + _manualFlag = f->readUint16LE() != 0; + _spritesIndex = f->readUint16LE(); + _scrollPosition.x = f->readSint16LE(); + _scrollPosition.y = f->readSint16LE(); + _scrollTicks = f->readUint32LE(); + f->skip(6); + + char buffer[FILENAME_SIZE]; + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _interfaceFile = Common::String(buffer); + + for (int i = 0; i < 50; ++i) { + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + if (i < _spriteSetsCount) + _spriteSetNames.push_back(Common::String(buffer)); + } + + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _soundName = Common::String(buffer); + + f->skip(13); + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _dsrName = Common::String(buffer); + + f->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE - 1] = '\0'; + _fontResource = Common::String(buffer); +} + +/*------------------------------------------------------------------------*/ + +void AnimMessage::load(Common::SeekableReadStream *f) { + _soundId = f->readSint16LE(); + + char buffer[64]; + f->read(&buffer[0], 64); + _msg = Common::String(buffer); + f->skip(4); + _pos.x = f->readSint16LE(); + _pos.y = f->readSint16LE(); + _flags = f->readUint16LE(); + _rgb1[0] = f->readByte() << 2; + _rgb1[1] = f->readByte() << 2; + _rgb1[2] = f->readByte() << 2; + _rgb2[0] = f->readByte() << 2; + _rgb2[1] = f->readByte() << 2; + _rgb2[2] = f->readByte() << 2; + f->skip(2); // Space for kernelMsgIndex + _kernelMsgIndex = -1; + f->skip(6); + _startFrame = f->readUint16LE(); + _endFrame = f->readUint16LE(); + f->skip(2); +} + +void AnimFrameEntry::load(Common::SeekableReadStream *f, bool uiFlag) { + if (uiFlag) { + f->skip(2); + _frameNumber = -1; // Unused + _seqIndex = f->readByte(); + _spriteSlot._spritesIndex = f->readByte(); + _spriteSlot._frameNumber = (int8)f->readByte(); + f->skip(1); + _spriteSlot._position.x = f->readSint16LE(); + _spriteSlot._position.y = f->readSint16LE(); + } else { + _frameNumber = f->readUint16LE(); + if (_frameNumber & 0x8000) + _frameNumber = -(_frameNumber & 0x7fff); + + _seqIndex = f->readByte(); + _spriteSlot._spritesIndex = f->readByte(); + _spriteSlot._frameNumber = f->readUint16LE(); + if (_spriteSlot._frameNumber & 0x8000) + _spriteSlot._frameNumber = -(_spriteSlot._frameNumber & 0x7fff); + + _spriteSlot._position.x = f->readSint16LE(); + _spriteSlot._position.y = f->readSint16LE(); + _spriteSlot._depth = f->readSByte(); + _spriteSlot._scale = (int8)f->readByte(); + } +} + +/*------------------------------------------------------------------------*/ + +void AnimMiscEntry::load(Common::SeekableReadStream *f) { + _soundId = f->readByte(); + _msgIndex = f->readSByte(); + _numTicks = f->readUint16LE(); + _posAdjust.x = f->readSint16LE(); + _posAdjust.y = f->readSint16LE(); + _field8 = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +void AnimUIEntry::load(Common::SeekableReadStream *f) { + _probability = f->readUint16LE(); + _imageCount = f->readUint16LE(); + _firstImage = f->readUint16LE(); + _lastImage = f->readUint16LE(); + _counter = f->readSint16LE(); + for (int i = 0; i < ANIM_SPAWN_COUNT; ++i) + _spawn[i] = f->readByte(); + for (int i = 0; i < ANIM_SPAWN_COUNT; ++i) + _spawnFrame[i] = f->readUint16LE(); + _sound = f->readUint16LE() & 0xFF; + _soundFrame = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +Animation *Animation::init(MADSEngine *vm, Scene *scene) { + return new Animation(vm, scene); +} + +Animation::Animation(MADSEngine *vm, Scene *scene) : _vm(vm), _scene(scene) { + _font = nullptr; + _resetFlag = false; + _messageCtr = 0; + _skipLoad = false; + _freeFlag = false; + _unkIndex = -1; + _nextFrameTimer = 0; + _nextScrollTimer = 0; + _trigger = 0; + _triggerMode = SEQUENCE_TRIGGER_PREPARE; + _actionDetails._verbId = VERB_NONE; + _actionDetails._objectNameId = -1; + _actionDetails._indirectObjectId = -1; + _currentFrame = 0; + _oldFrameEntry = 0; +} + +Animation::~Animation() { + Scene &scene = _vm->_game->_scene; + + if (_header._manualFlag) + scene._sprites.remove(_spriteListIndexes[_header._spritesIndex]); + + for (int idx = 0; idx < _header._spriteSetsCount; ++idx) { + if (!_header._manualFlag || _header._spritesIndex != idx) + scene._sprites.remove(_spriteListIndexes[idx]); + } +} + +void Animation::load(UserInterface &interfaceSurface, DepthSurface &depthSurface, + const Common::String &resName, int flags, Common::Array<PaletteCycle> *palCycles, + SceneInfo *sceneInfo) { + Common::String resourceName = resName; + if (!resourceName.contains(".")) + resourceName += ".AA"; + + File f(resourceName); + MadsPack madsPack(&f); + + Common::SeekableReadStream *stream = madsPack.getItemStream(0); + _header.load(stream); + delete stream; + + if (_header._bgType == ANIMBG_INTERFACE) + flags |= PALFLAG_RESERVED; + + if (flags & ANIMFLAG_LOAD_BACKGROUND) { + loadInterface(interfaceSurface, depthSurface, _header, flags, palCycles, sceneInfo); + } + if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) { + // No data + _header._messagesCount = 0; + _header._frameEntriesCount = 0; + _header._miscEntriesCount = 0; + } + + // Initialize the reference list + _spriteListIndexes.clear(); + for (int i = 0; i < _header._spriteSetsCount; ++i) + _spriteListIndexes.push_back(-1); + + int streamIndex = 1; + _messages.clear(); + if (_header._messagesCount > 0) { + // Chunk 2: Following is a list of any messages for the animation + Common::SeekableReadStream *msgStream = madsPack.getItemStream(streamIndex++); + + for (int i = 0; i < _header._messagesCount; ++i) { + AnimMessage rec; + rec.load(msgStream); + _messages.push_back(rec); + } + + delete msgStream; + } + + _frameEntries.clear(); + if (_header._frameEntriesCount > 0) { + // Chunk 3: animation frame info + Common::SeekableReadStream *frameStream = madsPack.getItemStream(streamIndex++); + + for (int i = 0; i < _header._frameEntriesCount; i++) { + AnimFrameEntry rec; + rec.load(frameStream, flags & ANIMFLAG_LOAD_BACKGROUND); + _frameEntries.push_back(rec); + } + + delete frameStream; + } + + _miscEntries.clear(); + _uiEntries.clear(); + if (_header._miscEntriesCount > 0) { + // Chunk 4: Misc Data + Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++); + + if (flags & ANIMFLAG_LOAD_BACKGROUND) { + for (int i = 0; i < _header._miscEntriesCount; ++i) { + AnimUIEntry rec; + rec.load(miscStream); + _uiEntries.push_back(rec); + } + } else { + for (int i = 0; i < _header._miscEntriesCount; ++i) { + AnimMiscEntry rec; + rec.load(miscStream); + _miscEntries.push_back(rec); + } + } + + delete miscStream; + } + + // If the animation specifies a font, then load it for access + delete _font; + if (_header._flags & ANIMFLAG_CUSTOM_FONT) { + Common::String fontName = "*" + _header._fontResource; + _font = _vm->_font->getFont(fontName.c_str()); + } else { + _font = nullptr; + } + + // Load all the sprite sets for the animation + for (uint i = 0; i < _spriteSets.size(); ++i) + delete _spriteSets[i]; + _spriteSets.clear(); + _spriteSets.resize(_header._spriteSetsCount); + + for (int i = 0; i < _header._spriteSetsCount; ++i) { + if (_header._manualFlag && (i == _header._spritesIndex)) { + // Skip over field, since it's manually loaded + _spriteSets[i] = nullptr; + } else { + _spriteSets[i] = new SpriteAsset(_vm, _header._spriteSetNames[i], flags); + _spriteListIndexes[i] = _vm->_game->_scene._sprites.add(_spriteSets[i]); + } + } + + if (_header._manualFlag) { + Common::String assetResName = "*" + _header._spriteSetNames[_header._spritesIndex]; + SpriteAsset *sprites = new SpriteAsset(_vm, assetResName, flags); + _spriteSets[_header._spritesIndex] = sprites; + + _spriteListIndexes[_header._spritesIndex] = _scene->_sprites.add(sprites); + } + + Common::Array<int> usageList; + for (int idx = 0; idx < _header._spriteSetsCount; ++idx) + usageList.push_back(_spriteSets[idx]->_usageIndex); + + if (usageList.size() > 0) + _vm->_palette->_paletteUsage.updateUsage(usageList, _header._messagesCount); + + // Remaps the sprite list indexes for frames to the loaded sprite list indexes + for (uint i = 0; i < _frameEntries.size(); ++i) { + int spriteListIndex = _frameEntries[i]._spriteSlot._spritesIndex; + _frameEntries[i]._spriteSlot._spritesIndex = _spriteListIndexes[spriteListIndex]; + } + + f.close(); +} + +void Animation::preLoad(const Common::String &resName, int level) { + // No implementation in ScummVM, since access is fast enough that data + // doesn't need to be preloaded +} + +void Animation::startAnimation(int endTrigger) { + _messageCtr = 0; + _skipLoad = true; + + if (_header._manualFlag) { + _unkIndex = -1; + //SpriteAsset *asset = _scene->_sprites[_spriteListIndexes[_header._spritesIndex]]; + + // TODO: Weird stuff with _unkList. Seems like it's treated as pointers + // here, but in processText, it's used as POINTs? + + loadFrame(1); + } + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE) + _vm->_palette->refreshSceneColors(); + + _currentFrame = 0; + _oldFrameEntry = 0; + _nextFrameTimer = _vm->_game->_scene._frameStartTime; + _trigger = endTrigger; + _triggerMode = _vm->_game->_triggerSetupMode; + _actionDetails = _vm->_game->_scene._action._activeAction; + + for (int idx = 0; idx < _header._messagesCount; ++idx) { + _messages[idx]._kernelMsgIndex = -1; + } +} + +void Animation::loadFrame(int frameNumber) { + Scene &scene = _vm->_game->_scene; + if (_skipLoad) + return; + + Common::Point pt; + int spriteListIndex = _spriteListIndexes[_header._spritesIndex]; + SpriteAsset &spriteSet = *scene._sprites[spriteListIndex]; + + if (_unkIndex < 0) { + MSurface *frame = spriteSet.getFrame(0); + pt.x = frame->getBounds().left; + pt.y = frame->getBounds().top; + } else { + pt.x = _unkList[_unkIndex].x; + pt.y = _unkList[_unkIndex].y; + _unkIndex = 1 - _unkIndex; + } + + if (drawFrame(spriteSet, pt, frameNumber)) + error("drawFrame failure"); +} + +bool Animation::drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) { + return 0; +} + +void Animation::loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface, + AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo) { + _scene->_depthStyle = 0; + if (header._bgType <= ANIMBG_FULL_SIZE) { + _vm->_palette->_paletteUsage.setEmpty(); + sceneInfo->load(header._roomNumber, flags, header._interfaceFile, 0, depthSurface, interfaceSurface); + _scene->_depthStyle = sceneInfo->_depthStyle == 2 ? 1 : 0; + if (palCycles) { + palCycles->clear(); + for (uint i = 0; i < sceneInfo->_paletteCycles.size(); ++i) + palCycles->push_back(sceneInfo->_paletteCycles[i]); + } + } else if (header._bgType == ANIMBG_INTERFACE) { + // Load a scene interface + Common::String resourceName = "*" + header._interfaceFile; + interfaceSurface.load(resourceName); + + if (palCycles) + palCycles->clear(); + } else { + // Original has useless code here + } +} + +bool Animation::hasScroll() const { + return (_header._scrollPosition.x != 0) || (_header._scrollPosition.y != 0); +} + +void Animation::update() { + Scene &scene = _vm->_game->_scene; + + if (_header._manualFlag) { + int spriteListIndex = _spriteListIndexes[_header._spritesIndex]; + int newIndex = -1; + + for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) { + if (_frameEntries[idx]._frameNumber > _currentFrame) + break; + if (_frameEntries[idx]._spriteSlot._spritesIndex == spriteListIndex) + newIndex = _frameEntries[idx]._spriteSlot._frameNumber; + } + + if (newIndex >= 0) + loadFrame(newIndex); + } + + // If it's not time for the next frame, then exit + if (_vm->_game->_scene._frameStartTime < _nextFrameTimer) + return; + + for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) { + if (scene._spriteSlots[idx]._seqIndex >= 0x80) + scene._spriteSlots[idx]._flags = IMG_ERASE; + } + + // Validate the current frame + if (_currentFrame >= (int)_miscEntries.size()) { + // Is the animation allowed to be repeated? + if (_resetFlag) { + _currentFrame = 0; + _oldFrameEntry = 0; + } else { + _freeFlag = true; + return; + } + } + + // Handle executing any sound command for this frame + AnimMiscEntry &misc = _miscEntries[_currentFrame]; + if (misc._soundId) + _vm->_sound->command(misc._soundId); + + // Handle any screen scrolling + if (hasScroll()) { + scene._backgroundSurface.scrollX(_header._scrollPosition.x); + scene._backgroundSurface.scrollY(_header._scrollPosition.y); + scene._spriteSlots.fullRefresh(); + } + + // Handle any offset adjustment for sprites as of this frame + bool paChanged = false; + if (scene._posAdjust.x != misc._posAdjust.x) { + scene._posAdjust.x = misc._posAdjust.x; + paChanged = true; + } + if (scene._posAdjust.y != misc._posAdjust.y) { + scene._posAdjust.y = misc._posAdjust.y; + paChanged = true; + } + + if (paChanged) { + int newIndex = scene._spriteSlots.add(); + scene._spriteSlots[newIndex]._seqIndex = -1; + scene._spriteSlots[newIndex]._flags = IMG_REFRESH; + } + + // Main frame animation loop - frames get animated by being placed, as necessary, into the + // main sprite slot array + while ((uint)_oldFrameEntry < _frameEntries.size()) { + if (_frameEntries[_oldFrameEntry]._frameNumber > _currentFrame) + break; + else if (_frameEntries[_oldFrameEntry]._frameNumber == _currentFrame) { + // Found the correct frame + int spriteSlotIndex = 0; + int index = 0; + + for (;;) { + if ((spriteSlotIndex == 0) && (index < (int)scene._spriteSlots.size())) { + int seqIndex = _frameEntries[_oldFrameEntry]._seqIndex - scene._spriteSlots[index]._seqIndex; + if (seqIndex == 0x80) { + if (scene._spriteSlots[index] == _frameEntries[_oldFrameEntry]._spriteSlot) { + scene._spriteSlots[index]._flags = IMG_STATIC; + spriteSlotIndex = -1; + } + } + ++index; + continue; + } + + if (spriteSlotIndex == 0) { + int slotIndex = scene._spriteSlots.add(); + SpriteSlot &slot = scene._spriteSlots[slotIndex]; + slot.copy(_frameEntries[_oldFrameEntry]._spriteSlot); + slot._seqIndex = _frameEntries[_oldFrameEntry]._seqIndex + 0x80; + + SpriteAsset &spriteSet = *scene._sprites[ + scene._spriteSlots[slotIndex]._spritesIndex]; + slot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE; + } + break; + } + } + + ++_oldFrameEntry; + } + + // Handle the display of any messages + for (uint idx = 0; idx < _messages.size(); ++idx) { + if (_messages[idx]._kernelMsgIndex >= 0) { + // Handle currently active message + if ((_currentFrame < _messages[idx]._startFrame) || (_currentFrame > _messages[idx]._endFrame)) { + scene._kernelMessages.remove(_messages[idx]._kernelMsgIndex); + _messages[idx]._kernelMsgIndex = -1; + --_messageCtr; + } + } else if ((_currentFrame >= _messages[idx]._startFrame) && (_currentFrame <= _messages[idx]._endFrame)) { + // Start displaying the message + AnimMessage &me = _messages[idx]; + + // The color index to use is dependant on how many messages are currently on-screen + uint8 colIndex; + switch (_messageCtr) { + case 1: + colIndex = 252; + break; + case 2: + colIndex = 16; + break; + default: + colIndex = 250; + break; + } + + _vm->_palette->setEntry(colIndex, me._rgb1[0], me._rgb1[1], me._rgb1[2]); + _vm->_palette->setEntry(colIndex + 1, me._rgb2[0], me._rgb2[1], me._rgb2[2]); + + // Add a kernel message to display the given text + me._kernelMsgIndex = scene._kernelMessages.add(me._pos, colIndex * 0x101 + 0x100, + 0, 0, INDEFINITE_TIMEOUT, me._msg); + assert(me._kernelMsgIndex >= 0); + ++_messageCtr; + } + } + + // Move to the next frame + _currentFrame++; + if (_currentFrame >= (int)_miscEntries.size()) { + // Animation is complete + if (_trigger != 0) { + _vm->_game->_trigger = _trigger; + _vm->_game->_triggerMode = _triggerMode; + + if (_triggerMode != SEQUENCE_TRIGGER_DAEMON) { + // Copy the noun list + scene._action._activeAction = _actionDetails; + } + } + } + + int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1); + _nextFrameTimer = _vm->_game->_scene._frameStartTime + _miscEntries[frameNum]._numTicks; +} + +void Animation::setCurrentFrame(int frameNumber) { + _currentFrame = frameNumber; + _oldFrameEntry = 0; + _freeFlag = false; + + _nextScrollTimer = _nextFrameTimer = _vm->_game->_scene._frameStartTime; +} + +void Animation::setNextFrameTimer(int frameNumber) { + _nextFrameTimer = frameNumber; +} + +} // End of namespace MADS diff --git a/engines/mads/animation.h b/engines/mads/animation.h new file mode 100644 index 0000000000..15086d3e41 --- /dev/null +++ b/engines/mads/animation.h @@ -0,0 +1,230 @@ +/* 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 MADS_ANIMATION_H +#define MADS_ANIMATION_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/msurface.h" +#include "mads/scene_data.h" +#include "mads/font.h" +#include "mads/user_interface.h" + +namespace MADS { + +enum AnimFlag { + ANIMFLAG_DITHER = 0x0001, // Dither to 16 colors + ANIMFLAG_CUSTOM_FONT = 0x0020, // Load ccustom font + ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background + ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only +}; + +enum AnimBgType { + ANIMBG_ROOM = 1, ANIMBG_FULL_SIZE = 2, ANIMBG_BLACK_SCREEN = 3, + ANIMBG_INTERFACE = 4 +}; + +class MADSEngine; +class Scene; + +class AnimMessage { +public: + int16 _soundId; + Common::String _msg; + Common::Point _pos; + byte _rgb1[3], _rgb2[3]; + int _flags; + int _startFrame, _endFrame; + int _kernelMsgIndex; + + /** + * Loads data for the message from a stream + */ + void load(Common::SeekableReadStream *f); +}; + +class AnimFrameEntry { +public: + int _frameNumber; + int _seqIndex; + SpriteSlotSubset _spriteSlot; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f, bool uiFlag); +}; + +class AnimMiscEntry { +public: + int _soundId; + int _msgIndex; + int _numTicks; + Common::Point _posAdjust; + int _field8; + + /** + * Loads data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +#define ANIM_SPAWN_COUNT 2 + +class AnimUIEntry { +public: + int _probability; + int _imageCount; + int _firstImage; + int _lastImage; + int _counter; + int _spawn[ANIM_SPAWN_COUNT]; + int _spawnFrame[ANIM_SPAWN_COUNT]; + int _sound; + int _soundFrame; + + /** + * Loads the data for the record + */ + void load(Common::SeekableReadStream *f); +}; + +class AAHeader { +public: + int _spriteSetsCount; + int _miscEntriesCount; + int _frameEntriesCount; + int _messagesCount; + byte _flags; + AnimBgType _bgType; + int _roomNumber; + bool _manualFlag; + int _spritesIndex; + Common::Point _scrollPosition; + uint32 _scrollTicks; + Common::String _interfaceFile; + Common::StringArray _spriteSetNames; + Common::String _lbmFilename; + Common::String _spritesFilename; + Common::String _soundName; + Common::String _dsrName; + Common::String _fontResource; + + /** + * Loads the data for a animation file header + */ + void load(Common::SeekableReadStream *f); +}; + +class Animation { +private: + MADSEngine *_vm; + Scene *_scene; + + Common::Array<AnimMiscEntry> _miscEntries; + Common::Array<SpriteAsset *> _spriteSets; + Font *_font; + + bool _freeFlag; + bool _skipLoad; + int _unkIndex; + Common::Point _unkList[2]; + uint32 _nextFrameTimer; + uint32 _nextScrollTimer; + int _messageCtr; + int _trigger; + TriggerMode _triggerMode; + ActionDetails _actionDetails; + + /** + * Load data for a given frame + * @param frameNumber Frame number + */ + void loadFrame(int frameNumber); + + bool drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); + + /** + * Load the user interface display for an animation + */ + void loadInterface(UserInterface &interfaceSurface, DepthSurface &depthSurface, + AAHeader &header, int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo); + + /** + * Returns true if there is a scroll required + */ + bool hasScroll() const; +protected: + Animation(MADSEngine *vm, Scene *scene); +public: + AAHeader _header; + Common::Array<int> _spriteListIndexes; + Common::Array<AnimFrameEntry> _frameEntries; + Common::Array<AnimUIEntry> _uiEntries; + Common::Array<AnimMessage> _messages; + bool _resetFlag; + int _currentFrame; + int _oldFrameEntry; + + static Animation *init(MADSEngine *vm, Scene *scene); + /* + * Destructor + */ + ~Animation(); + + /** + * Loads animation data + */ + void load(UserInterface &interfaceSurface, DepthSurface &depthSurface, const Common::String &resName, + int flags, Common::Array<PaletteCycle> *palCycles, SceneInfo *sceneInfo); + + /** + * Preload animation data for the scene + */ + void preLoad(const Common::String &resName, int level); + + /** + * Setups up a loaded animation for playback + */ + void startAnimation(int endTrigger); + + /** + * Update the animation + */ + void update(); + + void setNextFrameTimer(int frameNumber); + int getNextFrameTimer() const { return _nextFrameTimer; } + void setCurrentFrame(int frameNumber); + int getCurrentFrame() const { return _currentFrame; } + + bool freeFlag() const { return _freeFlag; } + int roomNumber() const { return _header._roomNumber; } + + void resetSpriteSetsCount() { _header._spriteSetsCount = 0; } // CHECKME: See if it doesn't leak the memory when the destructor is called +}; + +} // End of namespace MADS + +#endif /* MADS_ANIMATION_H */ diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp new file mode 100644 index 0000000000..0bbf6177eb --- /dev/null +++ b/engines/mads/assets.cpp @@ -0,0 +1,228 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/assets.h" +#include "mads/compression.h" +#include "mads/events.h" +#include "mads/palette.h" + +namespace MADS { + +SpriteAsset::SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags) : _vm(vm) { + Common::String resName = resourceName; + if (!resName.hasSuffix(".SS") && !resName.hasSuffix(".ss")) + resName += ".SS"; + _srcSize = 0; + + File file(resName); + load(&file, flags); + + file.close(); +} + +SpriteAsset::SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags) : _vm(vm) { + _srcSize = 0; + + load(stream, flags); +} + +SpriteAsset::~SpriteAsset() { + if (_usageIndex) + _vm->_palette->_paletteUsage.resetPalFlags(_usageIndex); + + for (uint i = 0; i < _frames.size(); ++i) + delete _frames[i]._frame; + + delete _charInfo; +} + +void SpriteAsset::load(Common::SeekableReadStream *stream, int flags) { + int curFrame = 0; + uint32 frameOffset = 0; + MadsPack sprite(stream); + _frameRate = 0; + _pixelSpeed = 0; + _maxWidth = 0; + _maxHeight = 0; + _usageIndex = -1; + + Common::SeekableReadStream *spriteStream = sprite.getItemStream(0); + _mode = spriteStream->readByte(); + spriteStream->skip(1); + int type1 = spriteStream->readUint16LE(); + int type2 = spriteStream->readUint16LE(); + _isBackground = (type1 != 0) && (type2 < 4); + spriteStream->skip(32); + _frameCount = spriteStream->readUint16LE(); + + if ((flags & SPRITE_SET_CHAR_INFO) == 0) + _charInfo = nullptr; + else + _charInfo = new SpriteSetCharInfo(spriteStream); + + delete spriteStream; + + // Get the palette data + Common::SeekableReadStream *palStream = sprite.getItemStream(2); + Common::Array<RGB6> palette; + + int numColors = palStream->readUint16LE(); + assert(numColors <= 252); + _colorCount = numColors; + + // Load in the palette + palette.resize(numColors); + for (int i = 0; i < numColors; ++i) + palette[i].load(palStream); + delete palStream; + + // Process the palette data + if (flags & 9) { + _usageIndex = 0; + + if (flags & 8) { + int newPalCtr = 0; + + for (uint i = 0; i < palette.size(); ++i) { + RGB6 &rgb = palette[i]; + + // Scan for existing rgb at beginning of the main palette + bool found = false; + for (int pIndex = 0; pIndex < 4 && !found; ++pIndex) { + byte *palP = &_vm->_palette->_mainPalette[pIndex * 3]; + if (palP[0] == rgb.r && palP[1] == rgb.g && palP[2] == rgb.b) { + rgb._palIndex = pIndex; + found = true; + } + } + + if (!found) { + // Existing palette entry not found, so need to add it in + int palIndex = (0xF7F607 >> (8 * newPalCtr)) & 0xff; + byte *palP = &_vm->_palette->_mainPalette[palIndex * 3]; + palP[0] = rgb.r; + palP[1] = rgb.g; + palP[2] = rgb.b; + rgb._palIndex = palIndex; + + newPalCtr = MIN(newPalCtr + 1, 2); + } + } + } + } else { + _usageIndex = _vm->_palette->_paletteUsage.process(palette, flags); + assert(_usageIndex >= 0); + } + + spriteStream = sprite.getItemStream(1); + Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); + SpriteAssetFrame frame; + Common::Array<int> frameSizes; + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + frame._stream = 0; + frame._comp = 0; + frameOffset = spriteStream->readUint32LE(); + _frameOffsets.push_back(frameOffset); + uint32 frameSize = spriteStream->readUint32LE(); + frameSizes.push_back(frameSize); + + frame._bounds.left = spriteStream->readSint16LE(); + frame._bounds.top = spriteStream->readSint16LE(); + frame._bounds.setWidth(spriteStream->readUint16LE()); + frame._bounds.setHeight(spriteStream->readUint16LE()); + + if (curFrame == 0) + debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", + _frameCount, frame._bounds.left, frame._bounds.top, + frame._bounds.width(), frame._bounds.height()); + + if (_mode == 0) { + // Create a frame and decompress the raw pixel data + uint32 currPos = (uint32)spriteDataStream->pos(); + frame._frame = new MSprite(spriteDataStream, palette, frame._bounds); + assert((uint32)spriteDataStream->pos() == (currPos + frameSize)); + } + + _frames.push_back(frame); + } + + if (_mode != 0) { + // Handle decompressing Fab encoded data + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + FabDecompressor fab; + + int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] : + _frameOffsets[curFrame + 1] - _frameOffsets[curFrame]; + byte *srcData = new byte[srcSize]; + assert(srcData); + spriteDataStream->read(srcData, srcSize); + + byte *destData = new byte[frameSizes[curFrame]]; + assert(destData); + + fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]); + + // Load the frames + Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]); + _frames[curFrame]._frame = new MSprite(rs, palette, _frames[curFrame]._bounds); + delete rs; + + delete[] srcData; + delete[] destData; + } + } + + delete spriteStream; + delete spriteDataStream; +} + +MSprite *SpriteAsset::getFrame(int frameIndex) { + if ((uint)frameIndex < _frames.size()) { + return _frames[frameIndex]._frame; + } else { + debugC(kDebugGraphics, "SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size()); + return _frames[_frames.size() - 1]._frame; + } +} + +/*------------------------------------------------------------------------*/ + +SpriteSetCharInfo::SpriteSetCharInfo(Common::SeekableReadStream *s) { + _totalFrames = s->readByte(); + s->skip(1); + _numEntries = s->readUint16LE(); + + for (int i = 0; i < 16; ++i) + _startFrames[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _stopFrames[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _ticksList[i] = s->readUint16LE(); + + _velocity = s->readUint16LE(); + _ticksAmount = s->readByte(); + _centerOfGravity = s->readByte(); +} + +} // End of namespace MADS diff --git a/engines/mads/assets.h b/engines/mads/assets.h new file mode 100644 index 0000000000..9242802187 --- /dev/null +++ b/engines/mads/assets.h @@ -0,0 +1,111 @@ +/* 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 MADS_ASSETS_H +#define MADS_ASSETS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/palette.h" + +namespace MADS { + +#define SPRITE_SET_CHAR_INFO 4 + +class MADSEngine; +class MSprite; +class MSurface; + +struct SpriteAssetFrame { + uint32 _stream; + Common::Rect _bounds; + uint32 _comp; + MSprite *_frame; +}; + +class SpriteSetCharInfo { +public: + SpriteSetCharInfo(Common::SeekableReadStream *s); + + int _totalFrames; + int _numEntries; + int _startFrames[16]; + int _stopFrames[16]; + int _ticksList[16]; + int _velocity; + int _ticksAmount; + int _centerOfGravity; +}; + +class SpriteAsset { +private: + MADSEngine *_vm; + byte _palette[PALETTE_SIZE]; + int _colorCount; + uint32 _srcSize; + int _frameRate, _pixelSpeed; + int _maxWidth, _maxHeight; + int _frameCount; + Common::Array<uint32> _frameOffsets; + Common::Array<SpriteAssetFrame> _frames; + uint8 _mode; + bool _isBackground; + + /** + * Load the data for the asset + */ + void load(Common::SeekableReadStream *stream, int flags); +public: + SpriteSetCharInfo *_charInfo; + int _usageIndex; +public: + /** + * Constructor + */ + SpriteAsset(MADSEngine *vm, const Common::String &resourceName, int flags); + + /** + * Constructor + */ + SpriteAsset(MADSEngine *vm, Common::SeekableReadStream *stream, int flags); + + /** + * Destructor + */ + ~SpriteAsset(); + + int getCount() { return _frameCount; } + int getFrameRate() const { return _frameRate; } + int getPixelSpeed() const { return _pixelSpeed; } + int getFrameWidth(int index); + int getFrameHeight(int index); + int getMaxFrameWidth() const { return _maxWidth; } + int getMaxFrameHeight() const { return _maxHeight; } + MSprite *getFrame(int frameIndex); + byte *getPalette() { return _palette; } + int getColorCount() { return _colorCount; } + bool isBackground() const { return _isBackground; } +}; + +} // End of namespace MADS + +#endif /* MADS_ASSETS_H */ diff --git a/engines/mads/audio.cpp b/engines/mads/audio.cpp new file mode 100644 index 0000000000..1c61e13957 --- /dev/null +++ b/engines/mads/audio.cpp @@ -0,0 +1,129 @@ +/* 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 "mads/audio.h" +#include "mads/compression.h" + +#include "common/stream.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "audio/decoders/raw.h" + +namespace MADS { + +AudioPlayer::AudioPlayer(Audio::Mixer *mixer, uint32 gameID) : _mixer(mixer), _gameID(gameID) { + setVolume(Audio::Mixer::kMaxChannelVolume); + setDefaultSoundGroup(); +} + +AudioPlayer::~AudioPlayer() { + _dsrEntries.clear(); +} + +bool AudioPlayer::isPlaying() const { + return _mixer->isSoundHandleActive(_handle); +} + +void AudioPlayer::setVolume(int volume) { + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume); +} + +void AudioPlayer::setDefaultSoundGroup() { + switch (_gameID) { + case GType_RexNebular: + setSoundGroup("rex009.dsr"); + break; + case GType_Dragonsphere: + setSoundGroup("drag009.dsr"); + break; + case GType_Phantom: + setSoundGroup("phan009.dsr"); + break; + default: + error("setDefaultSoundGroup: Unknown game"); + } +} + +void AudioPlayer::setSoundGroup(const Common::String &filename) { + _dsrEntries.clear(); + + _filename = filename; + _dsrFile.open(filename); + + // Read header + uint16 entryCount = _dsrFile.readUint16LE(); + + for (uint16 i = 0; i < entryCount; i++) { + DSREntry newEntry; + newEntry.frequency = _dsrFile.readUint16LE(); + newEntry.channels = _dsrFile.readUint32LE(); + newEntry.compSize = _dsrFile.readUint32LE(); + newEntry.uncompSize = _dsrFile.readUint32LE(); + newEntry.offset = _dsrFile.readUint32LE(); + _dsrEntries.push_back(newEntry); + } + + _dsrFile.close(); +} + +void AudioPlayer::playSound(int soundIndex, bool loop) { + if (_dsrEntries.empty()) { + warning("DSR file not loaded, not playing sound"); + return; + } + + if (soundIndex < 0 || soundIndex > (int)_dsrEntries.size() - 1) { + warning("Invalid sound index: %i (max %i), not playing sound", soundIndex, _dsrEntries.size() - 1); + return; + } + + // Get sound data + FabDecompressor fab; + int32 compSize = _dsrEntries[soundIndex].compSize; + int32 uncompSize = _dsrEntries[soundIndex].uncompSize; + int32 offset = _dsrEntries[soundIndex].offset; + int16 frequency = _dsrEntries[soundIndex].frequency; + byte *compData = new byte[compSize]; + byte *buffer = new byte[uncompSize]; + _dsrFile.open(_filename); + _dsrFile.seek(offset, SEEK_SET); + _dsrFile.read(compData, compSize); + _dsrFile.close(); + + fab.decompress(compData, compSize, buffer, uncompSize); + + // Play sound + Audio::AudioStream *stream = Audio::makeLoopingAudioStream( + Audio::makeRawStream(buffer, uncompSize, frequency, Audio::FLAG_UNSIGNED), + loop ? 0 : 1); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &_handle, stream, -1, Audio::Mixer::kMaxChannelVolume); + + /* + // Dump the sound file + FILE *destFile = fopen("sound.raw", "wb"); + fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile); + fclose(destFile); + */ +} + +} // End of namespace M4 diff --git a/engines/mads/audio.h b/engines/mads/audio.h new file mode 100644 index 0000000000..21f4bed59a --- /dev/null +++ b/engines/mads/audio.h @@ -0,0 +1,64 @@ +/* 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 MADS_AUDIO_H +#define MADS_AUDIO_H + +#include "mads/resources.h" + +#include "common/array.h" +#include "audio/mixer.h" + +namespace MADS { + +struct DSREntry { + int16 frequency; + int channels; + int32 compSize; + int32 uncompSize; + int32 offset; +}; + +class AudioPlayer { +public: + AudioPlayer(Audio::Mixer *mixer, uint32 gameID); + ~AudioPlayer(); + + void setSoundGroup(const Common::String &filename); + void setDefaultSoundGroup(); + void playSound(int soundIndex, bool loop = false); + void setVolume(int volume); + bool isPlaying() const; + + private: + Audio::Mixer *_mixer; + Audio::SoundHandle _handle; + uint32 _gameID; + + File _dsrFile; + Common::String _filename; + Common::Array<DSREntry> _dsrEntries; +}; + +} // End of namespace MADS + +#endif diff --git a/engines/mads/compression.cpp b/engines/mads/compression.cpp new file mode 100644 index 0000000000..79cd1786de --- /dev/null +++ b/engines/mads/compression.cpp @@ -0,0 +1,194 @@ +/* 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 "mads/compression.h" + +namespace MADS { + +const char *const madsPackString = "MADSPACK"; +const char *const FabInputExceededError = "FabDecompressor - Passed end of input buffer during decompression"; +const char *const FabOutputExceededError = "FabDecompressor - Decompressed data exceeded specified size"; + +bool MadsPack::isCompressed(Common::SeekableReadStream *stream) { + // Check whether the passed stream is packed + + char tempBuffer[8]; + stream->seek(0); + if (stream->read(tempBuffer, 8) == 8) { + if (!strncmp(tempBuffer, madsPackString, 8)) + return true; + } + + return false; +} + +MadsPack::MadsPack(Common::SeekableReadStream *stream) { + initialize(stream); +} + +MadsPack::MadsPack(const Common::String &resourceName, MADSEngine *vm) { + File file(resourceName); + initialize(&file); + file.close(); +} + +void MadsPack::initialize(Common::SeekableReadStream *stream) { + if (!MadsPack::isCompressed(stream)) + error("Attempted to decompress a resource that was not MadsPacked"); + + stream->seek(14); + _count = stream->readUint16LE(); + _items = new MadsPackEntry[_count]; + + byte *headerData = new byte[0xA0]; + byte *header = headerData; + stream->read(headerData, 0xA0); + + for (int i = 0; i < _count; ++i, header += 10) { + // Get header data + _items[i]._type = (CompressionType)*header; + _items[i]._priority = *(header + 1); + _items[i]._size = READ_LE_UINT32(header + 2); + _items[i]._compressedSize = READ_LE_UINT32(header + 6); + + byte *sourceData = new byte[_items[i]._compressedSize]; + stream->read(sourceData, _items[i]._compressedSize); + + switch (_items[i]._type) { + case COMPRESS_NONE: + // Entry isn't compressed + _items[i]._data = sourceData; + break; + + case COMPRESS_FAB: { + // Decompress the entry + _items[i]._data = new byte[_items[i]._size]; + + FabDecompressor fab; + fab.decompress(sourceData, _items[i]._compressedSize, _items[i]._data, _items[i]._size); + delete[] sourceData; + break; + } + + default: + error("Unknown compression type encountered"); + } + } + + delete[] headerData; + _dataOffset = stream->pos(); +} + +MadsPack::~MadsPack() { + for (int i = 0; i < _count; ++i) + delete[] _items[i]._data; + delete[] _items; +} + +//-------------------------------------------------------------------------- + +void FabDecompressor::decompress(const byte *srcData, int srcSize, byte *destData, int destSize) { + byte copyLen, copyOfsShift, copyOfsMask, copyLenMask; + unsigned long copyOfs; + byte *destP; + + // Validate that the data starts with the FAB header + if (strncmp((const char *)srcData, "FAB", 3) != 0) + error("FabDecompressor - Invalid compressed data"); + + int shiftVal = srcData[3]; + if ((shiftVal < 10) || (shiftVal > 13)) + error("FabDecompressor - Invalid shift start"); + + copyOfsShift = 16 - shiftVal; + copyOfsMask = 0xFF << (shiftVal - 8); + copyLenMask = (1 << copyOfsShift) - 1; + copyOfs = 0xFFFF0000; + destP = destData; + + // Initialize data fields + _srcData = srcData; + _srcP = _srcData + 6; + _srcSize = srcSize; + _bitsLeft = 16; + _bitBuffer = READ_LE_UINT16(srcData + 4); + + for (;;) { + if (getBit() == 0) { + if (getBit() == 0) { + copyLen = ((getBit() << 1) | getBit()) + 2; + copyOfs = *_srcP++ | 0xFFFFFF00; + } else { + copyOfs = (((_srcP[1] >> copyOfsShift) | copyOfsMask) << 8) | _srcP[0]; + copyLen = _srcP[1] & copyLenMask; + _srcP += 2; + if (copyLen == 0) { + copyLen = *_srcP++; + if (copyLen == 0) + break; + else if (copyLen == 1) + continue; + else + copyLen++; + } else { + copyLen += 2; + } + copyOfs |= 0xFFFF0000; + } + while (copyLen-- > 0) { + if (destP - destData == destSize) + error(FabOutputExceededError); + + *destP = destP[(signed int)copyOfs]; + destP++; + } + } else { + if (_srcP - srcData == srcSize) + error(FabInputExceededError); + if (destP - destData == destSize) + error(FabOutputExceededError); + + *destP++ = *_srcP++; + } + } + + if (destP - destData != destSize) + error("FabDecompressor - Decompressed data does not match header decompressed size"); +} + +int FabDecompressor::getBit() { + _bitsLeft--; + if (_bitsLeft == 0) { + if (_srcP - _srcData == _srcSize) + error(FabInputExceededError); + + _bitBuffer = (READ_LE_UINT16(_srcP) << 1) | (_bitBuffer & 1); + _srcP += 2; + _bitsLeft = 16; + } + + int bit = _bitBuffer & 1; + _bitBuffer >>= 1; + return bit; +} + +} // End of namespace MADS diff --git a/engines/mads/compression.h b/engines/mads/compression.h new file mode 100644 index 0000000000..f7381e4af3 --- /dev/null +++ b/engines/mads/compression.h @@ -0,0 +1,89 @@ +/* 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 MADS_COMPRESSION_H +#define MADS_COMPRESSION_H + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/memstream.h" +#include "common/stream.h" + +#include "mads/mads.h" + +namespace MADS { + +enum CompressionType { COMPRESS_NONE = 0, COMPRESS_FAB = 1 }; + +struct MadsPackEntry { +public: + CompressionType _type; + byte _priority; + uint32 _size; + uint32 _compressedSize; + byte *_data; +}; + +class MadsPack { +private: + MadsPackEntry *_items; + int _count; + int _dataOffset; + + void initialize(Common::SeekableReadStream *stream); +public: + static bool isCompressed(Common::SeekableReadStream *stream); + MadsPack(Common::SeekableReadStream *stream); + MadsPack(const Common::String &resourceName, MADSEngine *_vm); + ~MadsPack(); + + int getCount() const { return _count; } + MadsPackEntry &getItem(int index) const { + assert(index < _count); + return _items[index]; } + MadsPackEntry &operator[](int index) const { + assert(index < _count); + return _items[index]; + } + Common::MemoryReadStream *getItemStream(int index) { + assert(index < _count); + return new Common::MemoryReadStream(_items[index]._data, _items[index]._size, + DisposeAfterUse::NO); + } + int getDataOffset() const { return _dataOffset; } +}; + +class FabDecompressor { +private: + int _bitsLeft; + uint32 _bitBuffer; + const byte *_srcData, *_srcP; + int _srcSize; + + int getBit(); +public: + void decompress(const byte *srcData, int srcSize, byte *destData, int destSize); +}; + +} // End of namespace MADS + +#endif diff --git a/engines/mads/configure.engine b/engines/mads/configure.engine new file mode 100644 index 0000000000..60d833e9e8 --- /dev/null +++ b/engines/mads/configure.engine @@ -0,0 +1,3 @@ +# This file is included from the main "configure" script +# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] +add_engine mads "Rex Nebular and the Cosmic Gender Bender" no diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp new file mode 100644 index 0000000000..1ff42c5e2b --- /dev/null +++ b/engines/mads/debugger.cpp @@ -0,0 +1,326 @@ +/* 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 "common/file.h" +#include "mads/mads.h" +#include "mads/debugger.h" + +namespace MADS { + +Debugger::Debugger(MADSEngine *vm) : GUI::Debugger(), _vm(vm) { + _showMousePos = false; + + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_LoadScene)); + registerCmd("show_hotspots", WRAP_METHOD(Debugger, Cmd_ShowHotSpots)); + registerCmd("list_hotspots", WRAP_METHOD(Debugger, Cmd_ListHotSpots)); + registerCmd("play_sound", WRAP_METHOD(Debugger, Cmd_PlaySound)); + registerCmd("play_audio", WRAP_METHOD(Debugger, Cmd_PlayAudio)); + registerCmd("show_codes", WRAP_METHOD(Debugger, Cmd_ShowCodes)); + registerCmd("dump_file", WRAP_METHOD(Debugger, Cmd_DumpFile)); + registerCmd("show_quote", WRAP_METHOD(Debugger, Cmd_ShowQuote)); + registerCmd("show_vocab", WRAP_METHOD(Debugger, Cmd_ShowVocab)); + registerCmd("dump_vocab", WRAP_METHOD(Debugger, Cmd_DumpVocab)); + registerCmd("show_message", WRAP_METHOD(Debugger, Cmd_ShowMessage)); + registerCmd("show_item", WRAP_METHOD(Debugger, Cmd_ShowItem)); + registerCmd("dump_items", WRAP_METHOD(Debugger, Cmd_DumpItems)); + registerCmd("item", WRAP_METHOD(Debugger, Cmd_Item)); +} + +static int strToInt(const char *s) { + if (!*s) + // No string at all + return 0; + else if (toupper(s[strlen(s) - 1]) != 'H') + // Standard decimal string + return atoi(s); + + // Hexadecimal string + uint tmp = 0; + int read = sscanf(s, "%xh", &tmp); + if (read < 1) + error("strToInt failed on string \"%s\"", s); + return (int)tmp; +} + +bool Debugger::Cmd_Mouse(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s [ on | off ]\n", argv[0]); + } else { + _showMousePos = strcmp(argv[1], "on") == 0; + } + + return true; +} + +bool Debugger::Cmd_LoadScene(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Current scene is: %d\n", _vm->_game->_scene._currentSceneId); + debugPrintf("Usage: %s <scene number>\n", argv[0]); + return true; + } else { + _vm->_game->_scene._nextSceneId = strToInt(argv[1]); + return false; + } +} + +bool Debugger::Cmd_ShowHotSpots(int argc, const char **argv) { + Scene &scene = _vm->_game->_scene; + + // hotspots + byte hotspotCol = _vm->getRandomNumber(255); + for (uint i = 0; i < scene._hotspots.size(); i++) { + scene._backgroundSurface.frameRect(scene._hotspots[i]._bounds, hotspotCol); + } + + // Dynamic hotspots (red) + hotspotCol = _vm->getRandomNumber(255); + for (uint i = 0; i < scene._dynamicHotspots.size(); i++) { + scene._backgroundSurface.frameRect(scene._dynamicHotspots[i]._bounds, hotspotCol); + } + + scene._spriteSlots.fullRefresh(); + return false; +} + +bool Debugger::Cmd_ListHotSpots(int argc, const char **argv) { + Hotspots &hotspots = _vm->_game->_scene._hotspots; + + debugPrintf("%d hotspots present\n", hotspots.size()); + + for (uint index = 0; index < hotspots.size(); ++index) { + debugPrintf("(%d): %p x1 = %d; y1 = %d; x2 = %d; y2 = %d\n", + index, (void *)&hotspots[index], + hotspots[index]._bounds.left, hotspots[index]._bounds.top, + hotspots[index]._bounds.right, hotspots[index]._bounds.bottom); + } + + return true; +} + +bool Debugger::Cmd_PlaySound(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s <sound file>\n", argv[0]); + } else { + int commandId = strToInt(argv[1]); + int param = (argc >= 3) ? strToInt(argv[2]) : 0; + + _vm->_sound->command(commandId, param); + } + + return false; +} + +bool Debugger::Cmd_PlayAudio(int argc, const char **argv) { + if (argc < 2) { + debugPrintf("Usage: %s <sound index> <sound group>\n", argv[0]); + debugPrintf("If the sound group isn't defined, the default one will be used\n"); + } else { + int index = strToInt(argv[1]); + Common::String soundGroup = (argc >= 3) ? argv[2] : ""; + if (argc >= 3) + _vm->_audio->setSoundGroup(argv[2]); + else + _vm->_audio->setDefaultSoundGroup(); + + _vm->_audio->playSound(index); + } + + return true; +} + +bool Debugger::Cmd_ShowCodes(int argc, const char **argv) { + Scene &scene = _vm->_game->_scene; + + // Copy the depth/walk surface to the background and flag for screen refresh + scene._depthSurface.copyTo(&scene._backgroundSurface); + scene._spriteSlots.fullRefresh(); + + // Draw the locations of scene nodes onto the background + int color = _vm->getRandomNumber(255); + for (int i = 0; i < (int)scene._sceneInfo->_nodes.size(); ++i) { + Common::Point &pt = scene._sceneInfo->_nodes[i]._walkPos; + + scene._backgroundSurface.hLine(pt.x - 2, pt.y, pt.x + 2, color); + scene._backgroundSurface.vLine(pt.x, pt.y - 2, pt.y + 2, color); + } + + return false; +} + +bool Debugger::Cmd_DumpFile(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Usage: %s <resource>\n", argv[0]); + } else { + Common::DumpFile outFile; + Common::File inFile; + + if (!inFile.open(argv[1])) { + debugPrintf("Specified resource does not exist\n"); + } else { + outFile.open(argv[1]); + byte *data = new byte[inFile.size()]; + + inFile.read(data, inFile.size()); + outFile.write(data, inFile.size()); + outFile.flush(); + + delete[] data; + inFile.close(); + outFile.close(); + + debugPrintf("File written successfully.\n"); + } + } + + return true; +} + +bool Debugger::Cmd_ShowQuote(int argc, const char **argv) { + if (argc != 2) + debugPrintf("Usage: %s <quote number>\n", argv[0]); + else + debugPrintf("%s", _vm->_game->getQuote(strToInt(argv[1])).c_str()); + + return true; +} + +bool Debugger::Cmd_ShowVocab(int argc, const char **argv) { + if (argc != 2) { + for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) { + debugPrintf("%03d: '%s'\n", i, _vm->_game->_scene.getVocab(i + 1).c_str()); + } + } else { + int vocabId = strToInt(argv[1]); + debugPrintf("%03d: '%s'\n", vocabId, _vm->_game->_scene.getVocab(vocabId + 1).c_str()); + } + + return true; +} + +bool Debugger::Cmd_DumpVocab(int argc, const char **argv) { + Common::DumpFile outFile; + outFile.open("vocab.txt"); + + for (uint32 i = 0; i < _vm->_game->_scene.getVocabStringsCount(); i++) { + Common::String curId = Common::String::format("%x", i + 1); + Common::String curVocab = _vm->_game->_scene.getVocab(i + 1); + curVocab.toUppercase(); + + for (uint j = 0; j < curVocab.size(); j++) { + if (curVocab[j] == ' ' || curVocab[j] == '-') + curVocab.setChar('_', j); + } + + Common::String cur = "\tNOUN_" + curVocab + " = 0x" + curId + ",\n"; + + outFile.writeString(cur.c_str()); + } + + outFile.flush(); + outFile.close(); + + debugPrintf("Game vocab dumped\n"); + + return true; +} + +bool Debugger::Cmd_ShowMessage(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Usage: %s <message number>\n", argv[0]); + } else { + int messageId = strToInt(argv[1]); + Common::StringArray msg = _vm->_game->getMessage(messageId); + for (uint idx = 0; idx < msg.size(); ++idx) { + Common::String srcLine = msg[idx]; + debugPrintf("%s\n", srcLine.c_str()); + } + } + + return true; +} + +bool Debugger::Cmd_ShowItem(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + if (argc != 2) { + for (uint32 i = 0; i < objects.size(); i++) { + Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId); + debugPrintf("%03d: '%s'\n", i, desc.c_str()); + } + } else { + int vocabId = strToInt(argv[1]); + Common::String desc = _vm->_game->_scene.getVocab(objects[vocabId]._descId); + debugPrintf("%03d: '%s'\n", vocabId, desc.c_str()); + } + + return true; +} + +bool Debugger::Cmd_DumpItems(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + Common::DumpFile outFile; + outFile.open("items.txt"); + + for (uint32 i = 0; i < objects.size(); i++) { + Common::String curId = Common::String::format("%d", i); + Common::String desc = _vm->_game->_scene.getVocab(objects[i]._descId); + desc.toUppercase(); + + for (uint j = 0; j < desc.size(); j++) { + if (desc[j] == ' ' || desc[j] == '-') + desc.setChar('_', j); + } + + Common::String cur = "\tOBJ_" + desc + " = " + curId + ",\n"; + + outFile.writeString(cur.c_str()); + } + + outFile.flush(); + outFile.close(); + + debugPrintf("Game items dumped\n"); + + return true; +} + +bool Debugger::Cmd_Item(int argc, const char **argv) { + InventoryObjects &objects = _vm->_game->_objects; + + if (argc != 2) { + debugPrintf("Usage: %s <item number>\n", argv[0]); + return true; + } else { + int objectId = strToInt(argv[1]); + + if (!objects.isInInventory(objectId)) + objects.addToInventory(objectId); + + debugPrintf("Item added.\n"); + return false; + } +} + +} // End of namespace MADS diff --git a/engines/mads/debugger.h b/engines/mads/debugger.h new file mode 100644 index 0000000000..351eb13615 --- /dev/null +++ b/engines/mads/debugger.h @@ -0,0 +1,61 @@ +/* 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 MADS_DEBUGGER_H +#define MADS_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace MADS { + +class MADSEngine; + +class Debugger : public GUI::Debugger { +private: + MADSEngine *_vm; +protected: + bool Cmd_Mouse(int argc, const char **argv); + bool Cmd_LoadScene(int argc, const char **argv); + bool Cmd_ShowHotSpots(int argc, const char **argv); + bool Cmd_ListHotSpots(int argc, const char **argv); + bool Cmd_PlaySound(int argc, const char **argv); + bool Cmd_PlayAudio(int argc, const char **argv); + bool Cmd_ShowCodes(int argc, const char **argv); + bool Cmd_DumpFile(int argc, const char **argv); + bool Cmd_ShowQuote(int argc, const char **argv); + bool Cmd_ShowVocab(int argc, const char **argv); + bool Cmd_DumpVocab(int argc, const char **argv); + bool Cmd_ShowMessage(int argc, const char **argv); + bool Cmd_ShowItem(int argc, const char **argv); + bool Cmd_DumpItems(int argc, const char **argv); + bool Cmd_Item(int argc, const char **argv); +public: + bool _showMousePos; +public: + Debugger(MADSEngine *vm); + virtual ~Debugger() {} +}; + +} // End of namespace MADS + +#endif /* MADS_DEBUGGER_H */ diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp new file mode 100644 index 0000000000..971acde024 --- /dev/null +++ b/engines/mads/detection.cpp @@ -0,0 +1,194 @@ +/* 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 "mads/mads.h" + +#include "base/plugins.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "common/memstream.h" +#include "engines/advancedDetector.h" +#include "common/system.h" +#include "graphics/colormasks.h" +#include "graphics/surface.h" +#include "mads/events.h" +#include "mads/game.h" + +#define MAX_SAVES 99 + +namespace MADS { + +struct MADSGameDescription { + ADGameDescription desc; + + int gameID; + uint32 features; +}; + +uint32 MADSEngine::getGameID() const { + return _gameDescription->gameID; +} + +uint32 MADSEngine::getGameFeatures() const { + return _gameDescription->features; +} + +uint32 MADSEngine::getFeatures() const { + return _gameDescription->desc.flags; +} + +Common::Language MADSEngine::getLanguage() const { + return _gameDescription->desc.language; +} + +Common::Platform MADSEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + +} // End of namespace MADS + +static const PlainGameDescriptor MADSGames[] = { + {"MADS", "MADS"}, + {"dragonsphere", "Dragonsphere"}, + {"nebular", "Rex Nebular and the Cosmic Gender Bender"}, + {"phantom", "Return of the Phantom"}, + {0, 0} +}; + +#include "mads/detection_tables.h" + +class MADSMetaEngine : public AdvancedMetaEngine { +public: + MADSMetaEngine() : AdvancedMetaEngine(MADS::gameDescriptions, sizeof(MADS::MADSGameDescription), MADSGames) { + _maxScanDepth = 3; + } + + virtual const char *getName() const { + return "MADS Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "MADS (c)"; + } + + virtual bool hasFeature(MetaEngineFeature f) const; + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; + virtual SaveStateList listSaves(const char *target) const; + virtual int getMaximumSaveSlot() const; + virtual void removeSaveState(const char *target, int slot) const; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const; +}; + +bool MADSMetaEngine::hasFeature(MetaEngineFeature f) const { + return + (f == kSupportsListSaves) || + (f == kSupportsLoadingDuringStartup) || + (f == kSupportsDeleteSave) || + (f == kSavesSupportMetaInfo) || + (f == kSavesSupportThumbnail); +} + +bool MADS::MADSEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +bool MADSMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const MADS::MADSGameDescription *gd = (const MADS::MADSGameDescription *)desc; + if (gd) { + *engine = new MADS::MADSEngine(syst, gd); + } + return gd != 0; +} + +SaveStateList MADSMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray filenames; + Common::String saveDesc; + Common::String pattern = Common::String::format("%s.0??", target); + MADS::MADSSavegameHeader header; + + filenames = saveFileMan->listSavefiles(pattern); + sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + const char *ext = strrchr(file->c_str(), '.'); + int slot = ext ? atoi(ext + 1) : -1; + + if (slot >= 0 && slot < MAX_SAVES) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + MADS::Game::readSavegameHeader(in, header); + saveList.push_back(SaveStateDescriptor(slot, header._saveName)); + + header._thumbnail->free(); + delete header._thumbnail; + delete in; + } + } + } + + return saveList; +} + +int MADSMetaEngine::getMaximumSaveSlot() const { + return MAX_SAVES; +} + +void MADSMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +SaveStateDescriptor MADSMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(filename); + + if (f) { + MADS::MADSSavegameHeader header; + MADS::Game::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header._saveName); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + desc.setPlayTime(header._totalFrames * GAME_FRAME_TIME); + + return desc; + } + + return SaveStateDescriptor(); +} + + +#if PLUGIN_ENABLED_DYNAMIC(MADS) + REGISTER_PLUGIN_DYNAMIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine); +#else + REGISTER_PLUGIN_STATIC(MADS, PLUGIN_TYPE_ENGINE, MADSMetaEngine); +#endif diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h new file mode 100644 index 0000000000..e68ae380d0 --- /dev/null +++ b/engines/mads/detection_tables.h @@ -0,0 +1,122 @@ +/* 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. + * + */ + +namespace MADS { + +static const MADSGameDescription gameDescriptions[] = { +#if 0 + { + // Rex Nebular and the Cosmic Gender Bender DOS English (compressed) + // Removed for now, until the original floppy compression is supported + { + "nebular", + 0, + { + {"mpslabs.001", 0, "4df5c557b52abb5b661cf4befe5ae301", 1315354}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, +#endif + + { + // Rex Nebular and the Cosmic Gender Bender DOS English + { + "nebular", + 0, + { + {"section1.hag", 0, "6f725eb38660de8af31ec7cdd628d615", 927222}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, + + { + // Rex Nebular and the Cosmic Gender Bender DOS English 8.49 Alternate + { + "nebular", + 0, + { + { "section1.hag", 0, "d583576923e3437937fb7f46f4b6274f", 927222 }, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_RexNebular, + 0 + }, + + { + // Return of the Phantom DOS English + { + "phantom", + 0, + { + {"section1.hag", 0, "76e2d47a7aebafe48edc9884b3d91782", 1130939}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_Phantom, + 0 + }, + + { + // Dragonsphere DOS English + { + "dragonsphere", + 0, + { + {"section1.hag", 0, "2770e441d296be5e806194693eebd95a", 2061199}, + AD_LISTEND + }, + Common::EN_ANY, + Common::kPlatformDOS, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + GType_Dragonsphere, + 0 + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace MADS diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp new file mode 100644 index 0000000000..dc8c846beb --- /dev/null +++ b/engines/mads/dialogs.cpp @@ -0,0 +1,398 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/nebular/dialogs_nebular.h" + +namespace MADS { + +Dialog::Dialog(MADSEngine *vm) + : _vm(vm), _savedSurface(nullptr), _position(Common::Point(-1, -1)), + _width(0), _height(0) { + TEXTDIALOG_CONTENT1 = 0XF8; + TEXTDIALOG_CONTENT2 = 0XF9; + TEXTDIALOG_EDGE = 0XFA; + TEXTDIALOG_BACKGROUND = 0XFB; + TEXTDIALOG_FC = 0XFC; + TEXTDIALOG_FD = 0XFD; + TEXTDIALOG_FE = 0XFE; + TEXTDIALOG_BLACK = 0; +} + +Dialog::~Dialog() { +} + +void Dialog::save() { + _savedSurface = new MSurface(_width, _height); + _vm->_screen.copyTo(_savedSurface, + Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height), + Common::Point()); + + _vm->_screen.copyRectToScreen(getBounds()); +} + +void Dialog::restore() { + if (_savedSurface) { + _savedSurface->copyTo(&_vm->_screen, _position); + delete _savedSurface; + _savedSurface = nullptr; + + _vm->_screen.copyRectToScreen(getBounds()); + + Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3], + &_vm->_palette->_mainPalette[248 * 3]); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 248, 8); + } +} + +void Dialog::draw() { + // Calculate the dialog positioning + calculateBounds(); + + // Save the screen portion the dialog will overlap + save(); + + setDialogPalette(); + + // Draw the dialog + // Fill entire content of dialog + Common::Rect bounds = getBounds(); + _vm->_screen.fillRect(bounds, TEXTDIALOG_BACKGROUND); + + // Draw the outer edge lines + _vm->_screen.hLine(_position.x + 1, _position.y + _height - 2, + _position.x + _width - 2, TEXTDIALOG_EDGE); + _vm->_screen.hLine(_position.x, _position.y + _height - 1, + _position.x + _width - 1, TEXTDIALOG_EDGE); + _vm->_screen.vLine(_position.x + _width - 2, _position.y + 2, + _position.y + _height - 2, TEXTDIALOG_EDGE); + _vm->_screen.vLine(_position.x + _width - 1, _position.y + 1, + _position.y + _height - 1, TEXTDIALOG_EDGE); + + // Draw the gravelly dialog content + drawContent(Common::Rect(_position.x + 2, _position.y + 2, + _position.x + _width - 2, _position.y + _height - 2), 0, + TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2); +} + +void Dialog::setDialogPalette() { + // Save the high end of the palette, and set up the entries for dialog display + Common::copy(&_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3], + &_vm->_palette->_mainPalette[TEXTDIALOG_CONTENT1 * 3 + 8 * 3], + &_dialogPalette[0]); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_CONTENT1, 2, 0x90, 0x80); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_EDGE, 2, 0x9C, 0x70); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FC, 2, 0x90, 0x80); + Palette::setGradient(_vm->_palette->_mainPalette, TEXTDIALOG_FE, 1, 0xDC, 0xDC); + + _vm->_palette->setPalette(_vm->_palette->_mainPalette + (TEXTDIALOG_CONTENT1 * 3), + TEXTDIALOG_CONTENT1, 8); +} + +void Dialog::calculateBounds() { +} + +void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte color2) { + uint16 currSeed = seed ? seed : 0xB78E; + + for (int yp = 0; yp < r.height(); ++yp) { + byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp); + + for (int xp = 0; xp < r.width(); ++xp) { + uint16 seedAdjust = currSeed; + currSeed += 0x181D; + seedAdjust = (seedAdjust >> 9) | ((seedAdjust & 0x1ff) << 7); + currSeed ^= seedAdjust; + seedAdjust = (seedAdjust >> 3) | ((seedAdjust & 7) << 13); + currSeed += seedAdjust; + + *destP++ = (currSeed & 0x10) ? color2 : color1; + } + } +} + +/*------------------------------------------------------------------------*/ + +TextDialog::TextDialog(MADSEngine *vm, const Common::String &fontName, + const Common::Point &pos, int maxChars) + : Dialog(vm) { + _vm = vm; + _font = _vm->_font->getFont(fontName); + _position = pos; + + _vm->_font->setColors(TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK, TEXTDIALOG_BLACK); + + _innerWidth = (_font->maxWidth() + 1) * maxChars; + _width = _innerWidth + 10; + _lineSize = maxChars * 2; + _lineWidth = 0; + _currentX = 0; + _numLines = 0; + Common::fill(&_lineXp[0], &_lineXp[TEXT_DIALOG_MAX_LINES], 0); + _askLineNum = -1; + _askXp = 0; +} + +TextDialog::~TextDialog() { +} + +void TextDialog::addLine(const Common::String &line, bool underline) { + if (_lineWidth > 0 || _currentX > 0) + incNumLines(); + + int stringWidth = _font->getWidth(line, 1); + if (stringWidth >= _innerWidth || (int)line.size() >= _lineSize) { + wordWrap(line); + } else { + _lineXp[_numLines] = (_innerWidth / 2) - (stringWidth / 2); + _lines[_numLines] = line; + + if (underline) + underlineLine(); + } + + incNumLines(); +} + +void TextDialog::underlineLine() { + _lineXp[_numLines] |= 0x80; +} + +void TextDialog::downPixelLine() { + _lineXp[_numLines] |= 0x40; +} + +void TextDialog::incNumLines() { + _lineWidth = 0; + _currentX = 0; + if (++_numLines == TEXT_DIALOG_MAX_LINES) + error("Exceeded text dialog line max"); +} + +void TextDialog::wordWrap(const Common::String &line) { + Common::String tempLine; + + if (!line.empty()) { + const char *srcP = line.c_str(); + + do { + tempLine = ""; + bool endWord = false; + bool newLine = false; + bool continueFlag = true; + + do { + if (!*srcP) { + continueFlag = false; + } else { + tempLine += *srcP; + + if (*srcP == 10) { + continueFlag = false; + newLine = true; + ++srcP; + tempLine.deleteLastChar(); + } else if (*srcP == ' ') { + ++srcP; + endWord = true; + } else if (!endWord) { + ++srcP; + } else { + tempLine.deleteLastChar(); + continueFlag = false; + } + } + } while (continueFlag); + + if (tempLine.hasSuffix(" ")) + tempLine.deleteLastChar(); + + Common::String tempLine2; + if (_currentX > 0) + tempLine2 += ' '; + tempLine2 += tempLine; + + int lineWidth = _font->getWidth(tempLine2, 1); + if (((_currentX + (int)tempLine2.size()) > _lineSize) || + ((_lineWidth + lineWidth) > _innerWidth)) { + incNumLines(); + appendLine(tempLine); + } else { + appendLine(tempLine2); + } + + if (newLine) + incNumLines(); + } while (*srcP); + } +} + +void TextDialog::appendLine(const Common::String &line) { + _currentX += line.size(); + _lineWidth += _font->getWidth(line, 1) + 1; + _lines[_numLines] += line; +} + +void TextDialog::addInput() { + _askXp = _currentX + 1; + _askLineNum = _numLines; + incNumLines(); +} + +void TextDialog::addBarLine() { + if (_lineWidth > 0 || _currentX > 0) + incNumLines(); + + _lineXp[_numLines] = 0xFF; + incNumLines(); +} + +void TextDialog::setLineXp(int xp) { + _lineXp[_numLines] = xp; +} + +void TextDialog::draw() { + if (!_lineWidth) + --_numLines; + + // Figure out the size and position for the dialog + calculateBounds(); + + // Draw the underlying dialog + Dialog::draw(); + + // Draw the text lines + int lineYp = _position.y + 5; + for (int lineNum = 0; lineNum <= _numLines; ++lineNum) { + if (_lineXp[lineNum] == -1) { + // Draw a line across the entire dialog + _vm->_screen.hLine(_position.x + 2, + lineYp + (_font->getHeight() + 1) / 2, + _position.x + _width - 4, TEXTDIALOG_BLACK); + } else { + // Draw a text line + int xp = (_lineXp[lineNum] & 0x7F) + _position.x + 5; + int yp = lineYp; + if (_lineXp[lineNum] & 0x40) + ++yp; + + _font->writeString(&_vm->_screen, _lines[lineNum], + Common::Point(xp, yp), 1); + + if (_lineXp[lineNum] & 0x80) { + // Draw an underline under the text + int lineWidth = _font->getWidth(_lines[lineNum], 1); + _vm->_screen.hLine(xp, yp + _font->getHeight(), xp + lineWidth, + TEXTDIALOG_BLACK); + } + } + + lineYp += _font->getHeight() + 1; + } + + _vm->_screen.copyRectToScreen(getBounds()); +} + +void TextDialog::calculateBounds() { + _height = (_font->getHeight() + 1) * (_numLines + 1) + 10; + if (_position.x == -1) + _position.x = 160 - (_width / 2); + if (_position.y == -1) + _position.y = 100 - (_height / 2); + + if ((_position.x + _width) > _vm->_screen.getWidth()) + _position.x = _vm->_screen.getWidth() - (_position.x + _width); + if ((_position.y + _height) > _vm->_screen.getHeight()) + _position.y = _vm->_screen.getHeight() - (_position.y + _height); +} + +void TextDialog::drawWithInput() { + //int innerWidth = _innerWidth; + //int lineHeight = _font->getHeight() + 1; + //int xp = _position.x + 5; + + // Draw the content of the dialog + drawContent(Common::Rect(_position.x + 2, _position.y + 2, + _position.x + _width - 2, _position.y + _height - 2), 0, + TEXTDIALOG_CONTENT1, TEXTDIALOG_CONTENT2); + + error("TODO: drawWithInput"); +} + +void TextDialog::show() { + // Draw the dialog + draw(); + _vm->_events->showCursor(); + + // Wait for mouse click + do { + _vm->_events->waitForNextFrame(); + } while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && !_vm->_events->_mouseReleased); + + // Allow the mouse release or keypress to be gobbled up + if (!_vm->shouldQuit()) { + _vm->_events->waitForNextFrame(); + _vm->_events->_pendingKeys.clear(); + } + + // Restore the background + restore(); +} + +/*------------------------------------------------------------------------*/ + +MessageDialog::MessageDialog(MADSEngine *vm, int maxChars, ...) + : TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), maxChars) { + // Add in passed line list + va_list va; + va_start(va, maxChars); + + const char *line = va_arg(va, const char *); + while (line) { + addLine(line); + line = va_arg(va, const char *); + } + va_end(va); +} + +/*------------------------------------------------------------------------*/ + +Dialogs *Dialogs::init(MADSEngine *vm) { + if (vm->getGameID() == GType_RexNebular) + return new Nebular::DialogsNebular(vm); + + // Throw a warning for now, since the associated Dialogs class isn't implemented yet + warning("Dialogs: Unknown game"); + // HACK: Reuse the implemented Nebular dialogs for now, to avoid crashing later on + return new Nebular::DialogsNebular(vm); +} + +Dialogs::Dialogs(MADSEngine *vm) + : _vm(vm) { + _pendingDialog = DIALOG_NONE; +} + +} // End of namespace MADS diff --git a/engines/mads/dialogs.h b/engines/mads/dialogs.h new file mode 100644 index 0000000000..aad29f6551 --- /dev/null +++ b/engines/mads/dialogs.h @@ -0,0 +1,229 @@ +/* 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 MADS_DIALOGS_H +#define MADS_DIALOGS_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +class Dialog { +private: + void setDialogPalette(); +protected: + MADSEngine *_vm; + MSurface *_savedSurface; + Common::Point _position; + int _width; + int _height; + byte _dialogPalette[8 * 3]; + + int TEXTDIALOG_CONTENT1; + int TEXTDIALOG_CONTENT2; + int TEXTDIALOG_EDGE; + int TEXTDIALOG_BACKGROUND; + int TEXTDIALOG_FC; + int TEXTDIALOG_FD; + int TEXTDIALOG_FE; + int TEXTDIALOG_BLACK; +protected: + /** + * Draw the dialog + */ + virtual void draw(); + + /** + * Calculate bounds for the dialog + */ + virtual void calculateBounds(); + + /** + * Save the section of the passed surface the dialog will cover. + */ + virtual void save(); + + /** + * Restore saved dialog surface + */ + virtual void restore(); + + /** + * Draws the content of a dialog with a gravelly alternating color. + */ + void drawContent(const Common::Rect &r, int seed, byte color1, byte color2); +public: + /** + * Constructor + */ + Dialog(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~Dialog(); + + /** + * Return the bounds of the dialog. + */ + Common::Rect getBounds() const { + return Common::Rect(_position.x, _position.y, + _position.x + _width, _position.y + _height); + } +}; + +#define TEXT_DIALOG_MAX_LINES 20 + +class TextDialog : protected Dialog { +private: + /** + * Append text to the currently end line. + */ + void appendLine(const Common::String &line); + + /** + * Clean up after finishing displaying the dialog + */ + void restorePalette(); +protected: + Font *_font; + int _innerWidth; + int _lineWidth; + int _currentX; + int _numLines; + int _lineSize; + int _askXp; + int _askLineNum; + Common::String _lines[TEXT_DIALOG_MAX_LINES]; + int _lineXp[TEXT_DIALOG_MAX_LINES]; + + /** + * Calculate the bounds for the dialog + */ + virtual void calculateBounds(); +public: + /** + * Constructor + * @param vm Engine reference + * @param fontName Font to use for display + * @param pos Position for window top-left + * @param maxChars Horizontal width of window in characters + */ + TextDialog(MADSEngine *vm, const Common::String &fontName, const Common::Point &pos, + int maxChars); + + /** + * Destructor + */ + virtual ~TextDialog(); + + /** + * Draw the dialog + */ + virtual void draw(); + + /** + * Draw the dialog along with any input box + */ + void drawWithInput(); + + /** + * Add a new line to the dialog + */ + void addLine(const Common::String &line, bool underline = false); + + /** + * Adds one or more lines, word wrapping the passed text + */ + void wordWrap(const Common::String &line); + + /** + * Increments the number of text lines the text dialog uses + */ + void incNumLines(); + + /** + * Adds an input area following previously added text + */ + void addInput(); + + /** + * Adds a bar line to separate sections of text + */ + void addBarLine(); + + /** + * Flags the previously added line to be underlined + */ + void underlineLine(); + + void downPixelLine(); + + /** + * Set the x position for the given line + */ + void setLineXp(int xp); + + /** + * Show the dialog, and wait until a key or mouse press. + */ + virtual void show(); +}; + +class MessageDialog : public TextDialog { +public: + MessageDialog(MADSEngine *vm, int lines, ...); + + virtual ~MessageDialog() {} +}; + +enum DialogId { + DIALOG_NONE = 0, DIALOG_GAME_MENU = 1, DIALOG_SAVE = 2, DIALOG_RESTORE = 3, + DIALOG_OPTIONS = 4, DIALOG_DIFFICULTY = 5, DIALOG_ERROR = 6 +}; + +class Dialogs { +protected: + MADSEngine *_vm; + + Dialogs(MADSEngine *vm); +public: + static Dialogs *init(MADSEngine *vm); +public: + Common::Point _defaultPosition; + DialogId _pendingDialog; + int _indexList[10]; + + virtual ~Dialogs() {} + + virtual void showDialog() = 0; + virtual void showItem(int objectId, int messageId, int speech = 0) = 0; + virtual Common::String getVocab(int vocabId) = 0; + virtual bool show(int messageId, int objectId = -1) = 0; +}; + +} // End of namespace MADS + +#endif /* MADS_DIALOGS_H */ diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp new file mode 100644 index 0000000000..59d7914378 --- /dev/null +++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp @@ -0,0 +1,236 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/dragonsphere/game_dragonsphere.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" + +namespace MADS { + +namespace Dragonsphere { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + // TODO + //scene.addActiveVocab(NOUN_DROP); + + switch (scene._nextSceneId) { + // Scene group #1 (Castle, river and caves) + case 101: // king's bedroom + return new DummyScene(vm); // TODO + case 102: // queen's bedroom + return new DummyScene(vm); // TODO + case 103: // outside king's bedroom + return new DummyScene(vm); // TODO + case 104: // fireplace / bookshelf + return new DummyScene(vm); // TODO + case 105: // dining room + return new DummyScene(vm); // TODO + case 106: // throne room + return new DummyScene(vm); // TODO + case 107: // council chamber + return new DummyScene(vm); // TODO + case 108: // dungeon, cell entrance + return new DummyScene(vm); // TODO + case 109: // cell + return new DummyScene(vm); // TODO + case 110: // outside castle, merchants and well + return new DummyScene(vm); // TODO + case 111: // Dragonsphere closeup + return new DummyScene(vm); // TODO + case 112: // well descend + return new DummyScene(vm); // TODO + case 113: // bottom of well, river and trap door + return new DummyScene(vm); // TODO + case 114: // cave + return new DummyScene(vm); // TODO + case 115: // cave with passageway to west + return new DummyScene(vm); // TODO + case 116: // cave with pedestral + return new DummyScene(vm); // TODO + case 117: // river + return new DummyScene(vm); // TODO + case 118: // castle courtyard and gate + return new DummyScene(vm); // TODO + case 119: // castle stairs + return new DummyScene(vm); // TODO + case 120: // map + return new DummyScene(vm); // TODO + + // Scene group #2 (Slathan ni Patan, land of shapeshifters) + case 201: // guardhouse, entrance to Slathan ni Patan + return new DummyScene(vm); // TODO + case 203: // forest + return new DummyScene(vm); // TODO + case 204: // cave + return new DummyScene(vm); // TODO + case 205: // outside village + return new DummyScene(vm); // TODO + case 206: // village + return new DummyScene(vm); // TODO + + // Scene group #3 (Brynn-Fann, Land of faeries) + case 301: // maze entrance + return new DummyScene(vm); // TODO + case 302: // maze + return new DummyScene(vm); // TODO + case 303: // toads + return new DummyScene(vm); // TODO + + // Scene group #4 (The Desert) + case 401: // desert + return new DummyScene(vm); // TODO + case 402: // desert + return new DummyScene(vm); // TODO + case 403: // desert + return new DummyScene(vm); // TODO + case 404: // desert with dunes + return new DummyScene(vm); // TODO + case 405: // oasis + return new DummyScene(vm); // TODO + case 406: // inside tent + return new DummyScene(vm); // TODO + case 407: // gem sack closeup + return new DummyScene(vm); // TODO + case 408: // spirit plane + return new DummyScene(vm); // TODO + case 409: // spirit plane top down view, disks + return new DummyScene(vm); // TODO + case 410: // snake pit and spirit tree + return new DummyScene(vm); // TODO + case 411: // nest + return new DummyScene(vm); // TODO + case 412: // desert + return new DummyScene(vm); // TODO + case 454: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #5 (The Mountain) + case 501: // base of mountain / wall + return new DummyScene(vm); // TODO + case 502: // base of mountain + return new DummyScene(vm); // TODO + case 503: // waterfall + return new DummyScene(vm); // TODO + case 504: // hermit's cave + return new DummyScene(vm); // TODO + case 505: // rock trees + return new DummyScene(vm); // TODO + case 506: // nest + return new DummyScene(vm); // TODO + case 507: // above nest + return new DummyScene(vm); // TODO + case 508: // ledge, right + return new DummyScene(vm); // TODO + case 509: // ledge, left + return new DummyScene(vm); // TODO + case 510: // nest top down view and pillars + return new DummyScene(vm); // TODO + case 511: // pillars + return new DummyScene(vm); // TODO + case 512: // nest + return new DummyScene(vm); // TODO + case 557: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #6 (The Tower) + case 601: // ??? (tile count mismatch) + return new DummyScene(vm); // TODO + case 603: // eye chamber + return new DummyScene(vm); // TODO + case 604: // room of magic + return new DummyScene(vm); // TODO + case 605: // science room + return new DummyScene(vm); // TODO + case 606: // doorway + return new DummyScene(vm); // TODO + case 607: // prison + return new DummyScene(vm); // TODO + case 609: // stone pedestral chamber + return new DummyScene(vm); // TODO + case 612: // infernal machine room + return new DummyScene(vm); // TODO + case 613: // room with lava floor + return new DummyScene(vm); // TODO + case 614: // sorcerer's room + return new DummyScene(vm); // TODO + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +DragonsphereScene::DragonsphereScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GameDragonsphere *>(vm->_game)->_globals), + _game(*static_cast<GameDragonsphere *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String DragonsphereScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +} // End of namespace Dragonsphere + +} // End of namespace MADS diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.h b/engines/mads/dragonsphere/dragonsphere_scenes.h new file mode 100644 index 0000000000..a6c778eca7 --- /dev/null +++ b/engines/mads/dragonsphere/dragonsphere_scenes.h @@ -0,0 +1,695 @@ +/* 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 MADS_DRAGONSPHERE_SCENES_H +#define MADS_DRAGONSPHERE_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/dragonsphere/game_dragonsphere.h" +//#include "mads/dragonsphere/globals_dragonsphere.h" + + +namespace MADS { + +namespace Dragonsphere { + +enum Noun { + NOUN_GAME = 0x1, + NOUN_QSAVE = 0x2, + NOUN_LOOK = 0x3, + NOUN_TAKE = 0x4, + NOUN_PUSH = 0x5, + NOUN_OPEN = 0x6, + NOUN_PUT = 0x7, + NOUN_TALK_TO = 0x8, + NOUN_GIVE = 0x9, + NOUN_PULL = 0xA, + NOUN_CLOSE = 0xB, + NOUN_THROW = 0xC, + NOUN_WALK_TO = 0xD, + NOUN_NOTHING = 0xE, + NOUN_ = 0xF, + NOUN_FLOOR = 0x10, + NOUN_WALK_ACROSS = 0x11, + NOUN_RUG = 0x12, + NOUN_CARPET = 0x13, + NOUN_WALL = 0x14, + NOUN_BED = 0x15, + NOUN_PILLOW = 0x16, + NOUN_CHEST = 0x17, + NOUN_WINDOW = 0x18, + NOUN_NIGHTSTAND = 0x19, + NOUN_TAPESTRY = 0x1A, + NOUN_DRESSING_SCREEN = 0x1B, + NOUN_WALK_BEHIND = 0x1C, + NOUN_ROYAL_CREST = 0x1D, + NOUN_LOOK_AT = 0x1E, + NOUN_WASHBASIN = 0x1F, + NOUN_WASH_AT = 0x20, + NOUN_BOOK = 0x21, + NOUN_FIREPLACE = 0x22, + NOUN_FIREPLACE_SCREEN = 0x23, + NOUN_DOOR_TO_QUEENS_ROOM = 0x24, + NOUN_WALK_THROUGH = 0x25, + NOUN_HALL_TO_SOUTH = 0x26, + NOUN_WALK_INTO = 0x27, + NOUN_WALL_PLAQUE = 0x28, + NOUN_DECORATION = 0x29, + NOUN_SWORDS = 0x2A, + NOUN_WALL_SCONCE = 0x2B, + NOUN_BUST_ON_WALL = 0x2C, + NOUN_WALL_ARCH = 0x2D, + NOUN_SIGNET_RING = 0x2E, + NOUN_INVOKE = 0x2F, + NOUN_POLISH = 0x30, + NOUN_GANGBANG = 0x31, + NOUN_BIRD_FIGURINE = 0x32, + NOUN_RUB = 0x33, + NOUN_BIRDCALL = 0x34, + NOUN_USE = 0x35, + NOUN_MAKE_NOISE = 0x36, + NOUN_SHIELDSTONE = 0x37, + NOUN_SWORD = 0x38, + NOUN_ATTACK = 0x39, + NOUN_CARVE_UP = 0x3A, + NOUN_GOBLET = 0x3B, + NOUN_FILL = 0x3C, + NOUN_DRINK_FROM = 0x3D, + NOUN_BONE = 0x3E, + NOUN_GNAW = 0x3F, + NOUN_FRUIT = 0x40, + NOUN_EAT = 0x41, + NOUN_DOLL = 0x42, + NOUN_PLAY_WITH = 0x43, + NOUN_HEAL = 0x44, + NOUN_HEAL_THYSELF = 0x45, + NOUN_HEAL_SELF = 0x46, + NOUN_POLYSTONE = 0x47, + NOUN_MIMIC = 0x48, + NOUN_RED_POWERSTONE = 0x49, + NOUN_YELLOW_POWERSTONE = 0x4A, + NOUN_BLUE_POWERSTONE = 0x4B, + NOUN_KEY_CROWN = 0x4C, + NOUN_WEAR = 0x4D, + NOUN_DATES = 0x4E, + NOUN_STATUE = 0x4F, + NOUN_BOTTLE_OF_FLIES = 0x50, + NOUN_LISTEN_TO = 0x51, + NOUN_SOUL_EGG = 0x52, + NOUN_BREAK = 0x53, + NOUN_MAGIC_BELT = 0x54, + NOUN_ADJUST = 0x55, + NOUN_AMULET = 0x56, + NOUN_THRUST = 0x57, + NOUN_MUD = 0x58, + NOUN_FEEL = 0x59, + NOUN_TASTE = 0x5A, + NOUN_FEATHERS = 0x5B, + NOUN_TICKLE = 0x5C, + NOUN_TORCH = 0x5D, + NOUN_WAVE = 0x5E, + NOUN_FLASK = 0x5F, + NOUN_FLASK_FULL_OF_ACID = 0x60, + NOUN_POUR_CONTENTS = 0x61, + NOUN_POUR = 0x62, + NOUN_POUR_CONTENTS_OF = 0x63, + NOUN_DRINK = 0x64, + NOUN_ROPE = 0x65, + NOUN_TIE = 0x66, + NOUN_POWER_VACUUM_STONE = 0x67, + NOUN_TAKE_MAGIC_FROM = 0x68, + NOUN_DEAD_RAT = 0x69, + NOUN_PET = 0x6A, + NOUN_MAP = 0x6B, + NOUN_FOLD = 0x6C, + NOUN_CRYSTAL_BALL = 0x6D, + NOUN_GAZE_INTO = 0x6E, + NOUN_INVOKE_POWER_OF = 0x6F, + NOUN_BLACK_SPHERE = 0x70, + NOUN_SOPTUS_SOPORIFIC = 0x71, + NOUN_SHIFTER_RING = 0x72, + NOUN_SHIFT_SELF = 0x73, + NOUN_SHIFT_INTO_BEAR = 0x74, + NOUN_SHIFT_INTO_SEAL = 0x75, + NOUN_SHIFT_INTO_SNAKE = 0x76, + NOUN_REVERT = 0x77, + NOUN_MEDICINE_BUNDLE = 0x78, + NOUN_SHAKE = 0x79, + NOUN_PARTLY_BUILT_BUNDLE = 0x7A, + NOUN_RATSICLE = 0x7B, + NOUN_LICK = 0x7C, + NOUN_TENTACLE_PARTS = 0x7D, + NOUN_CHEW = 0x7E, + NOUN_TELEPORT_DOOR = 0x7F, + NOUN_UNROLL = 0x80, + NOUN_RARE_COIN = 0x81, + NOUN_ADMIRE = 0x82, + NOUN_CRYSTAL_FLOWER = 0x83, + NOUN_DIAMOND_DUST = 0x84, + NOUN_RUBY_RING = 0x85, + NOUN_GOLD_NUGGET = 0x86, + NOUN_MAGIC_MUSIC_BOX = 0x87, + NOUN_EMERALD = 0x88, + NOUN_PIECE_OF_PAPER = 0x89, + NOUN_SPEAK_WORDS_ON = 0x8A, + NOUN_VORTEX_STONE = 0x8B, + NOUN_RUG2 = 0x8C, + NOUN_FIREPLACE_SCREEN2 = 0x8D, + NOUN_BUST_ON_WALL2 = 0x8E, + NOUN_LOOK_AT2 = 0x8F, + NOUN_DRAGON = 0x90, + NOUN_DRAGONSPHERE = 0x91, + NOUN_TOUCH = 0x92, + NOUN_THRONE_ROOM = 0x93, + NOUN_RETURN_TO = 0x94, + NOUN_CAVE = 0x95, + NOUN_PASSAGEWAY_TO_WEST = 0x96, + NOUN_PASSAGEWAY_TO_EAST = 0x97, + NOUN_CAVE_FLOOR = 0x98, + NOUN_STONE_COLUMN = 0x99, + NOUN_ABYSS = 0x9A, + NOUN_LOOK_INTO = 0x9B, + NOUN_CASTLE = 0x9C, + NOUN_CASTLE_GATE = 0x9D, + NOUN_GROUND = 0x9E, + NOUN_BARREL = 0x9F, + NOUN_BARRELS = 0xA0, + NOUN_HAYSTACK = 0xA1, + NOUN_ROOT_THROUGH = 0xA2, + NOUN_BATTLEMENTS = 0xA3, + NOUN_GATE_TO_THRONE_ROOM = 0xA4, + NOUN_CASTLE_WALL = 0xA5, + NOUN_DOOR = 0xA6, + NOUN_WALL_SWITCH = 0xA7, + NOUN_STAIRS = 0xA8, + NOUN_WALK_DOWN = 0xA9, + NOUN_EDGE_OF_ABYSS = 0xAA, + NOUN_COURTYARD = 0xAB, + NOUN_ROCK = 0xAC, + NOUN_CAVE_CEILING = 0xAD, + NOUN_CAVE_WALL = 0xAE, + NOUN_BRAZIER = 0xAF, + NOUN_DOOR_TO_THRONE_ROOM = 0xB0, + NOUN_GO_THROUGH = 0xB1, + NOUN_DINING_TABLE = 0xB2, + NOUN_ACTIVATE = 0xB3, + NOUN_BATTLEMENT = 0xB4, + NOUN_DOOR_TO_GAURDROOM = 0xB5, + NOUN_DUNGEON_FLOOR = 0xB6, + NOUN_DUNGEON_WALLS = 0xB7, + NOUN_DUNGEON_CEILING = 0xB8, + NOUN_BEDDING = 0xB9, + NOUN_FLOOR_GRATE = 0xBA, + NOUN_MANACLES = 0xBB, + NOUN_CALENDAR = 0xBC, + NOUN_DOOR_TO_GUARDROOM = 0xBD, + NOUN_DOOR_TO_COUNCIL_ROOM = 0xBE, + NOUN_GUARD_STATION = 0xBF, + NOUN_DOOR_TO_DUNGEON_CELL = 0xC0, + NOUN_DOORWAY_TO_CELL = 0xC1, + NOUN_DUNGEON_DOOR = 0xC2, + NOUN_DUNGEON_WALL = 0xC3, + NOUN_CEILING = 0xC4, + NOUN_DOOR_TO_HALLWAY = 0xC5, + NOUN_TABLE = 0xC6, + NOUN_BOOKSHELF = 0xC7, + NOUN_TROPHY = 0xC8, + NOUN_READING_BENCH = 0xC9, + NOUN_CHAIR = 0xCA, + NOUN_LOVESEAT = 0xCB, + NOUN_WOOD_BASKET = 0xCC, + NOUN_STOOL = 0xCD, + NOUN_GUARD_STOOL = 0xCE, + NOUN_ROCKS = 0xCF, + NOUN_DIVIDING_WALL = 0xD0, + NOUN_ARCHWAY = 0xD1, + NOUN_MARKET_GROUNDS = 0xD2, + NOUN_HEDGE = 0xD3, + NOUN_SKY = 0xD4, + NOUN_PLAINS = 0xD5, + NOUN_FIELDS = 0xD6, + NOUN_GATE_TO_COURTYARD = 0xD7, + NOUN_ROAD_TO_EAST = 0xD8, + NOUN_TREES = 0xD9, + NOUN_CLOUDS = 0xDA, + NOUN_MERCHANTS_STALL = 0xDB, + NOUN_WELL = 0xDC, + NOUN_DOWN_WELL = 0xDD, + NOUN_GO = 0xDE, + NOUN_GO_DOWN = 0xDF, + NOUN_CRANK = 0xE0, + NOUN_BUCKET = 0xE1, + NOUN_JUMP_DOWN = 0xE2, + NOUN_WALLS = 0xE3, + NOUN_DOORWAY_TO_SOUTH = 0xE4, + NOUN_PEDESTAL = 0xE5, + NOUN_DOOR_TO_NORTH = 0xE6, + NOUN_PAINTING = 0xE7, + NOUN_DOCUMENT = 0xE8, + NOUN_INK_BOTTLE = 0xE9, + NOUN_QUILL_PEN = 0xEA, + NOUN_CHANDELIER = 0xEB, + NOUN_COUNCIL_TABLE = 0xEC, + NOUN_CANDLESTICK = 0xED, + NOUN_DESK = 0xEE, + NOUN_TURN = 0xEF, + NOUN_POLE = 0xF0, + NOUN_THE_SCENE = 0xF1, + NOUN_LEAVE = 0xF2, + NOUN_END_TABLE = 0xF3, + NOUN_BATTLE_AXES = 0xF4, + NOUN_DOOR_TO_KINGS_ROOM = 0xF5, + NOUN_COAT_OF_ARMS = 0xF6, + NOUN_LARGE_WINDOW = 0xF7, + NOUN_SMALL_WINDOW = 0xF8, + NOUN_DOOR_TO_MEETING_ROOM = 0xF9, + NOUN_DOOR_TO_BALLROOM = 0xFA, + NOUN_FLOWERS = 0xFB, + NOUN_SHUTTERS = 0xFC, + NOUN_BOOKCASE = 0xFD, + NOUN_DOOR_TO_COURTYARD = 0xFE, + NOUN_PLATFORM = 0xFF, + NOUN_STEP = 0x100, + NOUN_RED_CARPET = 0x101, + NOUN_KINGS_THRONE = 0x102, + NOUN_SIT_IN = 0x103, + NOUN_QUEENS_THRONE = 0x104, + NOUN_TRAPDOOR = 0x105, + NOUN_GRATE = 0x106, + NOUN_RIVER = 0x107, + NOUN_DIARIES = 0x108, + NOUN_SWIM_DOWN = 0x109, + NOUN_SCULLERY_MAID = 0x10A, + NOUN_DOORWAY_TO_DUNGEON = 0x10B, + NOUN_WARD = 0x10C, + NOUN_DARKNESS_BEAST = 0x10D, + NOUN_BEAST = 0x10E, + NOUN_PUT_MAGIC_INTO = 0x10F, + NOUN_GUARD = 0x110, + NOUN_CROWN = 0x111, + NOUN_BOOKS = 0x112, + NOUN_SECRET_DOOR = 0x113, + NOUN_WALL_PANEL = 0x114, + NOUN_DOORWAY = 0x115, + NOUN_FAERIE = 0x116, + NOUN_SOPTUS_ECLIPTUS = 0x117, + NOUN_GUARD_CAPTAIN = 0x118, + NOUN_MERCHANT = 0x119, + NOUN_SHAPECHANGER = 0x11A, + NOUN_RED_STONE = 0x11B, + NOUN_YELLOW_STONE = 0x11C, + NOUN_BLUE_STONE = 0x11D, + NOUN_FLIES = 0x11E, + NOUN_FLASK_OF_ACID = 0x11F, + NOUN_PARTIAL_BUNDLE = 0x120, + NOUN_SOPORIFIC = 0x121, + NOUN_PARCHMENT = 0x122, + NOUN_KING = 0x123, + NOUN_MACMORN = 0x124, + NOUN_MOUNTAINSIDE = 0x125, + NOUN_PATH_TO_SOUTH = 0x126, + NOUN_ROUGH_STONE = 0x127, + NOUN_CLIMB_UP = 0x128, + NOUN_LARGE_ROCK = 0x129, + NOUN_SMALL_ROCK = 0x12A, + NOUN_PATH_TO_WEST = 0x12B, + NOUN_CAVE_ENTRANCE = 0x12C, + NOUN_PALLET = 0x12D, + NOUN_BLANKET = 0x12E, + NOUN_FIREPIT = 0x12F, + NOUN_FLAT_STONE = 0x130, + NOUN_MOVE = 0x131, + NOUN_SPIRIT_BUNDLE = 0x132, + NOUN_TRAIL_LEADING_UP = 0x133, + NOUN_FOLLOW = 0x134, + NOUN_TRAIL_LEADING_DOWN = 0x135, + NOUN_NEST = 0x136, + NOUN_REACH_IN = 0x137, + NOUN_TRAIL_LEADING_WEST = 0x138, + NOUN_PATH_TO_EAST = 0x139, + NOUN_WATERFALL = 0x13A, + NOUN_PUDDLE = 0x13B, + NOUN_EDGE_OF_CLIFF = 0x13C, + NOUN_LEDGE = 0x13D, + NOUN_CLIMB_DOWN = 0x13E, + NOUN_LANDING = 0x13F, + NOUN_BOULDERS = 0x140, + NOUN_ROCK_TUMBLE = 0x141, + NOUN_ROCK_TREE = 0x142, + NOUN_PILLAR = 0x143, + NOUN_JUMP_TO = 0x144, + NOUN_CLIFF = 0x145, + NOUN_PILLARS = 0x146, + NOUN_SPECIAL_ROCK = 0x147, + NOUN_GAZE_UPON = 0x148, + NOUN_SCONCE = 0x149, + NOUN_LADDER = 0x14A, + NOUN_STAIRWAY = 0x14B, + NOUN_MECHANISM = 0x14C, + NOUN_SPEARHEADS = 0x14D, + NOUN_TRAP_DOOR = 0x14E, + NOUN_SWIM = 0x14F, + NOUN_DOWN_RIVER = 0x150, + NOUN_SWIM_UP = 0x151, + NOUN_UP_RIVER = 0x152, + NOUN_SHORE = 0x153, + NOUN_SWIM_TO = 0x154, + NOUN_SWIM_TOWARDS = 0x155, + NOUN_KING_CALLASH = 0x156, + NOUN_KINGS_THRONE2 = 0x157, + NOUN_KING2 = 0x158, + NOUN_GROTTO = 0x159, + NOUN_CLIMB_THROUGH = 0x15A, + NOUN_QUEEN_MOTHER = 0x15B, + NOUN_MACMORN2 = 0x15C, + NOUN_SMALL_LEDGE = 0x15D, + NOUN_MACMORN3 = 0x15E, + NOUN_TO_110 = 0x15F, + NOUN_TO_KITTY_HEAVEN = 0x160, + NOUN_KITTY_HEAVEN = 0x161, + NOUN_ROOM_110 = 0x162, + NOUN_LLANIE = 0x163, + NOUN_CW = 0x164, + NOUN_HERMIT = 0x165, + NOUN_TROU = 0x166, + NOUN_SHAK = 0x167, + NOUN_ROOM_501 = 0x168, + NOUN_MOON = 0x169, + NOUN_UFO = 0x16A, + NOUN_SIT_ON = 0x16B, + NOUN_STRANGER = 0x16C, + NOUN_TOWER_DOOR = 0x16D, + NOUN_DOOR_TO_EAST = 0x16E, + NOUN_DOOR_TO_WEST = 0x16F, + NOUN_EYE = 0x170, + NOUN_DOORWAY_TO_EAST = 0x171, + NOUN_DOORWAY_TO_WEST = 0x172, + NOUN_SKULL = 0x173, + NOUN_DOOR_TO_MAGIC_ROOM = 0x174, + NOUN_ANCIENT_BARREL = 0x175, + NOUN_COBWEBS = 0x176, + NOUN_SHELF = 0x177, + NOUN_MUSTY_CHART = 0x178, + NOUN_LAB_TABLE = 0x179, + NOUN_PETCOCK = 0x17A, + NOUN_NOZZLE = 0x17B, + NOUN_TUBING = 0x17C, + NOUN_BEAKER = 0x17D, + NOUN_FLAME = 0x17E, + NOUN_METAL_PLATE = 0x17F, + NOUN_SHAFT_OF_LIGHT = 0x180, + NOUN_CABINET = 0x181, + NOUN_BALANCE = 0x182, + NOUN_CAGE = 0x183, + NOUN_FREEZER = 0x184, + NOUN_CONTENTS_OF_FREEZER = 0x185, + NOUN_CAGE_WITH_RATS = 0x186, + NOUN_DOOR_TO_SOUTH = 0x187, + NOUN_TRAIL_OF_GREEN_SLIME = 0x188, + NOUN_NECK_LOCK = 0x189, + NOUN_BENCH = 0x18A, + NOUN_SKELETON = 0x18B, + NOUN_LEG_CLAMPS = 0x18C, + NOUN_LEG_LOCK = 0x18D, + NOUN_WAIST_LOCK = 0x18E, + NOUN_NER_TOM = 0x18F, + NOUN_BELT = 0x190, + NOUN_JUMP_INTO = 0x191, + NOUN_CLOSET = 0x192, + NOUN_DOOR_TO_EYE_CHAMBER = 0x193, + NOUN_DRESSER = 0x194, + NOUN_SCROLL = 0x195, + NOUN_WITCH_PARAPHERNALIA = 0x196, + NOUN_SHELVES = 0x197, + NOUN_MAGIC_TOMES = 0x198, + NOUN_MAGIC_PARAPHERNALIA = 0x199, + NOUN_BOOK_OF_MAGIC = 0x19A, + NOUN_HOURGLASS = 0x19B, + NOUN_STONE_SPHERE = 0x19C, + NOUN_SHADOW_OF_WINDOW = 0x19D, + NOUN_MUSIC_BOX = 0x19E, + NOUN_LARGE_SPIDER_WEB = 0x19F, + NOUN_INFERNAL_MACHINE = 0x1A0, + NOUN_WATER_SOURCE = 0x1A1, + NOUN_FLOW_OF_WATER = 0x1A2, + NOUN_RETORT = 0x1A3, + NOUN_DOORWAY_TO_CORRIDOR = 0x1A4, + NOUN_TELESCOPE = 0x1A5, + NOUN_STRANGE_MAP = 0x1A6, + NOUN_CIRCLE_OF_SPHERES = 0x1A7, + NOUN_STONE_BED = 0x1A8, + NOUN_DRAGON_SCULPTURE = 0x1A9, + NOUN_RAT = 0x1AA, + NOUN_RAT_CAGE = 0x1AB, + NOUN_DOWN_BUTTON = 0x1AC, + NOUN_DOOR_TO_MACHINE_ROOM = 0x1AD, + NOUN_STRANGE_PORTAL = 0x1AE, + NOUN_DOOR_FRAME = 0x1AF, + NOUN_ELEVATOR_HOLE = 0x1B0, + NOUN_UP_BUTTON = 0x1B1, + NOUN_DOORWAY_TO_DARK_ROOM = 0x1B2, + NOUN_BIG_SKULL = 0x1B3, + NOUN_ELEVATOR_PLATFORM = 0x1B4, + NOUN_BUTTON = 0x1B5, + NOUN_TOP_BUTTON = 0x1B6, + NOUN_BOTTOM_BUTTON = 0x1B7, + NOUN_TELEPORTAL = 0x1B8, + NOUN_EYE_CHAMBER_DOORWAY = 0x1B9, + NOUN_MACHINE_ROOM_DOORWAY = 0x1BA, + NOUN_GLOWING_FLOOR = 0x1BB, + NOUN_BRYNN_FANN = 0x1BC, + NOUN_GRAN_CALLAHACH = 0x1BD, + NOUN_SLATHAN_NI_PATAN = 0x1BE, + NOUN_HIGHTOWER = 0x1BF, + NOUN_SOPTUS_ECLIPTUS2 = 0x1C0, + NOUN_TOWER = 0x1C1, + NOUN_MOUNTAIN_PATH = 0x1C2, + NOUN_PATH_BEHIND_TOWER = 0x1C3, + NOUN_VINES = 0x1C4, + NOUN_SLATHAN_NI_PATAN2 = 0x1C5, + NOUN_SICK = 0x1C6, + NOUN_PATH_AROUND_TOWER = 0x1C7, + NOUN_PATH_TO_HIGHTOWER = 0x1C8, + NOUN_SPIRIT_PLANE = 0x1C9, + NOUN_SPIRIT_TREE = 0x1CA, + NOUN_WALK = 0x1CB, + NOUN_REMAINS = 0x1CC, + NOUN_DOORWAY_TO_ELEVATOR = 0x1CD, + NOUN_DRAGON_DOOR = 0x1CE, + NOUN_DRAGON_BONES = 0x1CF, + NOUN_IRON_FLOOR = 0x1D0, + NOUN_HOLE = 0x1D1, + NOUN_STONE = 0x1D2, + NOUN_HOMEMADE_BUNDLE = 0x1D3, + NOUN_LEFT = 0x1D4, + NOUN_RIGHT = 0x1D5, + NOUN_UP = 0x1D6, + NOUN_DOWN = 0x1D7, + NOUN_WEST = 0x1D8, + NOUN_DESERT_TO_WEST = 0x1D9, + NOUN_CROSS = 0x1DA, + NOUN_DESERT_TO_EAST = 0x1DB, + NOUN_DESERT_TO_SOUTH = 0x1DC, + NOUN_DESERT_TO_NORTH = 0x1DD, + NOUN_DESERT = 0x1DE, + NOUN_POWERSTONE = 0x1DF, + NOUN_BONES = 0x1E0, + NOUN_TENT = 0x1E1, + NOUN_BUSH = 0x1E2, + NOUN_SANWE = 0x1E3, + NOUN_TANGLE = 0x1E4, + NOUN_SAND = 0x1E5, + NOUN_MAGIC_GRAPES = 0x1E6, + NOUN_ROCS_NEST = 0x1E7, + NOUN_GRAPE_VINE = 0x1E8, + NOUN_STRANGE_SQUARE = 0x1E9, + NOUN_WATER_SPHERE = 0x1EA, + NOUN_EAST_END_OF_ISLAND = 0x1EB, + NOUN_ISLAND = 0x1EC, + NOUN_SECRET_MESSAGE = 0x1ED, + NOUN_FIND = 0x1EE, + NOUN_SAND_NEAR_STONES = 0x1EF, + NOUN_DESERT_SKY = 0x1F0, + NOUN_POOL = 0x1F1, + NOUN_PALM_TREE = 0x1F2, + NOUN_OASIS = 0x1F3, + NOUN_LEAN_TO = 0x1F4, + NOUN_TRADER = 0x1F5, + NOUN_SIGN = 0x1F6, + NOUN_WATER_FLOW = 0x1F7, + NOUN_FLOATING_DISK = 0x1F8, + NOUN_GNARLED_ROOT = 0x1F9, + NOUN_SNAKE_PIT = 0x1FA, + NOUN_MARKER = 0x1FB, + NOUN_SHAMAN = 0x1FC, + NOUN_GUARDHOUSE = 0x1FD, + NOUN_BONE_TREE = 0x1FE, + NOUN_EAR_ROCK = 0x1FF, + NOUN_MOUTH_ROCK = 0x200, + NOUN_NOSE_ROCK = 0x201, + NOUN_NEW_BUNDLE = 0x202, + NOUN_LIZARD = 0x203, + NOUN_ROC = 0x204, + NOUN_ROCS_NEST2 = 0x205, + NOUN_SELECT = 0x206, + NOUN_PURPLE_GEM = 0x207, + NOUN_PURPLE_STONE = 0x208, + NOUN_GREEN_STONE = 0x209, + NOUN_PATH = 0x20A, + NOUN_GUARDS = 0x20B, + NOUN_LAMP = 0x20C, + NOUN_SCIMITAR = 0x20D, + NOUN_SITTING_PILLOW = 0x20E, + NOUN_WATER_GOURD = 0x20F, + NOUN_JAR = 0x210, + NOUN_TENT_POLE = 0x211, + NOUN_EXIT = 0x212, + NOUN_PARAPHERNALIA = 0x213, + NOUN_SLATHAN_NI_PATAN3 = 0x214, + NOUN_EYE_ROCK = 0x215, + NOUN_BODY_TREE = 0x216, + NOUN_CLEARING = 0x217, + NOUN_TENTACLES = 0x218, + NOUN_SPELL_SHIELD = 0x219, + NOUN_POOL_MONSTER = 0x21A, + NOUN_SHIFTER_BOULDER = 0x21B, + NOUN_DEAD_TREE = 0x21C, + NOUN_PIT = 0x21D, + NOUN_SHIFTER_VILLAGE = 0x21E, + NOUN_SLATHAN_SKY = 0x21F, + NOUN_SHIFTER = 0x220, + NOUN_WALK_AROUND = 0x221, + NOUN_WRECKED_BRIDGE = 0x222, + NOUN_SHACK = 0x223, + NOUN_WRECKED_SHACK = 0x224, + NOUN_WISE_SHIFTER = 0x225, + NOUN_GRASS = 0x226, + NOUN_ENTRANCE_TO_MAZE = 0x227, + NOUN_TOPIARY_TOAD = 0x228, + NOUN_BOULDER = 0x229, + NOUN_MUSHROOM = 0x22A, + NOUN_SLATHAN_SKY2 = 0x22B, + NOUN_GRETA = 0x22C, + NOUN_TREE_STUMP = 0x22D, + NOUN_SANCTUARY_WOODS = 0x22E, + NOUN_TOADS = 0x22F, + NOUN_DOOFUS = 0x230, + NOUN_SHIFTING_MONSTER = 0x231, + NOUN_SPRITE = 0x232, + NOUN_MAZE = 0x233, + NOUN_TOPIARY_TOADSTOOL = 0x234, + NOUN_TOPIARY_GARGOYLE = 0x235, + NOUN_TOPIARY_DRAGON = 0x236, + NOUN_GUARDIAN = 0x237, + NOUN_BUTTERFLY_KING = 0x238, + NOUN_ROBE = 0x239, + NOUN_CEDAR_CHEST = 0x23A, + NOUN_DRAGONSPHERE2 = 0x23B, + NOUN_PATH_TO_HIGHTOWER2 = 0x23C, + NOUN_CALIPH = 0x23D +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Dragonsphere game scenes + */ +class DragonsphereScene : public SceneLogic { +protected: + DragonsphereGlobals &_globals; + GameDragonsphere &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering varous rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + DragonsphereScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoDragonsphere : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoDragonsphere(MADSEngine *vm) : SceneInfo(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class Scene1xx : public DragonsphereScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound() {} + + /** + *Sets the AA file to use for the scene + */ + void setAAName() {} + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix() {} +public: + Scene1xx(MADSEngine *vm) : DragonsphereScene(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class DummyScene : public DragonsphereScene { +public: + DummyScene(MADSEngine *vm) : DragonsphereScene(vm) { + warning("Unimplemented scene"); + } + + virtual void setup() {} + virtual void enter() {} + virtual void actions() {} +}; + +} // End of namespace Dragonsphere + +} // End of namespace MADS + +#endif /* MADS_DRAGONSPHERE_SCENES_H */ diff --git a/engines/mads/dragonsphere/game_dragonsphere.cpp b/engines/mads/dragonsphere/game_dragonsphere.cpp new file mode 100644 index 0000000000..c6097125b1 --- /dev/null +++ b/engines/mads/dragonsphere/game_dragonsphere.cpp @@ -0,0 +1,173 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/dragonsphere/game_dragonsphere.h" +//#include "mads/nebular/dialogs_nebular.h" +//#include "mads/nebular/globals_nebular.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" + +namespace MADS { + +namespace Dragonsphere { + +GameDragonsphere::GameDragonsphere(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; +} + +ProtectionResult GameDragonsphere::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[5] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GameDragonsphere::initializeGlobals() { + //int count, count2; + //int bad; + + _globals.reset(); + //_globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + // TODO + + /* Section #2 variables */ + // TODO + + /* Section #3 variables */ + // TODO + + /* Section #4 variables */ + // TODO + + /* Section #5 variables */ + // TODO + + /* Section #6 variables */ + // TODO + + /* Section #9 variables */ + // TODO + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + //Player::preloadSequences("RXM", 1); + //Player::preloadSequences("ROX", 1); +} + +void GameDragonsphere::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + case 6: + _sectionHandler = new Section6Handler(_vm); + break; + case 7: + _sectionHandler = new Section7Handler(_vm); + break; + case 8: + _sectionHandler = new Section8Handler(_vm); + break; + default: + break; + } +} + +void GameDragonsphere::checkShowDialog() { + // TODO: Copied from Nebular + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GameDragonsphere::doObjectAction() { + // TODO: Copied from Nebular + //Scene &scene = _scene; + MADSAction &action = _scene._action; + //Dialogs &dialogs = *_vm->_dialogs; + //int id; + + action._inProgress = false; +} + +void GameDragonsphere::unhandledAction() { + // TODO +} + +void GameDragonsphere::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + + // TODO + } + +} + +void GameDragonsphere::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + // TODO: Copied from Nebular + if (!phase1) { + _globals.synchronize(s); + } +} + +} // End of namespace Dragonsphere + +} // End of namespace MADS diff --git a/engines/mads/dragonsphere/game_dragonsphere.h b/engines/mads/dragonsphere/game_dragonsphere.h new file mode 100644 index 0000000000..5147f75178 --- /dev/null +++ b/engines/mads/dragonsphere/game_dragonsphere.h @@ -0,0 +1,151 @@ +/* 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 MADS_GAME_DRAGONSPHERE_H +#define MADS_GAME_DRAGONSPHERE_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +//#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Dragonsphere { + +// TODO: Adapt for Dragonsphere's difficulty setting +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_SIGNET_RING = 0, + OBJ_BIRD_FIGURINE = 1, + OBJ_BIRDCALL = 2, + OBJ_SHIELDSTONE = 3, + OBJ_SWORD = 4, + OBJ_GOBLET = 5, + OBJ_BONE = 6, + OBJ_FRUIT = 7, + OBJ_DOLL = 8, + OBJ_POLYSTONE = 9, + OBJ_RED_STONE = 10, + OBJ_YELLOW_STONE = 11, + OBJ_BLUE_STONE = 12, + OBJ_KEY_CROWN = 13, + OBJ_DATES = 14, + OBJ_STATUE = 15, + OBJ_FLIES = 16, + OBJ_SOUL_EGG = 17, + OBJ_MAGIC_BELT = 18, + OBJ_AMULET = 19, + OBJ_MUD = 20, + OBJ_FEATHERS = 21, + OBJ_TORCH = 22, + OBJ_FLASK = 23, + OBJ_FLASK_OF_ACID = 24, + OBJ_ROPE = 25, + OBJ_VORTEX_STONE = 26, + OBJ_DEAD_RAT = 27, + OBJ_MAP = 28, + OBJ_CRYSTAL_BALL = 29, + OBJ_BLACK_SPHERE = 30, + OBJ_SOPORIFIC = 31, + OBJ_SHIFTER_RING = 32, + OBJ_SPIRIT_BUNDLE = 33, + OBJ_PARTIAL_BUNDLE = 34, + OBJ_RATSICLE = 35, + OBJ_TENTACLE_PARTS = 36, + OBJ_TELEPORT_DOOR = 37, + OBJ_RARE_COIN = 38, + OBJ_CRYSTAL_FLOWER = 39, + OBJ_DIAMOND_DUST = 40, + OBJ_RUBY_RING = 41, + OBJ_GOLD_NUGGET = 42, + OBJ_MUSIC_BOX = 43, + OBJ_EMERALD = 44, + OBJ_PARCHMENT = 45, + OBJ_GAME = 46, + OBJ_GAME2 = 47, + OBJ_NEW_BUNDLE = 48 +}; + +// HACK: A stub for now, remove from here once it's implemented properly +class DragonsphereGlobals : public Globals { +public: + DragonsphereGlobals() { + resize(210); // Rex has 210 globals + } + virtual ~DragonsphereGlobals() {} +}; + +class GameDragonsphere : public Game { + friend class Game; +protected: + GameDragonsphere(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + DragonsphereGlobals _globals; + StoryMode _storyMode; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; +typedef Section1Handler Section6Handler; +typedef Section1Handler Section7Handler; +typedef Section1Handler Section8Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_DRAGONSPHERE_H */ diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp new file mode 100644 index 0000000000..c3e6d5c122 --- /dev/null +++ b/engines/mads/events.cpp @@ -0,0 +1,256 @@ +/* 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 "common/scummsys.h" +#include "graphics/cursorman.h" +#include "common/events.h" +#include "engines/util.h" +#include "mads/mads.h" +#include "mads/events.h" +#include "mads/scene.h" + +namespace MADS { + +EventsManager::EventsManager(MADSEngine *vm) { + _vm = vm; + _cursorSprites = nullptr; + _cursorId = CURSOR_NONE; + _newCursorId = CURSOR_NONE; + _frameCounter = 10; + _priorFrameTime = 0; + _mouseClicked = false; + _mouseReleased = false; + _mouseButtons = 0; + _mouseStatus = 0; + _vD2 = 0; + _mouseStatusCopy = 0; + _mouseMoved = false; + _vD8 = 0; + _rightMousePressed = false; +} + +EventsManager::~EventsManager() { + freeCursors(); +} + +void EventsManager::loadCursors(const Common::String &spritesName) { + delete _cursorSprites; + _cursorSprites = new SpriteAsset(_vm, spritesName, 0x4000); +} + +void EventsManager::setCursor(CursorType cursorId) { + _cursorId = cursorId; + changeCursor(); +} + +void EventsManager::setCursor2(CursorType cursorId) { + _cursorId = cursorId; + _newCursorId = cursorId; + changeCursor(); +} + +void EventsManager::showCursor() { + CursorMan.showMouse(true); +} + +void EventsManager::hideCursor() { + CursorMan.showMouse(false); +} + +bool EventsManager::isCursorVisible() { + return CursorMan.isVisible(); +} + +void EventsManager::waitCursor() { + CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT); + _newCursorId = cursorId; + if (_cursorId != _newCursorId) { + changeCursor(); + _cursorId = _newCursorId; + } +} + +void EventsManager::changeCursor() { + if (_cursorSprites) { + MSprite *cursor = _cursorSprites->getFrame(_cursorId - 1); + assert(cursor->w == cursor->h); + byte transIndex = cursor->getTransparencyIndex(); + + // Check for hotspot indication pixels along the right-hand and bottom + // row. Put together, these give the cursor's hotspot x,y + int hotspotX = 0, hotspotY = 0; + byte *cursorData = cursor->getData(); + for (int idx = 0; idx < cursor->w; ++idx) { + if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex) + hotspotX = idx; + + if (cursorData[(idx + 1) * cursor->w - 1] != transIndex) + hotspotY = idx; + } + + // Reduce the cursor data to remove the last column from each row, since + // the cursor routines don't have a pitch option + byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)]; + byte *srcP = cursorData; + byte *destP = destCursor; + + for (int idx = 0; idx < (cursor->h - 1); ++idx) { + Common::copy(srcP, srcP + cursor->w - 1, destP); + srcP += cursor->w; + destP += cursor->w - 1; + } + + // Set the raw cursor data to use + CursorMan.replaceCursor(destCursor, cursor->w - 1, cursor->h - 1, + hotspotX, hotspotY, transIndex); + showCursor(); + delete[] destCursor; + } +} + +void EventsManager::freeCursors() { + delete _cursorSprites; + _cursorSprites = nullptr; +} + +void EventsManager::pollEvents() { + checkForNextFrameCounter(); + _mouseMoved = false; + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + // Handle keypress + switch (event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + return; + + case Common::EVENT_KEYDOWN: + // Check for debugger + if (event.kbd.keycode == Common::KEYCODE_d && (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } else { + _pendingKeys.push(event); + } + return; + case Common::EVENT_KEYUP: + return; + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + _mouseClicked = true; + _mouseButtons = 1; + _mouseMoved = true; + if (event.type == Common::EVENT_RBUTTONDOWN) { + _rightMousePressed = true; + _mouseStatus |= 2; + } else { + _mouseStatus |= 1; + } + return; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _mouseClicked = false; + _mouseReleased = true; + _mouseMoved = true; + _rightMousePressed = false; + if (event.type == Common::EVENT_RBUTTONUP) { + _mouseStatus &= ~2; + } else { + _mouseStatus &= ~1; + } + return; + case Common::EVENT_MOUSEMOVE: + _mousePos = event.mouse; + _currentPos = event.mouse; + _mouseMoved = true; + break; + default: + break; + } + } +} + +void EventsManager::checkForNextFrameCounter() { + // Check for next game frame + uint32 milli = g_system->getMillis(); + if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { + ++_frameCounter; + _priorFrameTime = milli; + + // Do any palette cycling + _vm->_game->_scene.animatePalette(); + + // Give time to the debugger + _vm->_debugger->onFrame(); + + // Display the frame + _vm->_screen.updateScreen(); + + // Signal the ScummVM debugger + _vm->_debugger->onFrame(); + } +} + +void EventsManager::delay(int cycles) { + uint32 totalMilli = cycles * 1000 / GAME_FRAME_RATE; + uint32 delayEnd = g_system->getMillis() + totalMilli; + + while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd) { + g_system->delayMillis(10); + + pollEvents(); + } +} + +void EventsManager::waitForNextFrame() { + _mouseClicked = false; + _mouseReleased = false; + _mouseButtons = 0; + + bool mouseClicked = false; + bool mouseReleased = false; + int mouseButtons = 0; + + uint32 frameCtr = getFrameCounter(); + while (!_vm->shouldQuit() && frameCtr == _frameCounter) { + delay(1); + + mouseClicked |= _mouseClicked; + mouseReleased |= _mouseReleased; + mouseButtons |= _mouseButtons; + } + + _mouseClicked = mouseClicked; + _mouseReleased = mouseReleased; + _mouseButtons = mouseButtons; + _mouseMoved |= _mouseClicked || _mouseReleased; +} + +void EventsManager::initVars() { + _mousePos = Common::Point(-1, -1); + _mouseStatusCopy = _mouseStatus; + _vD2 = _vD8 = 0; +} + +} // End of namespace MADS diff --git a/engines/mads/events.h b/engines/mads/events.h new file mode 100644 index 0000000000..3d7504c0bd --- /dev/null +++ b/engines/mads/events.h @@ -0,0 +1,164 @@ +/* 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 MADS_EVENTS_H +#define MADS_EVENTS_H + +#include "common/scummsys.h" +#include "common/events.h" +#include "common/stack.h" +#include "mads/assets.h" +#include "mads/sprites.h" + +namespace MADS { + +enum CursorType { CURSOR_NONE = 0, CURSOR_ARROW = 1, CURSOR_WAIT = 2, CURSOR_GO_DOWN = 3, + CURSOR_GO_UP = 4, CURSOR_GO_LEFT = 5, CURSOR_GO_RIGHT = 6 }; + +#define GAME_FRAME_RATE 50 +#define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) + +class MADSEngine; + +class EventsManager { +private: + MADSEngine *_vm; + uint32 _frameCounter; + uint32 _priorFrameTime; + Common::Point _mousePos; + Common::Point _currentPos; + + /** + * Updates the cursor image when the current cursor changes + */ + void changeCursor(); + + /** + * Checks for whether the next game frame number has been reached. + */ + void checkForNextFrameCounter(); +public: + SpriteAsset *_cursorSprites; + CursorType _cursorId; + CursorType _newCursorId; + bool _mouseClicked; + bool _mouseReleased; + byte _mouseButtons; + bool _rightMousePressed; + int _mouseStatus; + int _vD2; + int _mouseStatusCopy; + bool _mouseMoved; + int _vD8; + Common::Stack<Common::Event> _pendingKeys; +public: + /** + * Constructor + */ + EventsManager(MADSEngine *vm); + + /** + * Destructor + */ + ~EventsManager(); + + /** + * Loads the sprite set containing the cursors + */ + void loadCursors(const Common::String &spritesName); + + /** + * Sets the cursor + */ + void setCursor(CursorType cursorId); + + /** + * Sets the cursor + */ + void setCursor2(CursorType cursorId); + + /** + * Show the mouse cursor + */ + void showCursor(); + + /** + * Hide the mouse cursor + */ + void hideCursor(); + + /** + * Returns if the mouse cursor is visible + */ + bool isCursorVisible(); + + /** + * Shows the wait cursor + */ + void waitCursor(); + + /** + * Free currently loaded cursors + */ + void freeCursors(); + + /** + * Poll any pending events + */ + void pollEvents(); + + /** + * Return the current mouse position + */ + Common::Point mousePos() const { return _mousePos; } + + /** + * Return the current mouse position + */ + Common::Point currentPos() const { return _currentPos; } + + /** + * Delay for a given number of frames + */ + void delay(int amount); + + /** + * Wait for the next frame + */ + void waitForNextFrame(); + + /** + * Gets the current frame counter + */ + uint32 getFrameCounter() const { return _frameCounter; } + + void initVars(); + + /** + * Returns true if there's any pending keys to be processed + */ + bool isKeyPressed() const { return !_pendingKeys.empty(); } +}; + +} // End of namespace MADS + +#endif /* MADS_EVENTS_H */ diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp new file mode 100644 index 0000000000..6af1346f01 --- /dev/null +++ b/engines/mads/font.cpp @@ -0,0 +1,252 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +MADSEngine *Font::_vm; + +Common::HashMap<Common::String, Font *> *Font::_fonts; + +uint8 Font::_fontColors[4]; + +void Font::init(MADSEngine *vm) { + _vm = vm; + _fontColors[0] = 0xFF; + _fontColors[1] = 0xF; + _fontColors[2] = 7; + _fontColors[3] = 8; + + _fonts = new Common::HashMap<Common::String, Font *>(); +} + +void Font::deinit() { + Common::HashMap<Common::String, Font *>::iterator i; + for (i = _fonts->begin(); i != _fonts->end(); ++i) + delete (*i)._value; + + delete _fonts; +} + +Font *Font::getFont(const Common::String &fontName) { + if (_fonts->contains(fontName)) { + return _fonts->getVal(fontName); + } else { + Font *font = new Font(fontName); + _fonts->setVal(fontName, font); + return font; + } +} + +Font::Font() { + _charWidths = nullptr; + _charOffs = nullptr; + _charData = nullptr; + setFont(FONT_INTERFACE); +} + +Font::Font(const Common::String &filename) { + _charWidths = nullptr; + _charOffs = nullptr; + _charData = nullptr; + setFont(filename); +} + +Font::~Font() { + delete[] _charWidths; + delete[] _charOffs; + delete[] _charData; +} + +void Font::setFont(const Common::String &filename) { + if (!_filename.empty() && (filename == _filename)) + // Already using specified font, so don't bother reloading + return; + + _filename = filename; + + MadsPack fontData(filename, _vm); + Common::SeekableReadStream *fontFile = fontData.getItemStream(0); + + _maxHeight = fontFile->readByte(); + _maxWidth = fontFile->readByte(); + + _charWidths = new uint8[128]; + // Char data is shifted by 1 + _charWidths[0] = 0; + fontFile->read(_charWidths + 1, 127); + fontFile->readByte(); // remainder + + _charOffs = new uint16[128]; + + uint startOffs = 2 + 128 + 256; + uint fontSize = fontFile->size() - startOffs; + + // Char data is shifted by 1 + _charOffs[0] = 0; + for (int i = 1; i < 128; i++) + _charOffs[i] = fontFile->readUint16LE() - startOffs; + fontFile->readUint16LE(); // remainder + + _charData = new uint8[fontSize]; + fontFile->read(_charData, fontSize); + + delete fontFile; +} + +void Font::setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4) { + _fontColors[0] = v1; + _fontColors[1] = v2; + _fontColors[2] = v3; + _fontColors[3] = v4; +} + +void Font::setColorMode(SelectionMode mode) { + switch (mode) { + case SELMODE_UNSELECTED: + setColors(0xFF, 4, 4, 0); + break; + case SELMODE_HIGHLIGHTED: + setColors(0xFF, 5, 5, 0); + break; + case SELMODE_SELECTED: + setColors(0xFF, 6, 6, 0); + break; + default: + break; + } +} + +int Font::writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, + int spaceWidth, int width) { + int xEnd; + if (width > 0) + xEnd = MIN((int)surface->w, pt.x + width); + else + xEnd = surface->w; + + int x = pt.x; + int y = pt.y; + + int skipY = 0; + if (y < 0) { + skipY = -y; + y = 0; + } + + int height = MAX(0, _maxHeight - skipY); + if (height == 0) + return x; + + int bottom = y + height - 1; + if (bottom > surface->getHeight() - 1) { + height -= MIN(height, bottom - (surface->getHeight() - 1)); + } + + if (height <= 0) + return x; + + byte *destPtr = surface->getBasePtr(x, y); + uint8 *oldDestPtr = destPtr; + + int xPos = x; + + const char *text = msg.c_str(); + while (*text) { + char theChar = (*text++) & 0x7F; + int charWidth = _charWidths[(byte)theChar]; + + if (charWidth > 0) { + + if (xPos + charWidth > xEnd) + return xPos; + + uint8 *charData = &_charData[_charOffs[(byte)theChar]]; + int bpp = getBpp(charWidth); + + if (skipY != 0) + charData += bpp * skipY; + + for (int i = 0; i < height; i++) { + for (int j = 0; j < bpp; j++) { + if (*charData & 0xc0) + *destPtr = _fontColors[(*charData & 0xc0) >> 6]; + destPtr++; + if (*charData & 0x30) + *destPtr = _fontColors[(*charData & 0x30) >> 4]; + destPtr++; + if (*charData & 0x0C) + *destPtr = _fontColors[(*charData & 0x0C) >> 2]; + destPtr++; + if (*charData & 0x03) + *destPtr = _fontColors[*charData & 0x03]; + destPtr++; + charData++; + } + + destPtr += surface->getWidth() - bpp * 4; + + } + + destPtr = oldDestPtr + charWidth + spaceWidth; + oldDestPtr = destPtr; + + } + + xPos += charWidth + spaceWidth; + + } + + return xPos; + +} + +int Font::getWidth(const Common::String &msg, int spaceWidth) { + int width = 0; + const char *text = msg.c_str(); + + if (msg.size() > 0) { + while (*text) + width += _charWidths[*text++ & 0x7F] + spaceWidth; + width -= spaceWidth; + } + + return width; +} + +int Font::getBpp(int charWidth) { + if (charWidth > 12) + return 4; + else if (charWidth > 8) + return 3; + else if (charWidth > 4) + return 2; + else + return 1; +} + +} // End of namespace MADS diff --git a/engines/mads/font.h b/engines/mads/font.h new file mode 100644 index 0000000000..47df647637 --- /dev/null +++ b/engines/mads/font.h @@ -0,0 +1,95 @@ +/* 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 MADS_FONT_H +#define MADS_FONT_H + +#include "common/scummsys.h" +#include "common/hashmap.h" +#include "common/endian.h" +#include "common/util.h" +#include "mads/msurface.h" + +namespace MADS { + +#define FONT_CONVERSATION "*FONTCONV.FF" +#define FONT_INTERFACE "*FONTINTR.FF" +#define FONT_MAIN "*FONTMAIN.FF" +#define FONT_MENU "*FONTMENU.FF" // Not in Rex (uses bitmap files for menu strings) +#define FONT_MISC "*FONTMISC.FF" +#define FONT_TELE "*FONTTELE.FF" // Not in Phantom +#define FONT_PHAN "*FONTPHAN.FF" // Phantom only + +enum SelectionMode { + SELMODE_UNSELECTED = 0, SELMODE_HIGHLIGHTED = 1, SELMODE_SELECTED = 2 +}; + +class MADSEngine; + +class Font { +private: + static uint8 _fontColors[4]; + static MADSEngine *_vm; + static Common::HashMap<Common::String, Font *> *_fonts; +public: + /** + * Initialize the font system + */ + static void init(MADSEngine *vm); + + /** + * Free up the resources used by the font + */ + static void deinit(); + + /** + * Returns a new Font instance using the specified font name + */ + static Font *getFont(const Common::String &fontName); +private: + uint8 _maxWidth, _maxHeight; + uint8 *_charWidths; + uint16 *_charOffs; + uint8 *_charData; + Common::String _filename; + + int getBpp(int charWidth); + + void setFont(const Common::String &filename); +public: + Font(); + Font(const Common::String &filename); + virtual ~Font(); + + void setColors(uint8 v1, uint8 v2, uint8 v3, uint8 v4); + void setColorMode(SelectionMode mode); + + int maxWidth() const { return _maxWidth; } + int getWidth(const Common::String &msg, int spaceWidth = -1); + int getHeight() const { return _maxHeight; } + int writeString(MSurface *surface, const Common::String &msg, const Common::Point &pt, + int spaceWidth = 0, int width = 0); +}; + +} // End of namespace MADS + +#endif /* MADS_FONT_H */ diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp new file mode 100644 index 0000000000..05dd932482 --- /dev/null +++ b/engines/mads/game.cpp @@ -0,0 +1,608 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "common/memstream.h" +#include "common/serializer.h" +#include "graphics/palette.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/game.h" +#include "mads/game_data.h" +#include "mads/events.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/dragonsphere/game_dragonsphere.h" +#include "mads/nebular/game_nebular.h" +#include "mads/phantom/game_phantom.h" + +namespace MADS { + +Game *Game::init(MADSEngine *vm) { + switch (vm->getGameID()) { + case GType_RexNebular: + return new Nebular::GameNebular(vm); + case GType_Dragonsphere: + return new Dragonsphere::GameDragonsphere(vm); + case GType_Phantom: + return new Phantom::GamePhantom(vm); + default: + error("Game: Unknown game"); + } + + return nullptr; +} + +Game::Game(MADSEngine *vm) + : _vm(vm), _surface(nullptr), _objects(vm), _scene(vm), + _screenObjects(vm), _player(vm) { + _sectionNumber = _priorSectionNumber = 0; + _loadGameSlot = -1; + _lastSave = -1; + _saveFile = nullptr; + _statusFlag = 0; + _sectionHandler = nullptr; + _sectionNumber = 1; + _priorSectionNumber = 0; + _currentSectionNumber = -1; + _kernelMode = KERNEL_GAME_LOAD; + _quoteEmergency = false; + _vocabEmergency = false; + _aaName = "*I0.AA"; + _priorFrameTimer = 0; + _anyEmergency = false; + _triggerMode = SEQUENCE_TRIGGER_PARSER; + _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _trigger = 0; + _winStatus = 0; + _widepipeCtr = 0; + _fx = kTransitionNone; + + // Load the inventory object list + _objects.load(); + if (_objects._inventoryList.size() > 0) + // At least one item in default inventory, so select first item for display + _scene._userInterface._selectedInvIndex = 0; + + // Load the quotes + loadQuotes(); +} + +Game::~Game() { + delete _saveFile; + delete _surface; + delete _sectionHandler; +} + +void Game::run() { + initializeGlobals(); + + // If requested, load a savegame instead of showing the intro + if (ConfMan.hasKey("save_slot")) { + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0 && saveSlot <= 999) + _loadGameSlot = saveSlot; + } + + _statusFlag = true; + int protectionResult = -1; + + if (_loadGameSlot == -1) { + protectionResult = checkCopyProtection(); + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + break; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + break; + default: + // Copy protection check succeeded + _scene._nextSceneId = 101; + _scene._priorSceneId = -1; + break; + } + } + + // Get the initial starting time for the first scene + _scene._frameStartTime = _vm->_events->getFrameCounter(); + + if (_saveFile == nullptr && protectionResult != -1 && protectionResult != -2) { + initSection(_sectionNumber); + _statusFlag = true; + + _vm->_dialogs->_pendingDialog = DIALOG_DIFFICULTY; + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + + _priorSectionNumber = 0; + _priorSectionNumber = -1; + _scene._priorSceneId = 0; + _scene._currentSceneId = -1; + } + + if (protectionResult != 1 && protectionResult != 2) { + initializeGlobals(); + } + + if (_statusFlag) + gameLoop(); +} + +void Game::splitQuote(const Common::String &source, Common::String &line1, Common::String &line2) { + // Make the first line up the end of the word at the half-way point + const char *strP = source.c_str() + source.size() / 2; + while (*strP != ' ') ++strP; + + line1 = Common::String(source.c_str(), strP); + + // The rest of the string goes in the second line + while (*strP == ' ') ++strP; + line2 = Common::String(strP); +} + +void Game::gameLoop() { + while (!_vm->shouldQuit() && _statusFlag) { + if (_loadGameSlot != -1) { + loadGame(_loadGameSlot); + _loadGameSlot = -1; + } + + setSectionHandler(); + _sectionHandler->preLoadSection(); + initSection(_sectionNumber); + _vm->_sound->init(_sectionNumber); + _sectionHandler->postLoadSection(); + + _scene._spriteSlots.reset(); + + if (_sectionNumber == _currentSectionNumber) + sectionLoop(); + + _player.releasePlayerSprites(); + assert(_scene._sprites._assetCount == 0); + + _vm->_palette->unlock(); + _vm->_events->waitCursor(); + _vm->_events->freeCursors(); + _vm->_sound->closeDriver(); + } + + _vm->_palette->close(); +} + +void Game::sectionLoop() { + while (!_vm->shouldQuit() && _statusFlag && (_sectionNumber == _currentSectionNumber)) { + _kernelMode = KERNEL_ROOM_PRELOAD; + _player._spritesChanged = true; + _quoteEmergency = false; + _vocabEmergency = false; + _vm->_events->waitCursor(); + + _scene.clearVocab(); + _scene._dynamicHotspots.clear(); + _scene.loadSceneLogic(); + + _player._walkAnywhere = false; + _player._stepEnabled = true; + _player._visible = true; + _vm->_dialogs->_defaultPosition = Common::Point(-1, -1); + _visitedScenes.add(_scene._nextSceneId); + + // Reset the user interface + _screenObjects._forceRescan = true; + _screenObjects._inputMode = kInputBuildingSentences; + _scene._userInterface._scrollbarActive = SCROLLBAR_NONE; + + _player._loadsFirst = true; + + _scene._sceneLogic->setup(); + if (_player._spritesChanged || _player._loadsFirst) { + if (_player._spritesLoaded) + _player.releasePlayerSprites(); + _vm->_palette->resetGamePalette(18, 10); + _scene._spriteSlots.reset(); + } else { + _vm->_palette->initPalette(); + } + + // Set up scene palette usage + _scene._scenePaletteUsage.clear(); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF0)); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF1)); + _scene._scenePaletteUsage.push_back(PaletteUsage::UsageEntry(0xF2)); + _vm->_palette->_paletteUsage.load(&_scene._scenePaletteUsage); + + if (!_player._spritesLoaded && _player._loadsFirst) { + if (_player.loadSprites("")) + _vm->quitGame(); + _player._loadedFirst = true; + } + + _scene.loadScene(_scene._nextSceneId, _aaName, 0); + _vm->_sound->pauseNewCommands(); + + if (!_player._spritesLoaded) { + if (_player.loadSprites("")) + _vm->quitGame(); + _player._loadedFirst = false; + } + + _vm->_events->initVars(); + _scene._userInterface._highlightedCommandIndex = -1; + _scene._userInterface._highlightedInvIndex = -1; + _scene._userInterface._highlightedItemVocabIndex = -1; + + _scene._action.clear(); + _player.setFinalFacing(); + _player._facing = _player._turnToFacing; + _player.cancelCommand(); + _kernelMode = KERNEL_ROOM_INIT; + + switch (_vm->_screenFade) { + case SCREEN_FADE_SMOOTH: + _fx = kTransitionFadeOutIn; + break; + case SCREEN_FADE_FAST: + _fx = kCenterVertTransition; + break; + default: + _fx = kTransitionNone; + break; + } + + _trigger = 0; + _priorFrameTimer = _scene._frameStartTime; + + // Call the scene logic for entering the given scene + _triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene._sceneLogic->enter(); + + // If in the middle of restoring a game, handle the rest of the loading + if (_saveFile != nullptr) { + Common::Serializer s(_saveFile, nullptr); + synchronize(s, false); + delete _saveFile; + _saveFile = nullptr; + } + + // Set player data + _player._targetPos = _player._playerPos; + _player._turnToFacing = _player._facing; + _player._targetFacing = _player._facing; + _player.selectSeries(); + _player.updateFrame(); + + _player._beenVisible = _player._visible; + _player._special = _scene.getDepthHighBits(_player._playerPos); + _player._priorTimer = _scene._frameStartTime - _player._ticksAmount; + _player.idle(); + + if (_scene._userInterface._selectedInvIndex >= 0) { + _scene._userInterface.loadInventoryAnim( + _objects._inventoryList[_scene._userInterface._selectedInvIndex]); + } else { + _scene._userInterface.noInventoryAnim(); + } + + _kernelMode = KERNEL_ACTIVE_CODE; + _scene._roomChanged = false; + + if ((_quoteEmergency || _vocabEmergency) && !_anyEmergency) { + _scene._currentSceneId = _scene._priorSceneId; + _anyEmergency = true; + } else { + _anyEmergency = false; + _scene.loop(); + } + + _vm->_events->waitCursor(); + _kernelMode = KERNEL_ROOM_PRELOAD; + + delete _scene._activeAnimation; + _scene._activeAnimation = nullptr; + + _scene._reloadSceneFlag = false; + + _scene._userInterface.noInventoryAnim(); + _scene.removeSprites(); + + if (!_player._loadedFirst) { + _player._spritesLoaded = false; + _player._spritesChanged = true; + } + + // Clear the scene + _scene.freeCurrentScene(); + _sectionNumber = _scene._nextSceneId / 100; + + // Check whether to show a dialog + checkShowDialog(); + } +} + +void Game::initSection(int sectionNumber) { + _priorSectionNumber = _currentSectionNumber; + _currentSectionNumber = sectionNumber; + + _vm->_palette->resetGamePalette(18, 10); + _vm->_palette->setLowRange(); + + if (_scene._layer == LAYER_GUI) + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 0, 4); + + _vm->_events->loadCursors("*CURSOR.SS"); + + assert(_vm->_events->_cursorSprites); + _vm->_events->setCursor2((_vm->_events->_cursorSprites->getCount() <= 1) ? + CURSOR_ARROW : CURSOR_WAIT); +} + +void Game::loadQuotes() { + File f("*QUOTES.DAT"); + + Common::String msg; + while (true) { + uint8 b = f.readByte(); + + msg += b; + if (f.eos() || b == '\0') { + // end of string, add it to the strings list + _quotes.push_back(msg); + msg = ""; + } + + if (f.eos()) break; + } + + f.close(); +} + +Common::StringArray Game::getMessage(uint32 id) { + File f("*MESSAGES.DAT"); + int count = f.readUint16LE(); + + for (int idx = 0; idx < count; ++idx) { + uint32 itemId = f.readUint32LE(); + uint32 offset = f.readUint32LE(); + uint16 size = f.readUint16LE(); + + if (itemId == id) { + // Get the source buffer size + uint16 sizeIn; + if (idx == (count - 1)) { + sizeIn = f.size() - offset; + } else { + f.skip(4); + uint32 nextOffset = f.readUint32LE(); + sizeIn = nextOffset - offset; + } + + // Get the compressed data + f.seek(offset); + byte *bufferIn = new byte[sizeIn]; + f.read(bufferIn, sizeIn); + + // Decompress it + char *bufferOut = new char[size]; + FabDecompressor fab; + fab.decompress(bufferIn, sizeIn, (byte *)bufferOut, size); + + // Form the output string list + Common::StringArray result; + const char *p = bufferOut; + while (p < (bufferOut + size)) { + result.push_back(p); + p += strlen(p) + 1; + } + + delete[] bufferIn; + delete[] bufferOut; + return result; + } + } + + error("Invalid message Id specified"); +} + +static const char *const DEBUG_STRING = "WIDEPIPE"; + +void Game::handleKeypress(const Common::Event &event) { + if (event.kbd.flags & Common::KBD_CTRL) { + if (_widepipeCtr == 8) { + // Implement original game cheating keys here someday + } else { + if (event.kbd.keycode == (Common::KEYCODE_a + + (DEBUG_STRING[_widepipeCtr] - 'a'))) { + if (++_widepipeCtr == 8) { + MessageDialog *dlg = new MessageDialog(_vm, 2, + "CHEATING ENABLED", "(for your convenience)."); + dlg->show(); + delete dlg; + } + } + } + } + + switch (event.kbd.keycode) { + case Common::KEYCODE_F1: + _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; + break; + case Common::KEYCODE_F5: + _vm->_dialogs->_pendingDialog = DIALOG_SAVE; + break; + case Common::KEYCODE_F7: + _vm->_dialogs->_pendingDialog = DIALOG_RESTORE; + break; + default: + break; + } + + warning("TODO: handleKeypress - %d", (int)event.kbd.keycode); +} + +void Game::synchronize(Common::Serializer &s, bool phase1) { + if (phase1) { + s.syncAsSint16LE(_fx); + s.syncAsSint16LE(_trigger); + s.syncAsUint16LE(_triggerSetupMode); + s.syncAsUint16LE(_triggerMode); + s.syncString(_aaName); + s.syncAsSint16LE(_lastSave); + + _scene.synchronize(s); + _objects.synchronize(s); + _visitedScenes.synchronize(s); + _player.synchronize(s); + _screenObjects.synchronize(s); + } else { + // Load scene specific data for the loaded scene + _scene._sceneLogic->synchronize(s); + } +} + +void Game::loadGame(int slotNumber) { + _saveFile = g_system->getSavefileManager()->openForLoading( + _vm->generateSaveName(slotNumber)); + + Common::Serializer s(_saveFile, nullptr); + + // Load the savaegame header + MADSSavegameHeader header; + if (!readSavegameHeader(_saveFile, header)) + error("Invalid savegame"); + + if (header._thumbnail) { + header._thumbnail->free(); + delete header._thumbnail; + } + + // Load most of the savegame data with the exception of scene specific info + synchronize(s, true); + + // Set up section/scene and other initial states for post-load + _currentSectionNumber = -2; + _scene._currentSceneId = -2; + _sectionNumber = _scene._nextSceneId / 100; + _scene._frameStartTime = _vm->_events->getFrameCounter(); + _vm->_screen._shakeCountdown = -1; + + // Default the selected inventory item to the first one, if the player has any + _scene._userInterface._selectedInvIndex = _objects._inventoryList.size() > 0 ? 0 : -1; + + // Set player sprites sets flags + _player._spritesLoaded = false; + _player._spritesChanged = true; +} + +void Game::saveGame(int slotNumber, const Common::String &saveName) { + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving( + _vm->generateSaveName(slotNumber)); + + MADSSavegameHeader header; + header._saveName = saveName; + writeSavegameHeader(out, header); + + Common::Serializer s(nullptr, out); + synchronize(s, true); + synchronize(s, false); + + out->finalize(); + delete out; +} + +const char *const SAVEGAME_STR = "MADS"; +#define SAVEGAME_STR_SIZE 4 + +bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header._thumbnail = nullptr; + + // Validate the header Id + in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1); + if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) + return false; + + header._version = in->readByte(); + if (header._version > MADS_SAVEGAME_VERSION) + return false; + + // Read in the string + header._saveName.clear(); + char ch; + while ((ch = (char)in->readByte()) != '\0') header._saveName += ch; + + // Get the thumbnail + header._thumbnail = Graphics::loadThumbnail(*in); + if (!header._thumbnail) + return false; + + // Read in save date/time + header._year = in->readSint16LE(); + header._month = in->readSint16LE(); + header._day = in->readSint16LE(); + header._hour = in->readSint16LE(); + header._minute = in->readSint16LE(); + header._totalFrames = in->readUint32LE(); + + return true; +} + +void Game::writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(MADS_SAVEGAME_VERSION); + + // Write savegame name + out->write(header._saveName.c_str(), header._saveName.size()); + out->writeByte('\0'); + + // Get the active palette + uint8 thumbPalette[256 * 3]; + g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256); + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + ::createThumbnail(thumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + thumb->free(); + delete thumb; + + // Write out the save date/time + TimeDate td; + g_system->getTimeAndDate(td); + out->writeSint16LE(td.tm_year + 1900); + out->writeSint16LE(td.tm_mon + 1); + out->writeSint16LE(td.tm_mday); + out->writeSint16LE(td.tm_hour); + out->writeSint16LE(td.tm_min); + out->writeUint32LE(_vm->_events->getFrameCounter()); +} + +} // End of namespace MADS diff --git a/engines/mads/game.h b/engines/mads/game.h new file mode 100644 index 0000000000..1b06f847d0 --- /dev/null +++ b/engines/mads/game.h @@ -0,0 +1,241 @@ +/* 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 MADS_GAME_H +#define MADS_GAME_H + +#include "common/scummsys.h" +#include "common/savefile.h" +#include "common/str-array.h" +#include "common/serializer.h" +#include "mads/audio.h" +#include "mads/scene.h" +#include "mads/game_data.h" +#include "mads/globals.h" +#include "mads/inventory.h" +#include "mads/player.h" +#include "mads/screen.h" + +namespace MADS { + +class MADSEngine; + +enum { + PLAYER_INVENTORY = 2 +}; + +enum KernelMode { + KERNEL_GAME_LOAD = 0, KERNEL_SECTION_PRELOAD = 1, KERNEL_SECTION_INIT = 2, + KERNEL_ROOM_PRELOAD = 3, KERNEL_ROOM_INIT = 4, KERNEL_ACTIVE_CODE = 5 +}; + +enum ProtectionResult { + PROTECTION_SUCCEED = 0, PROTECTION_FAIL = 1, PROTECTION_ESCAPE = 2 +}; + +#define MADS_SAVEGAME_VERSION 1 + +struct MADSSavegameHeader { + uint8 _version; + Common::String _saveName; + Graphics::Surface *_thumbnail; + int _year, _month, _day; + int _hour, _minute; + int _totalFrames; +}; + +class Game { +private: + /** + * Main game loop + */ + void gameLoop(); + + /** + * Inner game loop for executing gameplay within a game section + */ + void sectionLoop(); + + /** + * Load quotes data + */ + void loadQuotes(); +protected: + MADSEngine *_vm; + MSurface *_surface; + int _statusFlag; + Common::StringArray _quotes; + bool _quoteEmergency; + bool _vocabEmergency; + bool _anyEmergency; + int _lastSave; + Common::String _saveName; + Common::InSaveFile *_saveFile; + + /** + * Constructor + */ + Game(MADSEngine *vm); + + /** + * Initializes the current section number of the game + */ + void initSection(int sectionNumber); + + //@{ + /** @name Virtual Method list */ + + /** + * Perform any copy protection check + */ + virtual ProtectionResult checkCopyProtection() = 0; + + /** + * Initializes global variables for a new game + */ + virtual void initializeGlobals() = 0; + + /** + * Set up the section handler specific to each section + */ + virtual void setSectionHandler() = 0; + + /** + * Checks for whether to show a dialog + */ + virtual void checkShowDialog() = 0; + + //@} + +public: + static Game *init(MADSEngine *vm); + +public: + Player _player; + ScreenObjects _screenObjects; + int _sectionNumber; + int _priorSectionNumber; + int _currentSectionNumber; + InventoryObjects _objects; + SectionHandler *_sectionHandler; + VisitedScenes _visitedScenes; + Scene _scene; + KernelMode _kernelMode; + int _trigger; + ScreenTransition _fx; + TriggerMode _triggerMode; + TriggerMode _triggerSetupMode; + uint32 _priorFrameTimer; + Common::String _aaName; + int _winStatus; + int _widepipeCtr; + int _loadGameSlot; + +public: + virtual ~Game(); + + /** + * Main outer loop for the game + */ + void run(); + + /** + * Return the number of quotes + */ + uint32 getQuotesSize() { return _quotes.size(); } + + /** + * Get a specific quote string + */ + const Common::String &getQuote(uint32 index) { return _quotes[index - 1]; } + + /** + * Split a quote into two lines for display on-screen + */ + void splitQuote(const Common::String &source, Common::String &line1, Common::String &line2); + + Common::StringArray getMessage(uint32 id); + + /** + * Returns the globals for the game + */ + virtual Globals &globals() = 0; + + /** + * Standard object handling across the game + */ + virtual void doObjectAction() = 0; + + /** + * Fallback handler for any action that isn't explicitly handled + */ + virtual void unhandledAction() = 0; + + /** + * Global game step + */ + virtual void step() = 0; + + /** + * Synchronize the game data + * @param s Serializer + * @param phase1 If true, it's synchronizing the basic scene information + */ + virtual void synchronize(Common::Serializer &s, bool phase1); + + // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs + void clearQuotes() {} + void loadQuoteRange(int startNum, int endNum) {} + void loadQuoteSet(...) {} + void loadQuote(int quoteNum) {} + + /** + * Handle a keyboard event + */ + void handleKeypress(const Common::Event &event); + + /** + * Starts a savegame loading. + * @remarks Due to the way the engine is implemented, loading is done in two + * parts, the second part after the specific scene has been loaded + */ + void loadGame(int slotNumber); + + /** + * Save the current game + */ + void saveGame(int slotNumber, const Common::String &saveName); + + /** + * Write out a savegame header + */ + void writeSavegameHeader(Common::OutSaveFile *out, MADSSavegameHeader &header); + + /** + * Read in a savegame header + */ + static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header); +}; + +} // End of namespace MADS + +#endif /* MADS_GAME_H */ diff --git a/engines/mads/game_data.cpp b/engines/mads/game_data.cpp new file mode 100644 index 0000000000..0e2dcec70f --- /dev/null +++ b/engines/mads/game_data.cpp @@ -0,0 +1,54 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/nebular/game_nebular.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" + +namespace MADS { + +void VisitedScenes::add(int sceneId) { + _sceneRevisited = exists(sceneId); + + if (!_sceneRevisited) + push_back(sceneId); +} + +bool VisitedScenes::exists(int sceneId) { + for (uint i = 0; i < size(); ++i) { + if ((*this)[i] == sceneId) + return true; + } + + return false; +} + +void VisitedScenes::synchronize(Common::Serializer &s) { + SynchronizedList::synchronize(s); + s.syncAsByte(_sceneRevisited); +} + +} // End of namespace MADS diff --git a/engines/mads/game_data.h b/engines/mads/game_data.h new file mode 100644 index 0000000000..f15cd1a8f0 --- /dev/null +++ b/engines/mads/game_data.h @@ -0,0 +1,73 @@ +/* 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 MADS_GAME_DATA_H +#define MADS_GAME_DATA_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/resources.h" + +namespace MADS { + +class MADSEngine; +class Game; + +class VisitedScenes : public SynchronizedList { +public: + /** + * Stores true when a previously visited scene is revisited + */ + bool _sceneRevisited; + + /** + * Returns true if a given Scene Id exists in the listed of previously visited scenes. + */ + bool exists(int sceneId); + + /** + * Adds a scene Id to the list of previously visited scenes, if it doesn't already exist + */ + void add(int sceneId); + + /** + * Synchronizes the list + */ + void synchronize(Common::Serializer &s); +}; + +class SectionHandler { +protected: + MADSEngine *_vm; +public: + SectionHandler(MADSEngine *vm) : _vm(vm) {} + virtual ~SectionHandler() {} + + virtual void preLoadSection() = 0; + virtual void sectionPtr2() = 0; + virtual void postLoadSection() = 0; + virtual void step() {} +}; + +} // End of namespace MADS + +#endif /* MADS_GAME_DATA_H */ diff --git a/engines/mads/globals.cpp b/engines/mads/globals.cpp new file mode 100644 index 0000000000..1d088992ea --- /dev/null +++ b/engines/mads/globals.cpp @@ -0,0 +1,33 @@ +/* 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 "common/scummsys.h" +#include "mads/globals.h" + +namespace MADS { + +void Globals::reset() { + for (uint i = 0; i < size(); ++i) + (*this)[i] = 0; +} + +} // End of namespace MADS diff --git a/engines/mads/globals.h b/engines/mads/globals.h new file mode 100644 index 0000000000..a6c9b628dd --- /dev/null +++ b/engines/mads/globals.h @@ -0,0 +1,47 @@ +/* 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 MADS_GLOBALS_H +#define MADS_GLOBALS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" +#include "mads/resources.h" + +namespace MADS { + +class Globals : public SynchronizedList { +public: + Globals() {} + + virtual ~Globals() {} + + /* + * Resets all the globals to empty + */ + void reset(); +}; + +} // End of namespace MADS + +#endif /* MADS_GLOBALS_H */ diff --git a/engines/mads/hotspots.cpp b/engines/mads/hotspots.cpp new file mode 100644 index 0000000000..365f30985b --- /dev/null +++ b/engines/mads/hotspots.cpp @@ -0,0 +1,207 @@ +/* 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 "mads/mads.h" +#include "mads/hotspots.h" + +namespace MADS { + +DynamicHotspot::DynamicHotspot() { + _seqIndex = 0; + _facing = FACING_NONE; + _descId = 0; + _verbId = 0; + _articleNumber = 0; + _cursor = CURSOR_NONE; + _active = false; +} + +void DynamicHotspot::synchronize(Common::Serializer &s) { + +} + +/*------------------------------------------------------------------------*/ + +DynamicHotspots::DynamicHotspots(MADSEngine *vm) : _vm(vm) { + for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) { + DynamicHotspot rec; + rec._active = false; + _entries.push_back(rec); + } + + _changed = true; + _count = 0; +} + +int DynamicHotspots::add(int descId, int verbId, int seqIndex, const Common::Rect &bounds) { + // Find a free slot + uint idx = 0; + while ((idx < _entries.size()) && _entries[idx]._active) + ++idx; + if (idx == _entries.size()) + error("DynamicHotspots overflow"); + + _entries[idx]._active = true; + _entries[idx]._descId = descId; + _entries[idx]._seqIndex = seqIndex; + _entries[idx]._bounds = bounds; + _entries[idx]._feetPos = Common::Point(-3, 0); + _entries[idx]._facing = FACING_NONE; + _entries[idx]._verbId = verbId; + _entries[idx]._articleNumber = PREP_IN; + _entries[idx]._cursor = CURSOR_NONE; + + ++_count; + _changed = true; + + if (seqIndex >= 0) + _vm->_game->_scene._sequences[seqIndex]._dynamicHotspotIndex = idx; + + return idx; +} + +int DynamicHotspots::setPosition(int index, const Common::Point &pos, Facing facing) { + if (index >= 0) { + _entries[index]._feetPos = pos; + _entries[index]._facing = facing; + } + + return index; +} + +int DynamicHotspots::setCursor(int index, CursorType cursor) { + if (index >= 0) + _entries[index]._cursor = cursor; + + return index; +} + +void DynamicHotspots::remove(int index) { + Scene &scene = _vm->_game->_scene; + + if (index >= 0 && _entries[index]._active) { + if (_entries[index]._seqIndex >= 0) + scene._sequences[_entries[index]._seqIndex]._dynamicHotspotIndex = -1; + _entries[index]._active = false; + + --_count; + _changed = true; + } +} + +void DynamicHotspots::clear() { + for (uint i = 0; i < _entries.size(); ++i) + _entries[i]._active = false; + + _changed = false; + _count = 0; +} + +void DynamicHotspots::reset() { + for (uint i = 0; i < _entries.size(); ++i) + remove(i); + + _count = 0; + _changed = false; +} + +void DynamicHotspots::refresh() { + // Reset the screen objects back to only contain UI elements + ScreenObjects &scrObjects = _vm->_game->_screenObjects; + scrObjects.resize(scrObjects._uiCount); + + // Loop through adding hotspots + for (uint i = 0; i < _entries.size(); ++i) { + DynamicHotspot &dh = (*this)[i]; + + if ((*this)[i]._active) { + switch (scrObjects._inputMode) { + case kInputBuildingSentences: + case kInputLimitedSentences: + scrObjects.add(dh._bounds, _vm->_game->_scene._layer, CAT_12, dh._descId); + scrObjects._forceRescan = true; + break; + default: + break; + } + } + } + + // Reset the list's changed flag + _changed = false; +} + +void DynamicHotspots::synchronize(Common::Serializer &s) { + int count = _entries.size(); + s.syncAsSint16LE(count); + + // The MIN in the below loop is a workaround to fix earlier savegame + // loading accidentally adding new dynamic hotspots to the fixed list + for (int i = 0; i < count; ++i) { + _entries[MIN(i, (int)_entries.size() - 1)].synchronize(s); + } +} + +/*------------------------------------------------------------------------*/ + +Hotspot::Hotspot() { + _facing = FACING_NONE; + _articleNumber = 0; + _cursor = CURSOR_NONE; + _vocabId = 0; + _verbId = 0; + _active = false; +} + +Hotspot::Hotspot(Common::SeekableReadStream &f, bool isV2) { + _bounds.left = f.readSint16LE(); + _bounds.top = f.readSint16LE(); + _bounds.right = f.readSint16LE(); + _bounds.bottom = f.readSint16LE(); + _feetPos.x = f.readSint16LE(); + _feetPos.y = f.readSint16LE(); + _facing = (Facing)f.readByte(); + _articleNumber = f.readByte(); + _active = f.readByte() != 0; + _cursor = (CursorType)f.readByte(); + if (isV2) { + // This looks to be some sort of bitmask. Perhaps it signifies + // the valid verbs for this hotspot + f.skip(2); // unknown + } + _vocabId = f.readUint16LE(); + _verbId = f.readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +void Hotspots::activate(int vocabId, bool active) { + for (uint idx = 0; idx < size(); ++idx) { + Hotspot &hotspot = (*this)[idx]; + if (hotspot._vocabId == vocabId) { + hotspot._active = active; + _vm->_game->_screenObjects.setActive(CAT_HOTSPOT, idx, active); + } + } +} + +} // End of namespace MADS diff --git a/engines/mads/hotspots.h b/engines/mads/hotspots.h new file mode 100644 index 0000000000..5fd910e1aa --- /dev/null +++ b/engines/mads/hotspots.h @@ -0,0 +1,114 @@ +/* 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 MADS_HOTSPOTS_H +#define MADS_HOTSPOTS_H + +#include "common/scummsys.h" +#include "mads/events.h" +#include "mads/player.h" + +namespace MADS { + +class MADSEngine; + +class DynamicHotspot { +public: + bool _active; + int _seqIndex; + Common::Rect _bounds; + Common::Point _feetPos; + Facing _facing; + int _descId; + int _verbId; + int _articleNumber; + CursorType _cursor; + + /** + * Constructor + */ + DynamicHotspot(); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +#define DYNAMIC_HOTSPOTS_SIZE 8 + +class DynamicHotspots { +private: + MADSEngine *_vm; + Common::Array<DynamicHotspot> _entries; + int _count; +public: + bool _changed; +public: + DynamicHotspots(MADSEngine *vm); + + Common::Array<MADS::DynamicHotspot>::size_type size() const { return _entries.size(); } + DynamicHotspot &operator[](uint idx) { return _entries[idx]; } + int add(int descId, int verbId, int seqIndex, const Common::Rect &bounds); + int setPosition(int index, const Common::Point &pos, Facing facing); + int setCursor(int index, CursorType cursor); + void remove(int index); + void clear(); + void reset(); + void refresh(); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +class Hotspot { +public: + Common::Rect _bounds; + Common::Point _feetPos; + Facing _facing; + int _articleNumber; + bool _active; + CursorType _cursor; + int _vocabId; + int _verbId; + + Hotspot(); + Hotspot(Common::SeekableReadStream &f, bool isV2); +}; + +class Hotspots : public Common::Array<Hotspot> { +private: + MADSEngine *_vm; +public: + Hotspots(MADSEngine *vm) : _vm(vm) {} + + /** + * Sets the active state of a given hotspot + */ + void activate(int vocabId, bool active); +}; + +} // End of namespace MADS + +#endif /* MADS_HOTSPOTS_H */ diff --git a/engines/mads/inventory.cpp b/engines/mads/inventory.cpp new file mode 100644 index 0000000000..b7864bc6a7 --- /dev/null +++ b/engines/mads/inventory.cpp @@ -0,0 +1,226 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/inventory.h" + +namespace MADS { + +void InventoryObject::synchronize(Common::Serializer &s) { + s.syncAsUint16LE(_descId); + s.syncAsUint16LE(_roomNumber); + s.syncAsByte(_article); + s.syncAsByte(_vocabCount); + s.syncAsByte(_qualitiesCount); + s.skip(1); + + for (int i = 0; i < MAX_VOCAB; ++i) { + s.syncAsUint16LE(_vocabList[i]._vocabId); + s.syncAsByte(_vocabList[i]._verbType); + s.syncAsByte(_vocabList[i]._prepType); + } + + for (int i = 0; i < MAX_QUALITIES; ++i) + s.syncAsByte(_qualityId[i]); + for (int i = 0; i < MAX_QUALITIES; ++i) + s.syncAsSint32LE(_qualityValue[i]); +} + +bool InventoryObject::hasQuality(int qualityId) const { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) + return true; + } + + return false; +} + +void InventoryObject::setQuality(int qualityId, int qualityValue) { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) { + _qualityValue[i] = qualityValue; + } + } +} + +int InventoryObject::getQuality(int qualityId) const { + for (int i = 0; i < _qualitiesCount; ++i) { + if (_qualityId[i] == qualityId) { + return _qualityValue[i]; + } + } + + return 0; +} + +/*------------------------------------------------------------------------*/ + +void InventoryObjects::load() { + File f("*OBJECTS.DAT"); + int count = f.readUint16LE(); + Common::Serializer s(&f, nullptr); + + // Load the objects data + reserve(count); + for (int i = 0; i < count; ++i) { + InventoryObject obj; + obj.synchronize(s); + push_back(obj); + + // If it's for the player's inventory, add the index to the inventory list + if (obj._roomNumber == PLAYER_INVENTORY) { + _inventoryList.push_back(i); + assert(_inventoryList.size() <= 32); + } + } +} + +void InventoryObjects::synchronize(Common::Serializer &s) { + int count = size(); + s.syncAsUint16LE(count); + + if (s.isSaving()) { + // Store the data for each object in the inventory lsit + for (int idx = 0; idx < count; ++idx) + (*this)[idx].synchronize(s); + + // Synchronize the player's inventory + _inventoryList.synchronize(s); + } else { + clear(); + + // Read in each object + reserve(count); + for (int i = 0; i < count; ++i) { + InventoryObject obj; + obj.synchronize(s); + push_back(obj); + } + + // Synchronize the player's inventory + _inventoryList.synchronize(s); + } +} + +void InventoryObjects::setRoom(int objectId, int sceneNumber) { + InventoryObject &obj = (*this)[objectId]; + + if (obj._roomNumber == PLAYER_INVENTORY) + removeFromInventory(objectId, 1); + + if (sceneNumber == PLAYER_INVENTORY) + addToInventory(objectId); + else + obj._roomNumber = sceneNumber; +} + +bool InventoryObjects::isInRoom(int objectId) const { + return objectId >= 0 && (*this)[objectId]._roomNumber == _vm->_game->_scene._currentSceneId; +} + +bool InventoryObjects::isInInventory(int objectId) const { + return objectId >= 0 && (*this)[objectId]._roomNumber == PLAYER_INVENTORY; +} + +void InventoryObjects::addToInventory(int objectId) { + assert(_inventoryList.size() < 32); + UserInterface &userInterface = _vm->_game->_scene._userInterface; + + if (!isInInventory(objectId)) { + _inventoryList.push_back(objectId); + userInterface._selectedInvIndex = _inventoryList.size() - 1; + userInterface._inventoryTopIndex = CLIP(userInterface._inventoryTopIndex, + 0, userInterface._selectedInvIndex); + + if ((userInterface._inventoryTopIndex + 5) <= (int)_inventoryList.size()) + userInterface._inventoryTopIndex = _inventoryList.size() - 5; + userInterface._inventoryChanged = true; + + (*this)[objectId]._roomNumber = PLAYER_INVENTORY; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + userInterface.categoryChanged(); + userInterface.selectObject(userInterface._selectedInvIndex); + } + } +} + +void InventoryObjects::removeFromInventory(int objectId, int newScene) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + // Scan the inventory list for the object + int invIndex = -1; + for (int idx = 0; idx < (int)_inventoryList.size() && invIndex == -1; ++idx) { + if (_inventoryList[idx] == objectId) + invIndex = idx; + } + + // If the object isn't in the player's inventory, stop here + if (invIndex < 0) + return; + + int selectedIndex = userInterface._selectedInvIndex; + bool noSelection = selectedIndex < 0; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) + userInterface.selectObject(-1); + + // Remove the item from the inventory list + _inventoryList.remove_at(invIndex); + + if (invIndex > userInterface._inventoryTopIndex) { + userInterface._inventoryTopIndex = MAX(userInterface._inventoryTopIndex, 0); + } + + userInterface._inventoryChanged = true; + (*this)[objectId]._roomNumber = newScene; + + int newIndex = selectedIndex; + if (!noSelection) { + if (newIndex >= invIndex) + --newIndex; + if (newIndex < 0 && size() > 0) + newIndex = 0; + } + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE && + _vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + userInterface.categoryChanged(); + userInterface.selectObject(newIndex); + } +} + +int InventoryObjects::getIdFromDesc(int descId) { + for (int i = 0; i < (int)size(); ++i) { + InventoryObject &obj = (*this)[i]; + if (obj._descId == descId) + return i; + } + + return -1; +} + +} // End of namespace MADS diff --git a/engines/mads/inventory.h b/engines/mads/inventory.h new file mode 100644 index 0000000000..09ed67a826 --- /dev/null +++ b/engines/mads/inventory.h @@ -0,0 +1,141 @@ +/* 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 MADS_INVENTORY_H +#define MADS_INVENTORY_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" + +namespace MADS { + +enum { + NOWHERE = 1 +}; + +class MADSEngine; + +#define MAX_VOCAB 5 +#define MAX_QUALITIES 4 + +class InventoryObject { +public: + int _descId; + int _roomNumber; + int _article; + int _vocabCount; + int _qualitiesCount; + int syntax; + + struct { + int _vocabId; + VerbType _verbType; + PrepType _prepType; + } _vocabList[MAX_VOCAB]; + + int _qualityId[MAX_QUALITIES]; + int _qualityValue[MAX_QUALITIES]; + + /** + * Synchronizes the data for a given object + */ + void synchronize(Common::Serializer &s); + + /** + * Returns true if the given object has the specified quality + */ + bool hasQuality(int qualityId) const; + + /** + * Sets the quality value for a given quality Id + */ + void setQuality(int qualityId, int qualityValue); + + /** + * Gets the quality value for a given quality Id + */ + int getQuality(int qualityId) const; +}; + +class InventoryObjects : public Common::Array<InventoryObject> { +private: + MADSEngine *_vm; + +public: + SynchronizedList _inventoryList; + + /** + * Constructor + */ + InventoryObjects(MADSEngine *vm) : _vm(vm) {} + + /** + * Loads the game's object list + */ + void load(); + + /** + * Synchronize the objects list in a savegame + */ + void synchronize(Common::Serializer &s); + + /** + * Returns the inventory item from the player's inventory + */ + InventoryObject &getItem(int itemIndex) { + return (*this)[_inventoryList[itemIndex]]; + } + + /** + * Sets an item's scene number + */ + void setRoom(int objectId, int sceneNumber); + + /** + * Returns true if a given object is in the player's current scene + */ + bool isInRoom(int objectId) const; + + /** + * Returns true if a given object is in the player's inventory + */ + bool isInInventory(int objectId) const; + + /** + * Removes the specified object from the player's inventory + */ + void addToInventory(int objectId); + + /** + * Removes the specified object to the player's inventory + * @param objectId Object to remove + * @param newScene Specifies the new scene to set the item to + */ + void removeFromInventory(int objectId, int newScene); + + int getIdFromDesc(int objectId); +}; + +} // End of namespace MADS + +#endif /* MADS_INVENTORY_H */ diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp new file mode 100644 index 0000000000..31e9b0dbe2 --- /dev/null +++ b/engines/mads/mads.cpp @@ -0,0 +1,157 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "common/debug-channels.h" +#include "common/events.h" +#include "engines/util.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sound.h" +#include "mads/sprites.h" + +namespace MADS { + +MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) : + _gameDescription(gameDesc), Engine(syst), _randomSource("MADS") { + + // Initialize fields + _easyMouse = true; + _invObjectsAnimated = true; + _textWindowStill = false; + _screenFade = SCREEN_FADE_SMOOTH; + _musicFlag = true; + _dithering = false; + + _debugger = nullptr; + _dialogs = nullptr; + _events = nullptr; + _font = nullptr; + _game = nullptr; + _palette = nullptr; + _resources = nullptr; + _sound = nullptr; + _audio = nullptr; +} + +MADSEngine::~MADSEngine() { + delete _debugger; + delete _dialogs; + delete _events; + delete _font; + Font::deinit(); + delete _game; + delete _palette; + delete _resources; + delete _sound; +} + +void MADSEngine::initialize() { + // Set up debug channels + DebugMan.addDebugChannel(kDebugPath, "Path", "Pathfinding debug level"); + DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts"); + DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics handling"); + + // Initial sub-system engine references + MSurface::setVm(this); + MSprite::setVm(this); + + Resources::init(this); + Conversation::init(this); + _debugger = new Debugger(this); + _dialogs = Dialogs::init(this); + _events = new EventsManager(this); + _palette = new Palette(this); + Font::init(this); + _font = new Font(); + _screen.init(); + _sound = new SoundManager(this, _mixer); + _audio = new AudioPlayer(_mixer, getGameID()); + _game = Game::init(this); + + _screen.empty(); +} + +Common::Error MADSEngine::run() { + initGraphics(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, false); + initialize(); + + // Run the game + _game->run(); + + // Dummy loop to keep application active + _events->delay(9999); + + return Common::kNoError; +} + +int MADSEngine::getRandomNumber(int maxNumber) { + return _randomSource.getRandomNumber(maxNumber); +} + +int MADSEngine::getRandomNumber(int minNumber, int maxNumber) { + int range = maxNumber - minNumber; + + return minNumber + _randomSource.getRandomNumber(range); +} + +int MADSEngine::hypotenuse(int xv, int yv) { + return (int)sqrt((double)(xv * xv + yv * yv)); +} + +bool MADSEngine::canLoadGameStateCurrently() { + return !_game->_winStatus && !_game->globals()[5] + && _dialogs->_pendingDialog == DIALOG_NONE + && _events->_cursorId != CURSOR_WAIT; +} + +bool MADSEngine::canSaveGameStateCurrently() { + return !_game->_winStatus && !_game->globals()[5] + && _dialogs->_pendingDialog == DIALOG_NONE + && _events->_cursorId != CURSOR_WAIT; +} + +/** +* Support method that generates a savegame name +* @param slot Slot number +*/ +Common::String MADSEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +Common::Error MADSEngine::loadGameState(int slot) { + _game->_loadGameSlot = slot; + _game->_scene._currentSceneId = -1; + _game->_currentSectionNumber = -1; + return Common::kNoError; +} + +Common::Error MADSEngine::saveGameState(int slot, const Common::String &desc) { + _game->saveGame(slot, desc); + return Common::kNoError; +} + +} // End of namespace MADS diff --git a/engines/mads/mads.h b/engines/mads/mads.h new file mode 100644 index 0000000000..9a8f2152a1 --- /dev/null +++ b/engines/mads/mads.h @@ -0,0 +1,152 @@ +/* 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 MADS_MADS_H +#define MADS_MADS_H + +#include "common/scummsys.h" +#include "common/system.h" +#include "common/error.h" +#include "common/random.h" +#include "common/util.h" +#include "engines/engine.h" +#include "graphics/surface.h" +#include "mads/debugger.h" +#include "mads/dialogs.h" +#include "mads/events.h" +#include "mads/font.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sound.h" + +/** + * This is the namespace of the MADS engine. + * + * Status of this engine: In Development + * + * Games using this engine: + * - Rex Nebular and the Cosmic Gender Bender + */ +namespace MADS { + +#define DEBUG_BASIC 1 +#define DEBUG_INTERMEDIATE 2 +#define DEBUG_DETAILED 3 + +enum MADSDebugChannels { + kDebugPath = 1 << 0, + kDebugScripts = 1 << 1, + kDebugGraphics = 1 << 2 +}; + +enum { + GType_RexNebular = 0, + GType_Dragonsphere = 1, + GType_Phantom = 2 +}; + +enum ScreenFade { + SCREEN_FADE_SMOOTH = 0, + SCREEN_FADE_MEDIUM = 1, + SCREEN_FADE_FAST = 2 +}; + +struct MADSGameDescription; + + +class MADSEngine : public Engine { +private: + const MADSGameDescription *_gameDescription; + Common::RandomSource _randomSource; + + /** + * Handles basic initialisation + */ + void initialize(); +protected: + // Engine APIs + virtual Common::Error run(); + virtual bool hasFeature(EngineFeature f) const; +public: + Debugger *_debugger; + Dialogs *_dialogs; + EventsManager *_events; + Font *_font; + Game *_game; + Palette *_palette; + Resources *_resources; + ScreenSurface _screen; + SoundManager *_sound; + AudioPlayer *_audio; + bool _easyMouse; + bool _invObjectsAnimated; + bool _textWindowStill; + ScreenFade _screenFade; + bool _musicFlag; + bool _dithering; +public: + MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc); + virtual ~MADSEngine(); + + uint32 getFeatures() const; + Common::Language getLanguage() const; + Common::Platform getPlatform() const; + uint16 getVersion() const; + uint32 getGameID() const; + uint32 getGameFeatures() const; + + int getRandomNumber(int maxNumber); + int getRandomNumber(int minNumber, int maxNumber); + int hypotenuse(int xv, int yv); + + /** + * Returns true if it is currently okay to restore a game + */ + bool canLoadGameStateCurrently(); + + /** + * Returns true if it is currently okay to save the game + */ + bool canSaveGameStateCurrently(); + + /** + * Support method that generates a savegame name + * @param slot Slot number + */ + Common::String generateSaveName(int slot); + + /** + * Handles loading a game via the GMM + */ + virtual Common::Error loadGameState(int slot); + + /** + * Handles saving the game via the GMM + */ + virtual Common::Error saveGameState(int slot, const Common::String &desc); +}; + +} // End of namespace MADS + +#endif /* MADS_MADS_H */ diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp new file mode 100644 index 0000000000..9b2d6f3114 --- /dev/null +++ b/engines/mads/messages.cpp @@ -0,0 +1,570 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/font.h" +#include "mads/screen.h" +#include "mads/messages.h" +#include "mads/scene_data.h" + +namespace MADS { + +RandomMessages::RandomMessages() { + reserve(RANDOM_MESSAGE_SIZE); + _randomSpacing = 0; + _color = -1; + _duration = 0; + _scrollRate = -1; +} + +void RandomMessages::reset() { + for (uint i = 0; i < size(); ++i) { + (*this)[i]._handle = -1; + (*this)[i]._quoteId = -1; + } +} + + +KernelMessages::KernelMessages(MADSEngine *vm) + : _vm(vm) { + for (int i = 0; i < KERNEL_MESSAGES_SIZE; ++i) { + KernelMessage rec; + _entries.push_back(rec); + } + + _talkFont = _vm->_font->getFont(FONT_CONVERSATION); +} + +KernelMessages::~KernelMessages() { +} + +void KernelMessages::clear() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < _entries.size(); ++i) + _entries[i]._flags = 0; + + _talkFont = _vm->_font->getFont(FONT_CONVERSATION); + scene._textSpacing = -1; +} + +int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, + uint8 abortTimers, uint32 timeout, const Common::String &msg) { + Scene &scene = _vm->_game->_scene; + + // Find a free slot + uint idx = 0; + while ((idx < _entries.size()) && ((_entries[idx]._flags & KMSG_ACTIVE) != 0)) + ++idx; + if (idx == _entries.size()) { + if (abortTimers == 0) + return -1; + + error("KernelMessages overflow"); + } + + KernelMessage &rec = _entries[idx]; + rec._msg = msg; + rec._flags = flags | KMSG_ACTIVE; + rec._color1 = fontColor & 0xff; + rec._color2 = fontColor >> 8; + rec._position = pt; + rec._textDisplayIndex = -1; + rec._timeout = timeout; + rec._frameTimer = _vm->_game->_priorFrameTimer; + rec._trigger = abortTimers; + rec._abortMode = _vm->_game->_triggerSetupMode; + + rec._actionDetails = scene._action._activeAction; + + if (flags & KMSG_PLAYER_TIMEOUT) + rec._frameTimer = _vm->_game->_player._ticksAmount + + _vm->_game->_player._priorTimer; + + return idx; +} + +int KernelMessages::addQuote(int quoteId, int abortTimers, uint32 timeout) { + Common::String quoteStr = _vm->_game->getQuote(quoteId); + return add(Common::Point(), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, + abortTimers, timeout, quoteStr); +} + +void KernelMessages::scrollMessage(int msgIndex, int numTicks, bool quoted) { + if (msgIndex < 0) + return; + + _entries[msgIndex]._flags |= quoted ? (KMSG_SCROLL | KMSG_QUOTED) : KMSG_SCROLL; + _entries[msgIndex]._msgOffset = 0; + _entries[msgIndex]._numTicks = numTicks; + _entries[msgIndex]._frameTimer2 = _vm->_game->_priorFrameTimer; + + Common::String msg = _entries[msgIndex]._msg; + + if (_entries[msgIndex]._flags & KMSG_PLAYER_TIMEOUT) + _entries[msgIndex]._frameTimer2 = _vm->_game->_player._ticksAmount + + _vm->_game->_player._priorTimer; + + _entries[msgIndex]._frameTimer = _entries[msgIndex]._frameTimer2; +} + +void KernelMessages::setSeqIndex(int msgIndex, int seqIndex) { + if (msgIndex >= 0) { + _entries[msgIndex]._flags |= KMSG_SEQ_ENTRY; + _entries[msgIndex]._sequenceIndex = seqIndex; + } +} + +void KernelMessages::remove(int msgIndex) { + KernelMessage &rec = _entries[msgIndex]; + Scene &scene = _vm->_game->_scene; + + if (rec._flags & KMSG_ACTIVE) { + if (rec._flags & KMSG_SCROLL) { + // WORKAROUND: Code here no longer needed in ScummVM + } + + if (rec._textDisplayIndex >= 0) + scene._textDisplay.expire(rec._textDisplayIndex); + + rec._flags &= ~KMSG_ACTIVE; + } +} + +void KernelMessages::reset() { + for (uint i = 0; i < _entries.size(); ++i) + remove(i); + + _randomMessages.clear(); +} + +void KernelMessages::update() { + uint32 currentTimer = _vm->_game->_scene._frameStartTime; + + for (uint i = 0; i < _entries.size() && !_vm->_game->_trigger; ++i) { + KernelMessage &msg = _entries[i]; + + if (((msg._flags & KMSG_ACTIVE) != 0) && (currentTimer >= msg._frameTimer)) + processText(i); + } +} + +void KernelMessages::processText(int msgIndex) { + Scene &scene = _vm->_game->_scene; + KernelMessage &msg = _entries[msgIndex]; + uint32 currentTimer = _vm->_game->_priorFrameTimer; + bool flag = false; + + if ((msg._flags & KMSG_EXPIRE) != 0) { + scene._textDisplay.expire(msg._textDisplayIndex); + msg._flags &= ~KMSG_ACTIVE; + return; + } + + if ((msg._flags & KMSG_SCROLL) == 0) { + msg._timeout -= 3; + } + + if (msg._flags & KMSG_SEQ_ENTRY) { + SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex]; + if (seqEntry._doneFlag || !seqEntry._active) + msg._timeout = 0; + } + + if ((msg._timeout <= 0) && (_vm->_game->_trigger == 0)) { + msg._flags |= KMSG_EXPIRE; + if (msg._trigger != 0) { + _vm->_game->_trigger = msg._trigger; + _vm->_game->_triggerMode = msg._abortMode; + + if (_vm->_game->_triggerMode != SEQUENCE_TRIGGER_DAEMON) { + scene._action._activeAction = msg._actionDetails; + } + } + } + + msg._frameTimer = currentTimer + 3; + int x1 = 0, y1 = 0; + + if (msg._flags & KMSG_SEQ_ENTRY) { + SequenceEntry &seqEntry = scene._sequences[msg._sequenceIndex]; + if (!seqEntry._nonFixed) { + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1); + x1 = frame->getBounds().left; + y1 = frame->getBounds().top; + } else { + x1 = seqEntry._position.x; + y1 = seqEntry._position.y; + } + } + + Player &player = _vm->_game->_player; + if (msg._flags & KMSG_PLAYER_TIMEOUT) { + if (player._beenVisible) { + SpriteAsset &asset = *_vm->_game->_scene._sprites[player._spritesStart + player._spritesIdx]; + MSprite *frame = asset.getFrame(player._frameNumber - 1); + + int yAmount = player._currentScale * player._centerOfGravity / 100; + x1 = player._playerPos.x; + y1 = (frame->h * player._currentScale / -100) + yAmount + + player._playerPos.y - 15; + } else { + x1 = 160; + y1 = 78; + } + } + + x1 += msg._position.x; + y1 += msg._position.y; + + Common::String displayMsg = msg._msg; + + if ((msg._flags & KMSG_SCROLL) && (msg._frameTimer >= currentTimer)) { + ++msg._msgOffset; + + if (msg._msgOffset >= msg._msg.size()) { + // End of message + msg._flags &= ~KMSG_SCROLL; + } else { + displayMsg = Common::String(msg._msg.c_str(), msg._msg.c_str() + msg._msgOffset); + } + + msg._frameTimer = msg._frameTimer2 = currentTimer + msg._numTicks; + flag = true; + } + + int strWidth = _talkFont->getWidth(displayMsg, scene._textSpacing); + + if (msg._flags & (KMSG_RIGHT_ALIGN | KMSG_CENTER_ALIGN)) { + x1 -= (msg._flags & KMSG_CENTER_ALIGN) ? strWidth / 2 : strWidth; + } + + // Make sure text appears entirely on-screen + int x2 = x1 + strWidth; + if (x2 > MADS_SCREEN_WIDTH) + x1 -= x2 - MADS_SCREEN_WIDTH; + if (x1 > (MADS_SCREEN_WIDTH - 1)) + x1 = MADS_SCREEN_WIDTH - 1; + if (x1 < 0) + x1 = 0; + + if (y1 >(MADS_SCENE_HEIGHT - 1)) + y1 = MADS_SCENE_HEIGHT - 1; + if (y1 < 0) + y1 = 0; + + if (msg._textDisplayIndex >= 0) { + TextDisplay &textEntry = scene._textDisplay[msg._textDisplayIndex]; + + if (flag || (textEntry._bounds.left != x1) || (textEntry._bounds.top != y1)) { + // Mark the associated text entry as deleted, so it can be re-created + scene._textDisplay.expire(msg._textDisplayIndex); + msg._textDisplayIndex = -1; + } + } + + if (msg._textDisplayIndex < 0) { + // Need to create a new text display entry for this message + int idx = scene._textDisplay.add(x1, y1, msg._color1 | (msg._color2 << 8), + scene._textSpacing, displayMsg, _talkFont); + if (idx >= 0) + msg._textDisplayIndex = idx; + } +} + +void KernelMessages::delay(uint32 priorFrameTime, uint32 currentTime) { + for (uint i = 0; i < _entries.size(); ++i) { + _entries[i]._timeout += currentTime - priorFrameTime; + } +} + +void KernelMessages::setQuoted(int msgIndex, int numTicks, bool quoted) { + if (msgIndex >= 0) { + KernelMessage &msg = _entries[msgIndex]; + + msg._flags |= KMSG_SCROLL; + if (quoted) + msg._flags |= KMSG_QUOTED; + + msg._msgOffset = 0; + msg._numTicks = numTicks; + msg._frameTimer2 = _vm->_game->_scene._frameStartTime; + + if (msg._flags & KMSG_PLAYER_TIMEOUT) { + msg._frameTimer2 = _vm->_game->_player._priorTimer + + _vm->_game->_player._ticksAmount; + } + + msg._frameTimer = msg._frameTimer2; + } +} + +#define RANDOM_MESSAGE_TRIGGER 240 + +void KernelMessages::randomServer() { + if ((_vm->_game->_trigger >= RANDOM_MESSAGE_TRIGGER) && + (_vm->_game->_trigger < (RANDOM_MESSAGE_TRIGGER + (int)_randomMessages.size()))) { + _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._handle = -1; + _randomMessages[_vm->_game->_trigger - RANDOM_MESSAGE_TRIGGER]._quoteId = -1; + } +} + +int KernelMessages::checkRandom() { + int total = 0; + + for (uint i = 0; i < _randomMessages.size(); ++i) { + if (_randomMessages[i]._handle >= 0) + ++total; + } + + return total; +} + +bool KernelMessages::generateRandom(int major, int minor) { + bool generatedMessage = false; + + // Scan through the random messages array + for (uint msgCtr = 0; msgCtr < _randomMessages.size(); msgCtr++) { + // Find currently active random messages + if (_randomMessages[msgCtr]._handle < 0) { + // Check whether there's any existing 'scrolling in' message + bool bad = false; + for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) { + if (_randomMessages[scanCtr]._handle >= 0) { + if (_entries[_randomMessages[scanCtr]._handle]._flags & KMSG_SCROLL) { + bad = true; + break; + } + } + } + + // Do a random check for a new message to appear + if (_vm->getRandomNumber(major) <= minor && !bad) { + int quoteId; + + // Pick a random quote to display from the available list + do { + int quoteIdx = _vm->getRandomNumber(_randomQuotes.size() - 1); + quoteId = _randomQuotes[quoteIdx]; + + // Ensure the quote isn't already in use + bad = false; + for (uint scanCtr = 0; scanCtr < _randomMessages.size(); ++scanCtr) { + if (quoteId == _randomMessages[scanCtr]._quoteId) { + bad = true; + break; + } + } + } while (bad); + + // Store the quote Id to be used + _randomMessages[msgCtr]._quoteId = quoteId; + + // Position the message at a random position + Common::Point textPos; + textPos.x = _vm->getRandomNumber(_randomMessages._bounds.left, + _randomMessages._bounds.right); + + // Figure out Y position, making sure not to be overlapping with + // any other on-screen message + int abortCounter = 0; + + do { + // Ensure we don't get stuck in an infinite loop if too many messages + // are alrady on-screen + if (abortCounter++ > 100) goto done; + bad = false; + + // Set potential new Y position + textPos.y = _vm->getRandomNumber(_randomMessages._bounds.top, + _randomMessages._bounds.bottom); + + // Ensure it doesn't overlap an existing on-screen message + for (uint msgCtr2 = 0; msgCtr2 < _randomMessages.size(); ++msgCtr2) { + if (_randomMessages[msgCtr2]._handle >= 0) { + int lastY = _entries[_randomMessages[msgCtr2]._handle]._position.y; + + if ((textPos.y >= (lastY - _randomMessages._randomSpacing)) && + (textPos.y <= (lastY + _randomMessages._randomSpacing))) { + bad = true; + } + } + } + } while (bad); + + // Add the message + _randomMessages[msgCtr]._handle = add(textPos, _randomMessages._color, 0, + RANDOM_MESSAGE_TRIGGER + msgCtr, _randomMessages._duration, + _vm->_game->getQuote(_randomMessages[msgCtr]._quoteId)); + + if (_randomMessages._scrollRate > 0) { + if (_randomMessages[msgCtr]._handle >= 0) { + setQuoted(_randomMessages[msgCtr]._handle, + _randomMessages._scrollRate, true); + } + } + + generatedMessage = true; + break; + } + } + } + +done: + return generatedMessage; +} + +void KernelMessages::initRandomMessages(int maxSimultaneousMessages, + const Common::Rect &bounds, int minYSpacing, int scrollRate, + int color, int duration, int quoteId, ...) { + // Reset the random messages list + _randomMessages.clear(); + _randomMessages.resize(maxSimultaneousMessages); + + // Store passed parameters + _randomMessages._bounds = bounds; + _randomMessages._randomSpacing = minYSpacing; + _randomMessages._scrollRate = scrollRate; + _randomMessages._color = color; + _randomMessages._duration = duration; + + // Store the variable length random quote list + va_list va; + va_start(va, quoteId); + _randomQuotes.clear(); + + while (quoteId > 0) { + _randomQuotes.push_back(quoteId); + assert(_randomQuotes.size() < 100); + quoteId = va_arg(va, int); + } + + va_end(va); +} + + +/*------------------------------------------------------------------------*/ + +TextDisplay::TextDisplay() { + _active = false; + _expire = 0; + _spacing = 0; + _color1 = 0; + _color2 = 0; + _font = nullptr; +} + +/*------------------------------------------------------------------------*/ + +TextDisplayList::TextDisplayList(MADSEngine *vm) : _vm(vm) { + for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) { + TextDisplay rec; + rec._active = false; + rec._expire = 0; + push_back(rec); + } +} + +void TextDisplayList::reset() { + for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) + (*this)[i]._active = false; +} + +int TextDisplayList::add(int xp, int yp, uint fontColor, int charSpacing, + const Common::String &msg, Font *font) { + int usedSlot = -1; + + for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { + TextDisplay &td = (*this)[idx]; + if (!td._active) { + usedSlot = idx; + + td._bounds.left = xp; + td._bounds.top = yp; + td._font = font; + td._msg = msg; + td._bounds.setWidth(font->getWidth(msg, charSpacing)); + td._bounds.setHeight(font->getHeight()); + td._color1 = fontColor & 0xff; + td._color2 = fontColor >> 8; + td._spacing = charSpacing; + td._expire = 1; + td._active = true; + break; + } + } + + return usedSlot; +} + +void TextDisplayList::setDirtyAreas() { + Scene &scene = _vm->_game->_scene; + + for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; dirtyIdx < size(); ++idx, ++dirtyIdx) { + if (((*this)[idx]._expire >= 0) || !(*this)[idx]._active) { + scene._dirtyAreas[dirtyIdx]._active = false; + } else { + scene._dirtyAreas[dirtyIdx]._textActive = true; + scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]); + } + } +} + +void TextDisplayList::setDirtyAreas2() { + Scene &scene = _vm->_game->_scene; + + for (uint idx = 0, dirtyIdx = SPRITE_SLOTS_MAX_SIZE; idx < size(); ++idx, ++dirtyIdx) { + if ((*this)[idx]._active && ((*this)[idx]._expire >= 0)) { + scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]); + scene._dirtyAreas[dirtyIdx]._textActive = ((*this)[idx]._expire <= 0) ? 0 : 1; + } + } +} + +void TextDisplayList::draw(MSurface *s) { + for (uint idx = 0; idx < size(); ++idx) { + TextDisplay &td = (*this)[idx]; + if (td._active && (td._expire >= 0)) { + td._font->setColors(0xFF, td._color1, td._color2, 0); + td._font->writeString(s, td._msg, + Common::Point(td._bounds.left, td._bounds.top), + td._spacing, td._bounds.width()); + } + } +} + +void TextDisplayList::cleanUp() { + for (uint idx = 0; idx < size(); ++idx) { + if ((*this)[idx]._expire < 0) { + (*this)[idx]._active = false; + (*this)[idx]._expire = 0; + } + } +} + +void TextDisplayList::expire(int idx) { + (*this)[idx]._expire = -1; +} + +} // End of namespace MADS diff --git a/engines/mads/messages.h b/engines/mads/messages.h new file mode 100644 index 0000000000..a7411d98d1 --- /dev/null +++ b/engines/mads/messages.h @@ -0,0 +1,192 @@ +/* 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 MADS_MESSAGES_H +#define MADS_MESSAGES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/action.h" +#include "mads/font.h" +#include "mads/msurface.h" + +namespace MADS { + +#define KERNEL_MESSAGES_SIZE 10 +#define INDEFINITE_TIMEOUT 9999999 +#define TEXT_DISPLAY_SIZE 40 +#define RANDOM_MESSAGE_SIZE 4 + +enum KernelMessageFlags { + KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, + KMSG_RIGHT_ALIGN = 0x10, KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, + KMSG_ACTIVE = 0x80 +}; + +class MADSEngine; + +class KernelMessage { +public: + uint8 _flags; + int _sequenceIndex; + int _color1; + int _color2; + Common::Point _position; + int _textDisplayIndex; + uint32 _msgOffset; + int _numTicks; + uint32 _frameTimer2; + uint32 _frameTimer; + int32 _timeout; + int _trigger; + TriggerMode _abortMode; + ActionDetails _actionDetails; + Common::String _msg; + + KernelMessage(); +}; + +struct RandomEntry { + int _handle; + int _quoteId; + + RandomEntry() { _handle = _quoteId = -1; } +}; + +class RandomMessages : public Common::Array<RandomEntry> { +public: + Common::Rect _bounds; + int _randomSpacing; + int _color; + int _duration; + int _scrollRate; +public: + RandomMessages(); + + void reset(); +}; + +class KernelMessages { +private: + MADSEngine *_vm; + + Common::Array<int> _randomQuotes; + RandomMessages _randomMessages; +public: + Common::Array<KernelMessage> _entries; + Font *_talkFont; +public: + KernelMessages(MADSEngine *vm); + ~KernelMessages(); + + void clear(); + int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, + uint32 timeout, const Common::String &msg); + int addQuote(int quoteId, int abortTimers, uint32 timeout); + void scrollMessage(int msgIndex, int numTicks, bool quoted); + void setSeqIndex(int msgIndex, int seqIndex); + void remove(int msgIndex); + void reset(); + void update(); + void processText(int msgIndex); + void delay(uint32 priorFrameTime, uint32 currentTime); + void setQuoted(int msgIndex, int numTicks, bool quoted); + + void initRandomMessages(int maxSimultaneousMessages, + const Common::Rect &bounds, int minYSpacing, int scrollRate, + int color, int duration, int quoteId, ...); + + /** + * Handles expiring any active random messages as necessary + */ + void randomServer(); + + /** + * Return the number of currently active random messages + */ + int checkRandom(); + + /** + * Handles generating new random messages + */ + bool generateRandom(int major, int minor); +}; + +class TextDisplay { +public: + bool _active; + int _expire; + int _spacing; + Common::Rect _bounds; + uint8 _color1; + uint8 _color2; + Font *_font; + Common::String _msg; + + TextDisplay(); +}; + +#define TEXT_DISPLAY_SIZE 40 + +class TextDisplayList : public Common::Array<TextDisplay> { +private: + MADSEngine *_vm; +public: + TextDisplayList(MADSEngine *vm); + + /** + * Expire a given text display entry + */ + void expire(int idx); + + int add(int xp, int yp, uint fontColor, int charSpacing, const Common::String &, Font *font); + + /** + * Reset all of the text display entries in the list to inactive + */ + void reset(); + + /** + * Draw any text in the list to the specified surface + * @param surface Surface + */ + void draw(MSurface *s); + + /** + * Determine dirty areas for active text areas + */ + void setDirtyAreas(); + + /** + * Secondary setup dirty areas for the text areas + */ + void setDirtyAreas2(); + + /** + * Deactivates any text display entries that are finished + */ + void cleanUp(); +}; + +} // End of namespace MADS + +#endif /* MADS_MESSAGES_H */ diff --git a/engines/mads/module.mk b/engines/mads/module.mk new file mode 100644 index 0000000000..61e810e215 --- /dev/null +++ b/engines/mads/module.mk @@ -0,0 +1,58 @@ +MODULE := engines/mads + +MODULE_OBJS := \ + dragonsphere/game_dragonsphere.o \ + dragonsphere/dragonsphere_scenes.o \ + phantom/game_phantom.o \ + phantom/phantom_scenes.o \ + nebular/dialogs_nebular.o \ + nebular/game_nebular.o \ + nebular/globals_nebular.o \ + nebular/sound_nebular.o \ + nebular/nebular_scenes.o \ + nebular/nebular_scenes1.o \ + nebular/nebular_scenes2.o \ + nebular/nebular_scenes3.o \ + nebular/nebular_scenes4.o \ + nebular/nebular_scenes5.o \ + nebular/nebular_scenes6.o \ + nebular/nebular_scenes7.o \ + nebular/nebular_scenes8.o \ + action.o \ + animation.o \ + assets.o \ + audio.o \ + compression.o \ + debugger.o \ + detection.o \ + dialogs.o \ + events.o \ + font.o \ + game.o \ + game_data.o \ + globals.o \ + hotspots.o \ + inventory.o \ + mads.o \ + messages.o \ + msurface.o \ + palette.o \ + player.o \ + rails.o \ + resources.o \ + scene.o \ + scene_data.o \ + screen.o \ + sequence.o \ + sound.o \ + sprites.o \ + staticres.o \ + user_interface.o + +# This module can be built as a plugin +ifeq ($(ENABLE_MADS), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp new file mode 100644 index 0000000000..839882a354 --- /dev/null +++ b/engines/mads/msurface.cpp @@ -0,0 +1,572 @@ +/* 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 "engines/util.h" +#include "mads/compression.h" +#include "mads/screen.h" +#include "mads/mads.h" +#include "mads/msurface.h" +#include "mads/resources.h" +#include "mads/sprites.h" + +namespace MADS { + +MADSEngine *MSurface::_vm = nullptr; + +MSurface::MSurface() { + pixels = nullptr; + _freeFlag = false; +} + +MSurface::MSurface(int width, int height) { + pixels = nullptr; + _freeFlag = false; + setSize(width, height); +} + +MSurface::~MSurface() { + if (_freeFlag) + Graphics::Surface::free(); +} + +void MSurface::setSize(int width, int height) { + if (_freeFlag) + Graphics::Surface::free(); + Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + _freeFlag = true; +} + +void MSurface::setPixels(byte *pData, int horizSize, int vertSize) { + _freeFlag = false; + pixels = pData; + w = pitch = horizSize; + h = vertSize; + format.bytesPerPixel = 1; +} + +int MSurface::scaleValue(int value, int scale, int err) { + int scaled = 0; + while (value--) { + err -= scale; + while (err < 0) { + scaled++; + err += 100; + } + } + return scaled; +} + +void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect) { + + enum { + kStatusSkip, + kStatusScale, + kStatusDraw + }; + + // NOTE: The current clipping code assumes that the top left corner of the clip + // rectangle is always 0, 0 + assert(clipRect.top == 0 && clipRect.left == 0); + + // TODO: Put err* and scaled* into SpriteInfo + int errX = info.hotX * info.scaleX % 100; + int errY = info.hotY * info.scaleY % 100; + int scaledWidth = scaleValue(info.width, info.scaleX, errX); + int scaledHeight = scaleValue(info.height, info.scaleY, errY); + + int x = pt.x, y = pt.y; + int clipX = 0, clipY = 0; + // Clip the sprite's width and height according to the clip rectangle's dimensions + // This clips the sprite to the bottom and right + if (x >= 0) { + scaledWidth = MIN<int>(x + scaledWidth, clipRect.right) - x; + } else { + clipX = x; + scaledWidth = x + scaledWidth; + } + if (y >= 0) { + scaledHeight = MIN<int>(y + scaledHeight, clipRect.bottom) - y; + } else { + clipY = y; + scaledHeight = y + scaledHeight; + } + + // Check if sprite is inside the screen. If it's not, there's no need to draw it + if (scaledWidth + x <= 0 || scaledHeight + y <= 0) // check left and top (in case x,y are negative) + return; + if (scaledWidth <= 0 || scaledHeight <= 0) // check right and bottom + return; + int heightAmt = scaledHeight; + + byte *src = info.sprite->getData(); + byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY); + + int status = kStatusSkip; + byte *scaledLineBuf = new byte[scaledWidth]; + + while (heightAmt > 0) { + + if (status == kStatusSkip) { + // Skip line + errY -= info.scaleY; + if (errY < 0) + status = kStatusScale; + else + src += info.width; + } else { + + if (status == kStatusScale) { + // Scale current line + byte *lineDst = scaledLineBuf; + int curErrX = errX; + int width = scaledWidth; + byte *tempSrc = src; + int startX = clipX; + while (width > 0) { + byte pixel = *tempSrc++; + curErrX -= info.scaleX; + while (curErrX < 0) { + if (startX == 0) { + *lineDst++ = pixel; + width--; + } else { + startX++; + } + curErrX += 100; + } + } + src += info.width; + status = kStatusDraw; + } + + if (status == kStatusDraw && clipY == 0) { + // Draw previously scaled line + // TODO Implement different drawing types (depth, shadow etc.) + byte *tempDst = dst; + for (int lineX = 0; lineX < scaledWidth; lineX++) { + byte pixel = scaledLineBuf[lineX]; + + if (info.encoding & 0x80) { + + if (pixel == 0x80) { + pixel = 0; + } else { + byte destPixel = *tempDst; + byte r, g, b; + r = CLIP((info.palette[destPixel * 3] * pixel) >> 10, 0, 31); + g = CLIP((info.palette[destPixel * 3 + 1] * pixel) >> 10, 0, 31); + b = CLIP((info.palette[destPixel * 3 + 2] * pixel) >> 10, 0, 31); + pixel = info.inverseColorTable[(b << 10) | (g << 5) | r]; + } + } + + if (pixel) + *tempDst = pixel; + + tempDst++; + } + dst += pitch; + heightAmt--; + // TODO depth etc. + //depthAddress += Destination -> Width; + + errY += 100; + if (errY >= 0) + status = kStatusSkip; + } else if (status == kStatusDraw && clipY < 0) { + clipY++; + + errY += 100; + if (errY >= 0) + status = kStatusSkip; + } + + } + + } + + delete[] scaledLineBuf; + +} + +void MSurface::empty() { + Common::fill(getBasePtr(0, 0), getBasePtr(0, h), 0); +} + +void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds, + const Common::Point &destPos, int transparentColor) { + // Validation of the rectangle and position + int destX = destPos.x, destY = destPos.y; + if ((destX >= w) || (destY >= h)) + return; + + Common::Rect copyRect = srcBounds; + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + // Copy the specified area + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)pixels + (destY * getWidth()) + destX; + + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + if (transparentColor == -1) { + // No transparency, so copy line over + Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr); + } else { + // Copy each byte one at a time checking for the transparency color + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) + if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } +} + +void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth, + DepthSurface *depthSurface, int scale, int transparentColor) { + + int destX = destPos.x, destY = destPos.y; + if (scale == 100) { + // Copy the specified area + Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight()); + + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } + else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } + else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)pixels + (destY * pitch) + destX; + + // 100% scaling variation + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + // Copy each byte one at a time checking against the depth + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) { + int pixelDepth = depthSurface == nullptr ? 15 : + depthSurface->getDepth(Common::Point(destX + xCtr, destY + rowCtr)); + if ((depth <= pixelDepth) && (srcPtr[xCtr] != transparentColor)) + destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } + + return; + } + + // Start of draw logic for scaled sprites + const byte *srcPixelsP = src->getData(); + + int destRight = this->getWidth() - 1; + int destBottom = this->getHeight() - 1; + bool normalFrame = true; + int frameWidth = src->getWidth(); + int frameHeight = src->getHeight(); + + int highestDim = MAX(frameWidth, frameHeight); + bool lineDist[MADS_SCREEN_WIDTH]; + int distIndex = 0; + int distXCount = 0, distYCount = 0; + + int distCtr = 0; + do { + distCtr += scale; + if (distCtr < 100) { + lineDist[distIndex] = false; + } else { + lineDist[distIndex] = true; + distCtr -= 100; + + if (distIndex < frameWidth) + ++distXCount; + + if (distIndex < frameHeight) + ++distYCount; + } + } while (++distIndex < highestDim); + + destX -= distXCount / 2; + destY -= distYCount - 1; + + // Check x bounding area + int spriteLeft = 0; + int spriteWidth = distXCount; + int widthAmount = destX + distXCount - 1; + + if (destX < 0) { + spriteWidth += destX; + spriteLeft -= destX; + } + widthAmount -= destRight; + if (widthAmount > 0) + spriteWidth -= widthAmount; + + int spriteRight = spriteLeft + spriteWidth; + if (spriteWidth <= 0) + return; + if (!normalFrame) { + destX += distXCount - 1; + spriteLeft = -(distXCount - spriteRight); + spriteRight = (-spriteLeft + spriteWidth); + } + + // Check y bounding area + int spriteTop = 0; + int spriteHeight = distYCount; + int heightAmount = destY + distYCount - 1; + + if (destY < 0) { + spriteHeight += destY; + spriteTop -= destY; + } + heightAmount -= destBottom; + if (heightAmount > 0) + spriteHeight -= heightAmount; + int spriteBottom = spriteTop + spriteHeight; + + if (spriteHeight <= 0) + return; + + byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); + + spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); + + // Loop through the lines of the sprite + for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) { + if (!lineDist[yp]) + // Not a display line, so skip it + continue; + // Check whether the sprite line is in the display range + ++sprY; + if ((sprY >= spriteBottom) || (sprY < spriteTop)) + continue; + + // Found a line to display. Loop through the pixels + const byte *srcP = srcPixelsP; + byte *destP = destPixelsP; + + for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { + if (xp < spriteLeft) + // Not yet reached start of display area + continue; + if (!lineDist[sprX++]) + // Not a display pixel + continue; + + // Get depth of current output pixel in depth surface + Common::Point pt((destP - (byte *)this->pixels) % this->pitch, + (destP - (byte *)this->pixels) / this->pitch); + int pixelDepth = (depthSurface == nullptr) ? 15 : depthSurface->getDepth(pt); + + if ((*srcP != transparentColor) && (depth <= pixelDepth)) + *destP = *srcP; + + ++destP; + } + + // Move to the next destination line + destPixelsP += this->pitch; + } +} + +void MSurface::copyFromScaled(MSurface *src, const Common::Point &destPos, int depth, + DepthSurface *depthSurface, int scale, int transparentColor) { + int distXCount = 0, distYCount = 0; + int highestDim = MAX(src->w, src->h); + int accum = 0; + + for (int idx = 0; idx < highestDim; ++idx) { + accum += scale; + if (accum >= 100) { + accum -= 100; + if (idx < src->w) + ++distXCount; + if (idx < src->h) + ++distYCount; + } + } + + Common::Point newPos(destPos.x - distXCount / 2, destPos.y - distYCount); + copyFrom(src, src->getBounds(), newPos, transparentColor); +} + +void MSurface::scrollX(int xAmount) { + if (xAmount == 0) + return; + + byte buffer[80]; + int direction = (xAmount > 0) ? -1 : 1; + int xSize = ABS(xAmount); + assert(xSize <= 80); + + byte *srcP = getBasePtr(0, 0); + + for (int y = 0; y < this->h; ++y, srcP += pitch) { + if (direction < 0) { + // Copy area to be overwritten + Common::copy(srcP, srcP + xSize, &buffer[0]); + // Shift the remainder of the line over the given area + Common::copy(srcP + xSize, srcP + this->w, srcP); + // Move buffered area to the end of the line + Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize); + } else { + // Copy area to be overwritten + Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]); + // Shift the remainder of the line over the given area + Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w); + // Move buffered area to the start of the line + Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize); + } + } +} + +void MSurface::scrollY(int yAmount) { + if (yAmount == 0) + return; + + int direction = (yAmount > 0) ? 1 : -1; + int ySize = ABS(yAmount); + assert(ySize < (this->h / 2)); + assert(this->w == pitch); + + int blockSize = ySize * this->w; + byte *tempData = new byte[blockSize]; + byte *pixelsP = getBasePtr(0, 0); + + if (direction > 0) { + // Buffer the lines to be overwritten + byte *srcP = (byte *)getBasePtr(0, this->h - ySize); + Common::copy(srcP, srcP + (pitch * ySize), tempData); + // Vertically shift all the lines + Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)), + pixelsP + (pitch * this->h)); + // Transfer the buffered lines top the top of the screen + Common::copy(tempData, tempData + blockSize, pixelsP); + } else { + // Buffer the lines to be overwritten + Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData); + // Vertically shift all the lines + Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP); + // Transfer the buffered lines to the bottom of the screen + Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize))); + } + + delete[] tempData; +} + + +void MSurface::translate(Common::Array<RGB6> &palette) { + for (int y = 0; y < this->h; ++y) { + byte *pDest = getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x, ++pDest) { + if (*pDest < 255) // scene 752 has some palette indices of 255 + *pDest = palette[*pDest]._palIndex; + } + } +} + +void MSurface::translate(byte map[PALETTE_COUNT]) { + for (int y = 0; y < this->h; ++y) { + byte *pDest = getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x, ++pDest) { + *pDest = map[*pDest]; + } + } +} + +MSurface *MSurface::flipHorizontal() const { + MSurface *dest = new MSurface(this->w, this->h); + + for (int y = 0; y < this->h; ++y) { + const byte *srcP = getBasePtr(this->w - 1, y); + byte *destP = dest->getBasePtr(0, y); + + for (int x = 0; x < this->w; ++x) + *destP++ = *srcP--; + } + + return dest; +} + +/*------------------------------------------------------------------------*/ + +int DepthSurface::getDepth(const Common::Point &pt) { + if (_vm->_game->_scene._sceneInfo->_depthStyle == 2) { + int bits = (3 - (pt.x % 4)) * 2; + byte v = *getBasePtr(pt.x >> 2, pt.y); + return v >> bits; + } else { + if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h) + return 0; + + return *getBasePtr(pt.x, pt.y) & 0xF; + } +} + +int DepthSurface::getDepthHighBit(const Common::Point &pt) { + if (_vm->_game->_scene._sceneInfo->_depthStyle == 2) { + int bits = (3 - (pt.x % 4)) * 2; + byte v = *getBasePtr(pt.x >> 2, pt.y); + return (v >> bits) & 2; + } else { + if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h) + return 0; + + return *getBasePtr(pt.x, pt.y) & 0x80; + } +} + + +} // End of namespace MADS diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h new file mode 100644 index 0000000000..985a097d4a --- /dev/null +++ b/engines/mads/msurface.h @@ -0,0 +1,255 @@ +/* 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 MADS_MSURFACE_H +#define MADS_MSURFACE_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "mads/palette.h" + +namespace MADS { + +class MADSEngine; +class MSprite; +class DepthSurface; + +/** + * Basic sprite information + */ +struct SpriteInfo { + MSprite *sprite; + int hotX, hotY; + int width, height; + int scaleX, scaleY; + uint8 encoding; + byte *inverseColorTable; + byte *palette; +}; + +/* + * MADS graphics surface + */ +class MSurface : public Graphics::Surface { +private: + bool _freeFlag; +protected: + static MADSEngine *_vm; +public: + /** + * Sets the engine refrence used all surfaces + */ + static void setVm(MADSEngine *vm) { _vm = vm; } + + /** + * Helper method for calculating new dimensions when scaling a sprite + */ + static int scaleValue(int value, int scale, int err); +public: + /** + * Basic constructor + */ + MSurface(); + + /** + * Constructor for a surface with fixed dimensions + */ + MSurface(int width, int height); + + /** + * Destructor + */ + virtual ~MSurface(); + + /** + * Reinitializes a surface to have a given set of dimensions + */ + void setSize(int width, int height); + + /** + * Sets the pixels the surface is associated with + * @remarks The surface will not free the data block + */ + void setPixels(byte *pData, int horizSize, int vertSize); + + /** + * Draws an arbitrary line on the screen using a specified color + * @param startPos Starting position + * @param endPos Ending position + * @param color Color to use + */ + void line(const Common::Point &startPos, const Common::Point &endPos, byte color); + + /** + * Draws a sprite + * @param pt Position to draw sprite at + * @param info General sprite details + * @param clipRect Clipping rectangle to constrain sprite drawing within + */ + void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect); + + /** + * Returns the width of the surface + */ + int getWidth() const { return w; } + + /** + * Returns the height of the surface + */ + int getHeight() const { return h; } + + /** + * Returns the size of the surface as a Rect + */ + Common::Rect getBounds() const { + return Common::Rect(0, 0, w, h); + } + + /** + * Returns a pointer to the surface data + */ + byte *getData() { return (byte *)Graphics::Surface::getPixels(); } + + /** + * Returns a pointer to a given position within the surface + */ + byte *getBasePtr(int x, int y) { return (byte *)Graphics::Surface::getBasePtr(x, y); } + + /** + * Returns a pointer to a given position within the surface + */ + const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::Surface::getBasePtr(x, y); } + + /** + * Clears the surface + */ + void empty(); + + /** + * Copys a sub-section of another surface into the current one. + * @param src Source surface + * @param srcBounds Area of source surface to copy + * @param destPos Destination position to draw in current surface + * @param transparentColor Transparency palette index + */ + void copyFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparentColor = -1); + + /** + * Copys a sub-section of another surface into the current one. + * @param src Source surface + * @param destPos Destination position to draw in current surface + * @param depth Depth of sprite + * @param depthSurface Depth surface to use with sprite depth + * @param scale Scale for image + * @param transparentColor Transparency palette index + */ + void copyFrom(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface, + int scale, int transparentColor = -1); + + /** + * Copys a sub-section of another surface into the current one, taking into + * account variation in the destination copy position based on item size + * and scaling. + * @param src Source surface + * @param destPos Destination position to draw in current surface + * @param depth Depth of sprite + * @param depthSurface Depth surface to use with sprite depth + * @param scale Scale for image + * @param transparentColor Transparency palette index + */ + void copyFromScaled(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface, + int scale, int transparentColor = -1); + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, int transparentColor = -1) { + dest->copyFrom(this, Common::Rect(w, h), Common::Point(), transparentColor); + } + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, const Common::Point &pt, int transparentColor = -1) { + dest->copyFrom(this, Common::Rect(w, h), pt, transparentColor); + } + + /** + * Copies the surface to a given destination surface + */ + void copyTo(MSurface *dest, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparentColor = -1) { + dest->copyFrom(this, srcBounds, destPos, transparentColor); + } + + /** + * Scroll the screen horizontally by a given amount + * @param xAmount Horizontal amount + */ + void scrollX(int xAmount); + + /** + * Scroll the screen vertically by a given amount + * @param yAmount Vertical amount + */ + void scrollY(int yAmount); + + /** + * Translates the pixels of an image used the passed palette with RGB mapping + */ + void translate(Common::Array<RGB6> &palette); + + /** + * Translates the pixels of an image used the passed palette with RGB mapping + */ + void translate(byte map[PALETTE_COUNT]); + + /** + * Create a new surface which is a flipped horizontal copy of the current one + */ + MSurface *flipHorizontal() const; +}; + +class DepthSurface : public MSurface { +private: + MADSEngine *_vm; +public: + /** + * Constructor + */ + DepthSurface(MADSEngine *vm) : _vm(vm) {} + + /** + * Returns the depth at a given position + */ + int getDepth(const Common::Point &pt); + + /** + */ + int getDepthHighBit(const Common::Point &pt); +}; + +} // End of namespace MADS + +#endif /* MADS_MSURFACE_H */ diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp new file mode 100644 index 0000000000..d8a85d472d --- /dev/null +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -0,0 +1,698 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "common/util.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/staticres.h" +#include "mads/nebular/dialogs_nebular.h" + +namespace MADS { + +namespace Nebular { + +bool DialogsNebular::show(int messageId, int objectId) { + MADSAction &action = _vm->_game->_scene._action; + Common::StringArray msg = _vm->_game->getMessage(messageId); + Common::String title; + Common::String commandText; + Common::String valStr; + Common::String dialogText; + bool result = true; + bool centerFlag = false; + bool underlineFlag = false; + bool commandFlag = false; + bool crFlag = false; + TextDialog *dialog = nullptr; + _dialogWidth = 17; + _capitalizationMode = kUppercase; + + // Loop through the lines of the returned text + for (uint idx = 0; idx < msg.size(); ++idx) { + Common::String srcLine = msg[idx]; + const char *srcP = srcLine.c_str(); + + // Loop through the text of the line + while (srcP < srcLine.c_str() + srcLine.size()) { + if (*srcP == '[') { + // Starting a command + commandText = ""; + commandFlag = true; + } else if (*srcP == ']') { + // Ending a command + if (commandFlag) { + if (commandCheck("CENTER", valStr, commandText)) { + centerFlag = true; + } else if (commandCheck("TITLE", valStr, commandText)) { + centerFlag = true; + underlineFlag = true; + crFlag = true; + int v = atoi(valStr.c_str()); + if (v != 0) + _dialogWidth = v; + } else if (commandCheck("CR", valStr, commandText)) { + if (centerFlag) { + crFlag = true; + } else { + if (objectId == -1) { + dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth); + } else { + dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId); + } + dialog->wordWrap(dialogText); + dialog->incNumLines(); + } + } else if (commandCheck("ASK", valStr, commandText)) { + dialog->addInput(); + } else if (commandCheck("VERB", valStr, commandText)) { + dialogText += getVocab(action._activeAction._verbId); + } else if (commandCheck("INDEX", valStr, commandText)) { + int idxLocal = atoi(valStr.c_str()); + if (_indexList[idxLocal]) + dialogText += getVocab(_indexList[idxLocal]); + } else if (commandCheck("NUMBER", valStr, commandText)) { + int idxLocal = atoi(valStr.c_str()); + dialogText += Common::String::format("%.4d", _indexList[idxLocal]); + } else if (commandCheck("NOUN1", valStr, commandText)) { + if (!textNoun(dialogText, 1, valStr)) + dialogText += getVocab(action._activeAction._objectNameId); + } else if (commandCheck("NOUN2", valStr, commandText)) { + if (!textNoun(dialogText, 2, valStr)) + dialogText += getVocab(action._activeAction._indirectObjectId); + } else if (commandCheck("PREP", valStr, commandText)) { + dialogText += kArticleList[action._savedFields._articleNumber]; + } else if (commandCheck("SENTENCE", valStr, commandText)) { + dialogText += action._sentence; + } else if (commandCheck("WIDTH", valStr, commandText)) { + _dialogWidth = atoi(valStr.c_str()); + } else if (commandCheck("BAR", valStr, commandText)) { + dialog->addBarLine(); + } else if (commandCheck("UNDER", valStr, commandText)) { + underlineFlag = true; + } else if (commandCheck("DOWN", valStr, commandText)) { + dialog->downPixelLine(); + } else if (commandCheck("TAB", valStr, commandText)) { + int xp = atoi(valStr.c_str()); + dialog->setLineXp(xp); + } + } + + commandFlag = false; + } else if (commandFlag) { + // Add the next character to the command + commandText += *srcP; + } else { + // Add to the text to be displayed in the dialog + dialogText += *srcP; + } + + ++srcP; + } + + if (!dialog) { + if (objectId == -1) { + dialog = new TextDialog(_vm, FONT_INTERFACE, _defaultPosition, _dialogWidth); + } else { + dialog = new PictureDialog(_vm, _defaultPosition, _dialogWidth, objectId); + } + } + + if (centerFlag) { + dialog->addLine(dialogText, underlineFlag); + if (crFlag) + dialog->incNumLines(); + } else { + dialog->wordWrap(dialogText); + } + + // Reset line processing flags in preparation for next line + dialogText = ""; + commandFlag = false; + underlineFlag = false; + centerFlag = false; + crFlag = false; + } + + if (!centerFlag) + dialog->incNumLines(); + + // Show the dialog + _vm->_events->setCursor(CURSOR_ARROW); + dialog->show(); + + delete dialog; + return result; +} + +void DialogsNebular::showItem(int objectId, int messageId, int speech) { + // MADS engine doesn't currently support speech + assert(!speech); + + show(messageId, objectId); +} + +Common::String DialogsNebular::getVocab(int vocabId) { + assert(vocabId > 0); + + Common::String vocab = _vm->_game->_scene.getVocab(vocabId); + + switch (_capitalizationMode) { + case kUppercase: + vocab.toUppercase(); + break; + case kLowercase: + vocab.toLowercase(); + break; + case kUpperAndLower: + vocab.toLowercase(); + vocab.setChar(toupper(vocab[0]), 0); + default: + break; + } + + return vocab; +} + +bool DialogsNebular::textNoun(Common::String &dest, int nounId, const Common::String &source) { + // Ensure the destination has parameter specifications + if (!source.hasPrefix(":")) + return false; + + // Extract the first (singular) result value + Common::String param1 = Common::String(source.c_str() + 1); + Common::String param2; + const char *sepChar = strchr(source.c_str() + 1, ':'); + if (sepChar) { + param1 = Common::String(source.c_str() + 1, sepChar); + + // Get the second, plural form + param2 = Common::String(sepChar + 1); + } + + // Get the vocab to use + MADSAction &action = _vm->_game->_scene._action; + Common::String vocab = _vm->_dialogs->getVocab(action._activeAction._verbId); + Common::String *str; + + if (vocab.hasSuffix("s") || vocab.hasSuffix("S")) { + str = ¶m2; + } else { + str = ¶m1; + + if (param1 == "a ") { + switch (toupper(vocab[0])) { + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + param1 = "an "; + break; + default: + break; + } + } + } + + dest += *str; + return true; +} + +bool DialogsNebular::commandCheck(const char *idStr, Common::String &valStr, + const Common::String &command) { + uint idLen = strlen(idStr); + + valStr = (command.size() <= idLen) ? "" : Common::String(command.c_str() + idLen); + + // Check whether the command starts with the given Id + int result = scumm_strnicmp(idStr, command.c_str(), idLen) == 0; + if (!result) + return false; + + // It does, so set the command case mode + if (Common::isUpper(command[0]) && Common::isUpper(command[1])) { + _capitalizationMode = kUppercase; + } else if (Common::isUpper(command[0])) { + _capitalizationMode = kUpperAndLower; + } else { + _capitalizationMode = kLowercase; + } + + return true; +} + +void DialogsNebular::showDialog() { + switch (_pendingDialog) { + case DIALOG_GAME_MENU: + //GameMenuDialog::show(); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +CopyProtectionDialog::CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong) : +TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { + getHogAnusEntry(_hogEntry); + + if (priorAnswerWrong) { + addLine("ANSWER INCORRECT!", true); + wordWrap("\n"); + addLine("(But we'll give you another chance!)"); + } + else { + addLine("REX NEBULAR version 8.43", true); + wordWrap("\n"); + addLine("(Copy Protection, for your convenience)"); + } + wordWrap("\n"); + + wordWrap("Now comes the part that everybody hates. But if we don't"); + wordWrap("do this, nasty rodent-like people will pirate this game"); + wordWrap("and a whole generation of talented designers, programmers,"); + wordWrap("artists, and playtesters will go hungry, and will wander"); + wordWrap("aimlessly through the land at night searching for peace."); + wordWrap("So let's grit our teeth and get it over with. Just get"); + + Common::String line = "out your copy of "; + line += _hogEntry._bookId == 103 ? "the GAME MANUAL" : "REX'S LOGBOOK"; + line += ". See! That was easy. "; + wordWrap(line); + + line = Common::String::format("Next, just turn to page %d. On line %d, find word number %d, ", + _hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum); + wordWrap(line); + + wordWrap("and type it on the line below (we',27h,'ve even given you"); + wordWrap("first letter as a hint). As soon as you do that, we can get"); + wordWrap("right into this really COOL adventure game!\n"); + wordWrap("\n"); + wordWrap(" "); + addInput(); + wordWrap("\n"); +} + +void CopyProtectionDialog::show() { + draw(); + _vm->_events->showCursor(); + + // TODO: Replace with text input + while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && + !_vm->_events->_mouseClicked) { + _vm->_events->delay(1); + } + + _vm->_events->_pendingKeys.clear(); +} + +bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) { + File f; + f.open("*HOGANUS.DAT"); + + // Read in the total number of entries, and randomly pick an entry to use + int numEntries = f.readUint16LE(); + int entryIndex = _vm->getRandomNumber(1, numEntries); + + // Read in the encrypted entry + f.seek(28 * entryIndex + 2); + byte entryData[28]; + f.read(entryData, 28); + + // Decrypt it + for (int i = 0; i < 28; ++i) + entryData[i] = ~entryData[i]; + + // Fill out the fields + entry._bookId = entryData[0]; + entry._pageNum = READ_LE_UINT16(&entryData[2]); + entry._lineNum = READ_LE_UINT16(&entryData[4]); + entry._wordNum = READ_LE_UINT16(&entryData[6]); + entry._word = Common::String((char *)&entryData[8]); + + f.close(); + return true; +} + +/*------------------------------------------------------------------------*/ + +PictureDialog::PictureDialog(MADSEngine *vm, const Common::Point &pos, + int maxChars, int objectId) : + TextDialog(vm, FONT_INTERFACE, pos, maxChars), _objectId(objectId) { + // Turn off cycling if active + Scene &scene = _vm->_game->_scene; + _cyclingActive = scene._cyclingActive; + scene._cyclingActive = false; +} + +PictureDialog::~PictureDialog() { + // Restore cycling flag + Scene &scene = _vm->_game->_scene; + scene._cyclingActive = _cyclingActive; +} + +void PictureDialog::save() { + Palette &palette = *_vm->_palette; + byte map[PALETTE_COUNT]; + + // Save the entire screen + _savedSurface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT); + _vm->_screen.copyTo(_savedSurface); + + // Save palette information + Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE], &_palette[0]); + Common::copy(&palette._palFlags[0], &palette._palFlags[PALETTE_COUNT], &_palFlags[0]); + _rgbList.copy(palette._rgbList); + + // Set up palette allocation + Common::fill(&palette._colorFlags[0], &palette._colorFlags[3], true); + + uint32 *palFlagP = &palette._palFlags[0]; + for (int idx = 0; idx < PALETTE_COUNT; ++idx, ++palFlagP) { + if (idx < PALETTE_RESERVED_LOW_COUNT || + idx >= (PALETTE_COUNT - PALETTE_RESERVED_HIGH_COUNT - 10)) { + *palFlagP = 1; + map[idx] = idx; + } else { + *palFlagP = 0; + } + } + + // Reset the flag list + palette._rgbList.reset(); + + // Fade the screen to grey + int numColors = PALETTE_COUNT - PALETTE_RESERVED_LOW_COUNT - PALETTE_RESERVED_HIGH_COUNT; + palette.fadeOut(palette._mainPalette, &map[PALETTE_RESERVED_LOW_COUNT], + PALETTE_RESERVED_LOW_COUNT, numColors, 248, 8, 1, 16); + + // Remap the greyed out screen to use the small greyscale range + // at the top end of the palette + _vm->_screen.translate(map); + + // Load the inventory picture + Common::String setName = Common::String::format("*OB%.3d.SS", _objectId); + SpriteAsset *asset = new SpriteAsset(_vm, setName, 0x8000); + palette.setFullPalette(palette._mainPalette); + + // Get the inventory frame, and adjust the dialog position to allow for it + MSprite *frame = asset->getFrame(0); + _position.y = frame->h + 12; + + // Draw the inventory picture + frame->copyTo(&_vm->_screen, Common::Point(160 - frame->w / 2, 6), + frame->getTransparencyIndex()); + _vm->_screen.copyRectToScreen(_vm->_screen.getBounds()); + + // Adjust the dialog colors to use + TEXTDIALOG_CONTENT1 -= 10; + TEXTDIALOG_CONTENT2 -= 10; + TEXTDIALOG_EDGE -= 10; + TEXTDIALOG_BACKGROUND -= 10; + TEXTDIALOG_FC -= 10; + TEXTDIALOG_FD -= 10; + TEXTDIALOG_FE -= 10; +} + +void PictureDialog::restore() { + if (_savedSurface) { + _savedSurface->copyTo(&_vm->_screen); + delete _savedSurface; + _savedSurface = nullptr; + + _vm->_screen.copyRectToScreen(_vm->_screen.getBounds()); + + // Restore palette information + Palette &palette = *_vm->_palette; + Common::copy(&_palette[0], &_palette[PALETTE_SIZE], &palette._mainPalette[0]); + _vm->_palette->setFullPalette(palette._mainPalette); + Common::copy(&_palFlags[0], &_palFlags[PALETTE_COUNT], &palette._palFlags[0]); + palette._rgbList.copy(_rgbList); + + _vm->_dialogs->_defaultPosition.y = -1; + } +} + +/*------------------------------------------------------------------------*/ + +ScreenDialog::DialogLine::DialogLine() { + _state = 0; + _textDisplayIndex = -1; + _font = nullptr; + _widthAdjust = 0; +} + +ScreenDialog::DialogLine::DialogLine(const Common::String &s) { + _state = 0; + _textDisplayIndex = -1; + _font = nullptr; + _widthAdjust = -1; + _msg = s; +} + +/*------------------------------------------------------------------------*/ + +ScreenDialog::ScreenDialog(MADSEngine *vm) : _vm(vm), + _savedSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT) { + Game &game = *_vm->_game; + Scene &scene = game._scene; + + _v1 = 0; + _selectedLine = 0; + _dirFlag = false; + _textLineCount = 0; + _screenId = 920; + + game.loadQuoteSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 0); + game._kernelMode = KERNEL_ROOM_PRELOAD; + _vm->_events->waitCursor(); + scene.clearVocab(); + scene._dynamicHotspots.clear(); + _vm->_dialogs->_defaultPosition = Common::Point(-1, -1); + + bool palFlag = false; + int nextSceneId = scene._nextSceneId; + int currentSceneId = scene._currentSceneId; + int priorSceneId = scene._priorSceneId; + + if (_vm->_dialogs->_pendingDialog == DIALOG_DIFFICULTY) { + palFlag = true; + } else { + _vm->_palette->initPalette(); + } + scene.loadScene(_screenId, game._aaName, palFlag); + + scene._priorSceneId = priorSceneId; + scene._currentSceneId = currentSceneId; + scene._nextSceneId = nextSceneId; + _vm->_screen._offset.y = 22; + _vm->_sound->pauseNewCommands(); + _vm->_events->initVars(); + game._kernelMode = KERNEL_ROOM_INIT; + + SpriteAsset *menuSprites = new SpriteAsset(_vm, "*MENU", 0); + _menuSpritesIndex = scene._sprites.add(menuSprites); + + byte pal[768]; + if (_vm->_screenFade) { + Common::fill(&pal[0], &pal[PALETTE_SIZE], 0); + _vm->_palette->setFullPalette(pal); + } else { + _vm->_palette->getFullPalette(pal); + _vm->_palette->fadeOut(pal, nullptr, 0, PALETTE_COUNT, 0, 1, 1, 16); + } + + _vm->_screen.copyTo(&_savedSurface); + /* + _vm->_screen.hLine(0, 0, MADS_SCREEN_WIDTH, 2); + _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y, + MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 1)); + _vm->_screen.copyRectToScreen(Common::Rect(0, _vm->_screen._offset.y + 157, + MADS_SCREEN_WIDTH, _vm->_screen._offset.y + 157)); + */ + + game._fx = _vm->_screenFade == SCREEN_FADE_SMOOTH ? + kCenterVertTransition : kTransitionFadeIn; + game._trigger = 0; + _vm->_events->setCursor(CURSOR_ARROW); + + _vm->_palette->setEntry(10, 0, 63, 0); + _vm->_palette->setEntry(11, 0, 45, 0); + _vm->_palette->setEntry(12, 63, 63, 0); + _vm->_palette->setEntry(13, 45, 45, 0); + _vm->_palette->setEntry(14, 63, 63, 63); + _vm->_palette->setEntry(15, 45, 45, 45); + + _lineIndex = -1; +} + +void ScreenDialog::clearLines() { + Scene &scene = _vm->_game->_scene; + _lines.clear(); + scene._spriteSlots.fullRefresh(true); +} + +void ScreenDialog::addQuote(int id1, int id2, DialogTextAlign align, + const Common::Point &pt, Font *font) { + Common::String msg = _vm->_game->getQuote(id1); + + if (id2 > 0) { + msg += " "; + msg += _vm->_game->getQuote(id2); + } + + addLine(msg, align, pt, font); +} + +void ScreenDialog::addLine(const Common::String &msg, DialogTextAlign align, + const Common::Point &pt, Font *font) { + Scene &scene = _vm->_game->_scene; + DialogLine *line; + + if (_lineIndex < (int)_lines.size()) { + if (_lines.size() >= 20) { + ++_lineIndex; + return; + } + + _lines.push_back(msg); + line = &_lines[_lines.size() - 1]; + } else { + line = &_lines[_lineIndex]; + if (msg.compareToIgnoreCase(msg)) { + ++_lineIndex; + return; + } + + if (line->_textDisplayIndex >= 0) { + TextDisplay &textDisplay = scene._textDisplay[line->_textDisplayIndex]; + if (textDisplay._active) { + textDisplay._expire = -1; + if (_textLineCount < 20) { + textDisplay._msg = msg; + ++_textLineCount; + } + } + } + } + + line->_font = font; + line->_state = 0; + line->_pos = pt; + line->_widthAdjust = -1; + line->_textDisplayIndex = -1; + + int xOffset; + switch (align) { + case ALIGN_CENTER: + xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth(msg, -1) / 2; + line->_pos.x += xOffset; + break; + + case ALIGN_AT_CENTER: { + const char *msgP = msg.c_str(); + const char *ch = strchr(msgP, '@'); + if (ch) { + xOffset = (MADS_SCREEN_WIDTH / 2) - font->getWidth( + Common::String(msgP, ch), line->_widthAdjust); + line->_pos.x += xOffset; + } + break; + } + + case ALIGN_RIGHT: + xOffset = font->getWidth(msg, -1); + line->_pos.x -= xOffset; + break; + + default: + break; + } + + ++_lineIndex; +} + +void ScreenDialog::initVars() { + _v1 = -1; + _selectedLine = -1; + _lineIndex = 0; + _textLineCount = 0; +} + +void ScreenDialog::chooseBackground() { + switch (_vm->_game->_currentSectionNumber) { + case 1: + case 2: + _screenId = 921; + break; + case 3: + case 4: + _screenId = 922; + break; + case 5: + case 6: + case 7: + _screenId = 923; + break; + case 8: + _screenId = 924; + break; + default: + _screenId = 920; + break; + } +} + +void ScreenDialog::setFrame(int frameNumber, int depth) { + Scene &scene = _vm->_game->_scene; + SpriteSlot &spriteSlot = scene._spriteSlots[scene._spriteSlots.add()]; + spriteSlot._flags = IMG_UPDATE; + spriteSlot._seqIndex = 1; + spriteSlot._spritesIndex = _menuSpritesIndex; + spriteSlot._frameNumber = frameNumber; + +} + +/*------------------------------------------------------------------------*/ + +GameMenuDialog::GameMenuDialog(MADSEngine *vm) : ScreenDialog(vm) { + clearLines(); + setFrame(1, 2); +} + +void GameMenuDialog::addLines() { + initVars(); + Font *font = _vm->_font->getFont(FONT_CONVERSATION); + int top = 78 - (font->getHeight() + 2) * 12; + addQuote(10, 0, ALIGN_CENTER, Common::Point(0, top), font); + // TODO +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h new file mode 100644 index 0000000000..0554becea4 --- /dev/null +++ b/engines/mads/nebular/dialogs_nebular.h @@ -0,0 +1,179 @@ +/* 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 MADS_DIALOGS_NEBULAR_H +#define MADS_DIALOGS_NEBULAR_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/dialogs.h" + +namespace MADS { + +namespace Nebular { + +enum CapitalizationMode { kUppercase = 0, kLowercase = 1, kUpperAndLower = 2 }; + +class DialogsNebular : public Dialogs { + friend class Dialogs; +private: + int _dialogWidth; + CapitalizationMode _capitalizationMode; + + DialogsNebular(MADSEngine *vm): Dialogs(vm), _capitalizationMode(kUppercase) {} + + virtual Common::String getVocab(int vocabId); + + bool textNoun(Common::String &dest, int nounId, const Common::String &source); + + bool commandCheck(const char *idStr, Common::String &valStr, const Common::String &command); +public: + virtual void showDialog(); + + virtual void showItem(int objectId, int messageId, int speech = -1); + + virtual bool show(int messageId, int objectId = -1); +}; + +struct HOGANUS { + int _bookId; + int _pageNum; + int _lineNum; + int _wordNum; + Common::String _word; +}; + +class CopyProtectionDialog : public TextDialog { +private: + HOGANUS _hogEntry; + + /** + * Get a random copy protection entry from the HOGANUS resource + */ + bool getHogAnusEntry(HOGANUS &entry); +public: + /** + * Constructor + */ + CopyProtectionDialog(MADSEngine *vm, bool priorAnswerWrong); + + /** + * Show the dialog + */ + virtual void show(); +}; + +class PictureDialog : public TextDialog { +private: + int _objectId; + bool _cyclingActive; + byte _palette[PALETTE_SIZE]; + uint32 _palFlags[PALETTE_COUNT]; + RGBList _rgbList; +protected: + virtual void save(); + + virtual void restore(); +public: + PictureDialog(MADSEngine *vm, const Common::Point &pos, int maxChars, int objectId); + + virtual ~PictureDialog(); +}; + +enum DialogTextAlign { ALIGN_CENTER = -1, ALIGN_AT_CENTER = -2, ALIGN_RIGHT = -3 }; + +class ScreenDialog { + struct DialogLine { + int _state; + Common::Point _pos; + int _textDisplayIndex; + Common::String _msg; + Font *_font; + int _widthAdjust; + + DialogLine(); + DialogLine(const Common::String &s); + }; +protected: + MADSEngine *_vm; + MSurface _savedSurface; + Common::Array<DialogLine> _lines; + int _v1; + int _selectedLine; + bool _dirFlag; + int _screenId; + int _menuSpritesIndex; + int _lineIndex; + int _textLineCount; + + /** + * Reset the lines list for the dialog + */ + void clearLines(); + + /** + * Add a quote to the lines list + */ + void addQuote(int id1, int id2, DialogTextAlign align, const Common::Point &pt, Font *font); + + /** + * Adds a line to the lines list + */ + void addLine(const Common::String &msg, DialogTextAlign align, const Common::Point &pt, Font *font); + + /** + * Initializes variables + */ + void initVars(); + + /** + * Sets the display for the screen background behind the dialog + */ + void setFrame(int frameNumber, int depth); + + /** + * Choose the background to display for the dialog + */ + void chooseBackground(); +public: + /** + * Constructor + */ + ScreenDialog(MADSEngine *vm); +}; + +class GameMenuDialog : public ScreenDialog { +private: + /** + * Add the lines for the Game Menu dialog + */ + void addLines(); +public: + GameMenuDialog(MADSEngine *vm); + +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_DIALOGS_NEBULAR_H */ diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp new file mode 100644 index 0000000000..e5a59a0050 --- /dev/null +++ b/engines/mads/nebular/game_nebular.cpp @@ -0,0 +1,819 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/dialogs_nebular.h" +#include "mads/nebular/globals_nebular.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +GameNebular::GameNebular(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; + _difficulty = DIFFICULTY_EASY; +} + +ProtectionResult GameNebular::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[kCopyProtectFailed] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GameNebular::initializeGlobals() { + int count, count2; + int bad; + + _globals.reset(); + _globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + _globals[kNeedToStandUp] = true; + _globals[kTurkeyExploded] = false; + _globals[kMedicineCabinetOpen] = false; + _globals[kMedicineCabinetVirgin] = true; + _globals[kWatchedViewScreen] = false; + _globals[kHoovicAlive] = true; + _globals[kWaterInAPuddle] = false; + + _globals[kFishIn105] = true; + _globals[kFishIn107] = true; + _globals[kFishIn108] = true; + + /* Section #2 variables */ + _globals[kLadderBroken] = false; + _globals[kBone202Status] = 0; + _globals[kRhotundaStatus] = RHOTUNDA_HUNGRY; + _globals[kMonkeyStatus] = MONKEY_AMBUSH_READY; + _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT; + _globals[kMeteorologistEverSeen] = false; + _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + _globals[kTeleporterUnderstood] = false; + _globals[kTwinklesStatus] = TWINKLES_AT_HOME; + _globals[kTwinklesApproached] = 0; + + /* Section #3 variables */ + _globals[kAfterHavoc] = false; + _globals[kKickedIn391Grate] = false; + + /* Section #4 variables */ + _globals[kBadFirstIngredient] = -1; + _objects[OBJ_CHARGE_CASES].setQuality(EXPLOSIVES_INSIDE, 0); + _globals[kHasPurchased] = false; + _globals[kBeenThruHelgaScene] = false; + _globals[kNextIngredient] = 0; + _globals[kHasSaidTimer] = false; + _globals[kHasSaidBinocs] = false; + _globals[kBottleDisplayed] = false; + _globals[kHasBeenScanned] = false; + _globals[kSomeoneHasExploded] = false; + + // Generate a random ingredient list + for (count = 0; count < 4; ++count) { + do { + _globals[kIngredientList + count] = _vm->getRandomNumber(3); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kIngredientList + count] == _globals[kIngredientList + count2]) { + bad = true; + } + } + } while (bad); + } + + // Generate random ingredient quantities + for (count = 0; count < 4; ++count) { + do { + _globals[kIngredientQuantity + count] = _vm->getRandomNumber(3); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kIngredientQuantity + count] == _globals[kIngredientQuantity + count2]) { + bad = true; + } + } + } while (bad); + } + + + /* Section #5 variables */ + _globals[kHoverCarLocation] = 501; + _globals[kHoverCarDestination] = -1; + _globals[kCityFlooded] = false; + _globals[kBoatRaised] = true; + _globals[kLaserHoleIsThere] = false; + _globals[kLineStatus] = LINE_NOT_DROPPED; + + + /* Section #6 variables */ + _globals[kHasTalkedToHermit] = false; + _globals[kHandsetCellStatus] = FIRST_TIME_PHONE_CELLS; + _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED; + _globals[kWarnedFloodCity] = false; + _globals._timebombClock = 0; + _globals._timebombTimer = 0; + + + /* Section #7 variables */ + _globals[kBottleStatus] = BOTTLE_EMPTY; + _globals[kBoatStatus] = BOAT_UNFLOODED; + + + /* Section #8 variables */ + _globals[kWindowFixed] = false; + _globals[kInSpace] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kCameFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = false; + _globals[kHasWatchedAntigrav] = false; + _globals[kRemoteSequenceRan] = false; + _globals[kRemoteOnGround] = false; + _globals[kFromCockpit] = false; + _globals[kExitShip] = false; + _globals[kBetweenRooms] = false; + _globals[kTopButtonPushed] = false; + _globals[kShieldModInstalled] = false; + _globals[kTargetModInstalled] = false; + _globals[kUpBecauseOfRemote] = false; + + + /* Set up the game's teleporters */ + _globals[kTeleporterRoom] = 201; + _globals[kTeleporterRoom + 1] = 301; + _globals[kTeleporterRoom + 2] = 413; + _globals[kTeleporterRoom + 3] = 706; + _globals[kTeleporterRoom + 4] = 801; + _globals[kTeleporterRoom + 5] = 551; + _globals[kTeleporterRoom + 6] = 752; + _globals[kTeleporterRoom + 7] = 0; + _globals[kTeleporterRoom + 8] = 0; + _globals[kTeleporterRoom + 9] = 0; + + for (count = 0; count < TELEPORTER_COUNT; ++count) { + do { + _globals[kTeleporterCode + count] = _vm->getRandomNumber(9999); + bad = false; + for (count2 = 0; count2 < count; ++count2) { + if (_globals[kTeleporterCode + count] == _globals[kTeleporterCode + count2]) { + bad = true; + } + } + } while (bad); + } + + // Final setup based on selected difficulty level + switch (_difficulty) { + case DIFFICULTY_HARD: + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + _objects.setRoom(OBJ_PENLIGHT, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_TRAP; + break; + + case DIFFICULTY_MEDIUM: + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kDurafailRecharged] = true; + _globals[kPenlightCellStatus] = FIRST_TIME_CHARGED_DURAFAIL; + break; + + case DIFFICULTY_EASY: + _objects.setRoom(OBJ_BLOWGUN, NOWHERE); + _objects.setRoom(OBJ_NOTE, NOWHERE); + + _globals[kLeavesStatus] = LEAVES_ON_GROUND; + _globals[kPenlightCellStatus] = FIRST_TIME_UNCHARGED_DURAFAIL; + _globals[kDurafailRecharged] = false; + break; + } + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + Player::preloadSequences("RXM", 1); + Player::preloadSequences("ROX", 1); +} + +void GameNebular::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + case 6: + _sectionHandler = new Section6Handler(_vm); + break; + case 7: + _sectionHandler = new Section7Handler(_vm); + break; + case 8: + _sectionHandler = new Section8Handler(_vm); + break; + default: + break; + } +} + +void GameNebular::checkShowDialog() { + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[kCopyProtectFailed]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GameNebular::showRecipe() { + Dialogs &dialogs = *_vm->_dialogs; + int count; + + for (count = 0; count < 4; count++) { + switch(_globals[kIngredientQuantity + count]) { + case 0: + dialogs._indexList[count] = NOUN_DROP; + break; + case 1: + dialogs._indexList[count] = NOUN_DOLLOP; + break; + case 2: + dialogs._indexList[count] = NOUN_DASH; + break; + case 3: + dialogs._indexList[count] = NOUN_SPLASH; + break; + default: + break; + } + } + + for (count = 0; count < 4; count++) { + switch(_globals[kIngredientList + count]) { + case 0: + dialogs._indexList[count + 4] = NOUN_ALCOHOL; + break; + case 1: + dialogs._indexList[count + 4] = NOUN_LECITHIN; + break; + case 2: + dialogs._indexList[count + 4] = NOUN_PETROX; + break; + case 3: + dialogs._indexList[count + 4] = NOUN_FORMALDEHYDE; + break; + default: + break; + } + } + + _vm->_dialogs->show(401); +} + +void GameNebular::doObjectAction() { + Scene &scene = _scene; + MADSAction &action = _scene._action; + Dialogs &dialogs = *_vm->_dialogs; + int id; + + if (action.isAction(VERB_SMELL) && scene._currentSceneId > 103 && scene._currentSceneId < 111) { + dialogs.show(440); + } else if (action.isAction(VERB_EAT) && scene._currentSceneId > 103 && scene._currentSceneId < 111) { + dialogs.show(441); + } else if (action.isAction(VERB_SMELL, NOUN_BURGER)) { + dialogs.show(442); + } else if (action.isAction(VERB_EAT, NOUN_BURGER)) { + dialogs.show(443); + } else if (action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) { + dialogs.show(444); + } else if (action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) { + dialogs.show(445); + } else if (action.isAction(VERB_WEAR, NOUN_REBREATHER)) { + dialogs.show(scene._currentSceneId > 103 && scene._currentSceneId < 111 ? 446 : 447); + } else if (action.isAction(VERB_SET, NOUN_TIMER_MODULE)) { + dialogs.show(448); + } else if (action.isAction(VERB_NIBBLE_ON, NOUN_BIG_LEAVES)) { + dialogs.show(449); + } else if (action.isAction(VERB_LICK, NOUN_POISON_DARTS)) { + dialogs.show(450); + } else if (action.isAction(VERB_EAT, NOUN_TWINKIFRUIT)) { + _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + dialogs.show(451); + } else if (action.isAction(VERB_GORGE_ON, NOUN_TWINKIFRUIT)) { + _objects.setRoom(OBJ_TWINKIFRUIT, PLAYER_INVENTORY); + dialogs.show(452); + } else if (action.isAction(VERB_GNAW_ON)) { + dialogs.show(453); + } else if (action.isAction(VERB_MASSAGE, NOUN_AUDIO_TAPE)) { + dialogs.show(454); + } else if (action.isAction(VERB_MANGLE, NOUN_CREDIT_CHIP)) { + dialogs.show(455); + } else if (action.isAction(VERB_FONDLE, NOUN_CHARGE_CASES)) { + dialogs.show(456); + } else if (action.isAction(VERB_RUB, NOUN_BOMB)) { + dialogs.show(457); + } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) { + dialogs.show(458); + } else if (action.isAction(VERB_GUZZLE, NOUN_ALIEN_LIQUOR)) { + dialogs.show(459); + } else if (action.isAction(VERB_SMASH, NOUN_TARGET_MODULE)) { + dialogs.show(460); + } else if (action.isAction(VERB_JUGGLE)) { + dialogs.show(461); + } else if (action.isAction(VERB_APPLY, NOUN_POLYCEMENT)) { + dialogs.show(462); + } else if (action.isAction(VERB_SNIFF, NOUN_POLYCEMENT)) { + dialogs.show(465); + } else if (action.isAction(VERB_TIE, NOUN_FISHING_LINE)) { + dialogs.show(463); + } else if (action.isAction(VERB_ATTACH, NOUN_FISHING_LINE)) { + dialogs.show(463); + } else if (action.isAction(VERB_UNLOCK)) { + dialogs.show(464); + } else if (action.isAction(VERB_REFLECT)) { + dialogs.show(466); + } else if (action.isAction(VERB_GAZE_INTO, NOUN_REARVIEW_MIRROR)) { + dialogs.show(467); + } else if (action.isAction(VERB_EAT, NOUN_CHICKEN_BOMB)) { + dialogs.show(469); + } else if (action.isAction(VERB_BREAK, NOUN_VASE)) { + dialogs.show(471); + } else if (action.isAction(VERB_SHAKE_HANDS, NOUN_GUARDS_ARM2)) { + dialogs.show(472); + } else if (action.isAction(VERB_READ, NOUN_LOG)) { + dialogs.show(473); + } else if (action.isAction(VERB_RUB, NOUN_BOMBS)) { + dialogs.show(474); + } else if (action.isAction(VERB_DRINK, NOUN_FORMALDEHYDE)) { + dialogs.show(475); + } else if (action.isAction(VERB_DRINK, NOUN_PETROX)) { + dialogs.show(476); + } else if (action.isAction(VERB_DRINK, NOUN_LECITHIN)) { + dialogs.show(477); + } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_PLANT_STALK) && _objects.isInInventory(OBJ_POISON_DARTS) + && _objects.isInInventory(OBJ_PLANT_STALK)) { + _objects.addToInventory(OBJ_BLOWGUN); + _objects.setRoom(OBJ_PLANT_STALK, NOWHERE); + _globals[kBlowgunStatus] = 0; + dialogs.showItem(OBJ_BLOWGUN, 809); + } else if (action.isAction(VERB_PUT, NOUN_POISON_DARTS, NOUN_BLOWGUN) && _objects.isInInventory(OBJ_POISON_DARTS) + && _objects.isInInventory(OBJ_BLOWGUN)) { + dialogs.show(433); + } else if (action.isAction(VERB_DEFACE) && action.isAction(VERB_FOLD) && action.isAction(VERB_MUTILATE)) { + dialogs.show(434); + } else if (action.isAction(VERB_SPINDLE)) { + dialogs.show(479); + } else if ((action.isAction(VERB_READ) || action.isAction(VERB_LOOK_AT) || action.isAction(VERB_LOOK)) && + action.isObject(NOUN_NOTE) && _objects.isInInventory(OBJ_NOTE)) { + _objects.setRoom(OBJ_NOTE, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_COMBINATION); + dialogs.showItem(OBJ_COMBINATION, 851); + } else if ((action.isAction(VERB_LOOK) || action.isAction(VERB_READ)) && + ((id = _objects.getIdFromDesc(action._activeAction._objectNameId)) > 0 || + (action._activeAction._indirectObjectId > 0 && + (id = _objects.getIdFromDesc(action._activeAction._indirectObjectId)))) && + _objects.isInInventory(id)) { + if (id == OBJ_REPAIR_LIST) { + dialogs._indexList[0] = _globals[kTeleporterCode + 7]; + dialogs._indexList[1] = _globals[kTeleporterCode + 8]; + dialogs._indexList[2] = _globals[kTeleporterCode + 6]; + dialogs._indexList[3] = _globals[kTeleporterCode + 9]; + dialogs._indexList[4] = _globals[kTeleporterCode + 0]; + dialogs._indexList[5] = _globals[kTeleporterCode + 1]; + dialogs._indexList[6] = _globals[kTeleporterCode + 4]; + dialogs._indexList[7] = _globals[kTeleporterCode + 5]; + dialogs._indexList[8] = _globals[kTeleporterCode + 2]; + + dialogs.showItem(id, 402); + } else { + int messageId = 800 + id; + if ((id == OBJ_CHARGE_CASES) && _objects[OBJ_CHARGE_CASES].getQuality(3) != 0) { + messageId = 860; + } + + if (id == OBJ_TAPE_PLAYER && _objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) + messageId = 867; + + if (id == 32 && _objects[OBJ_FISHING_LINE]._roomNumber == 3) + messageId = 862; + + if (id == OBJ_BOTTLE && _globals[kBottleStatus] != 0) + messageId = 862 + _globals[kBottleStatus]; + + if (id == OBJ_PHONE_HANDSET && _globals[kHandsetCellStatus]) + messageId = 861; + + dialogs.showItem(id, messageId); + } + } else if (action.isAction(VERB_PUT, NOUN_BURGER, NOUN_DEAD_FISH)) { + if (_objects.isInInventory(OBJ_BURGER) || _objects.isInInventory(OBJ_DEAD_FISH)) { + _objects.removeFromInventory(OBJ_DEAD_FISH, PLAYER_INVENTORY); + _objects.removeFromInventory(OBJ_BURGER, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_STUFFED_FISH); + dialogs.showItem(OBJ_STUFFED_FISH, 803); + } + } else if (action.isAction(VERB_PUT, NOUN_AUDIO_TAPE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_AUDIO_TAPE) && + _objects.isInInventory(OBJ_TAPE_PLAYER)) { + _objects.setRoom(OBJ_AUDIO_TAPE, OBJ_TAPE_PLAYER); + } else if (action.isAction(VERB_ACTIVATE, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) { + if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) { + showRecipe(); + } else { + dialogs.show(406); + } + } else if (action.isAction(VERB_EJECT, NOUN_TAPE_PLAYER) && _objects.isInInventory(OBJ_TAPE_PLAYER)) { + if (_objects[OBJ_AUDIO_TAPE]._roomNumber == OBJ_TAPE_PLAYER) { + _objects.addToInventory(OBJ_AUDIO_TAPE); + } else { + dialogs.show(407); + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_TAPE_PLAYER)) { + dialogs.show(408); + } else if (action.isAction(VERB_ACTIVATE, NOUN_REMOTE)) { + dialogs.show(_globals[kTopButtonPushed] ? 502 : 501); + } else if ((action.isAction(VERB_ATTACH, NOUN_DETONATORS, NOUN_CHARGE_CASES) || action.isAction(VERB_PUT, NOUN_DETONATORS, NOUN_CHARGE_CASES)) && + _objects.isInInventory(OBJ_DETONATORS) && _objects.isInInventory(OBJ_CHARGE_CASES)) { + if (_objects[OBJ_CHARGE_CASES].getQuality(3)) { + _objects.setRoom(OBJ_CHARGE_CASES, 1); + _objects.setRoom(OBJ_DETONATORS, 1); + _objects.addToInventory(OBJ_BOMBS); + dialogs.showItem(OBJ_BOMBS, 403); + } else { + dialogs.show(405); + } + } else if (action.isAction(VERB_ATTACH, NOUN_DETONATORS)) { + dialogs.show(470); + } else if ((action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMBS) || action.isAction(VERB_ATTACH, NOUN_TIMER_MODULE, NOUN_BOMB) + || action.isAction(VERB_PUT, NOUN_TIMER_MODULE, NOUN_BOMB)) && _objects.isInInventory(OBJ_TIMER_MODULE) && ( + _objects.isInInventory(OBJ_BOMBS) || _objects.isInInventory(OBJ_BOMB))) { + if (_objects.isInInventory(OBJ_BOMBS)) { + _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_BOMB); + } else { + _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + } + + _objects.setRoom(OBJ_TIMER_MODULE, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_TIMEBOMB); + dialogs.showItem(OBJ_TIMEBOMB, 404); + } else if (action.isAction(VERB_FONDLE, NOUN_PLANT_STALK)) { + dialogs.show(410); + } else if (action.isAction(VERB_EMPTY, NOUN_BOTTLE)) { + _globals[kBottleStatus] = 0; + dialogs.show(432); + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_FISHING_ROD)) { + if (_objects[OBJ_FISHING_LINE]._roomNumber == 3) { + _objects.addToInventory(OBJ_FISHING_LINE); + dialogs.showItem(OBJ_FISHING_LINE, 409); + } else { + dialogs.show(428); + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PENLIGHT)) { + switch (_globals[kPenlightCellStatus]) { + case 1: + case 2: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 412); + break; + case 3: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 413); + break; + case 5: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 411); + break; + case 6: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, 429); + break; + default: + dialogs.show(478); + break; + } + } else if (action.isAction(VERB_DISASSEMBLE, NOUN_PHONE_HANDSET)) { + switch (_globals[kHandsetCellStatus]) { + case 1: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + dialogs.showItem(OBJ_DURAFAIL_CELLS, + _difficulty != 1 || _globals[kDurafailRecharged] ? 415 : 414); + break; + case 2: + _objects.addToInventory(OBJ_DURAFAIL_CELLS); + if (_difficulty == 1) { + dialogs.showItem(OBJ_DURAFAIL_CELLS, 416); + } else { + _globals[kHandsetCellStatus] = 0; + } + break; + case 3: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_PHONE_CELLS, 418); + break; + case 4: + _objects.addToInventory(OBJ_PHONE_CELLS); + dialogs.showItem(OBJ_PHONE_CELLS, 417); + break; + default: + dialogs.show(478); + break; + } + } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PENLIGHT)) { + if (_globals[kPenlightCellStatus] == 0) { + _globals[kPenlightCellStatus] = 3; + _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + dialogs.show(419); + } else { + dialogs.show(420); + } + } else if (action.isAction(VERB_PUT, NOUN_PHONE_CELLS, NOUN_PHONE_HANDSET)) { + if (_globals[kHandsetCellStatus] == 0) { + _globals[kHandsetCellStatus] = 3; + _objects.setRoom(OBJ_PHONE_CELLS, PLAYER_INVENTORY); + dialogs.show(421); + } else { + dialogs.show(422); + } + } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PENLIGHT)) { + if (_globals[kPenlightCellStatus]) { + dialogs.show(424); + } else { + _objects.setRoom(OBJ_DURAFAIL_CELLS, PLAYER_INVENTORY); + _globals[kPenlightCellStatus] = _difficulty != 1 || _globals[kDurafailRecharged] ? 1 : 2; + dialogs.show(423); + } + } else if (action.isAction(VERB_PUT, NOUN_DURAFAIL_CELLS, NOUN_PHONE_HANDSET)) { + if (_globals[kHandsetCellStatus]) { + dialogs.show(424); + } else { + _objects.setRoom(OBJ_DURAFAIL_CELLS, PLAYER_INVENTORY); + _globals[kDurafailRecharged] = _difficulty != 1 || _globals[kHandsetCellStatus] ? 1 : 2; + dialogs.show(425); + } + } else if (action.isAction(VERB_SET, NOUN_TIMEBOMB)) { + dialogs.show(427); + } else if (action.isAction(VERB_PUT, NOUN_BOMB, NOUN_CHICKEN) || action.isAction(VERB_PUT, NOUN_BOMBS, NOUN_CHICKEN)) { + _objects.setRoom(OBJ_CHICKEN, PLAYER_INVENTORY); + if (_objects.isInInventory(OBJ_BOMBS)) { + _objects.setRoom(OBJ_BOMBS, PLAYER_INVENTORY); + _objects.addToInventory(OBJ_BOMB); + } else { + _objects.setRoom(OBJ_BOMB, PLAYER_INVENTORY); + } + + _objects.addToInventory(OBJ_CHICKEN_BOMB); + dialogs.showItem(OBJ_CHICKEN_BOMB, 430); + } else { + return; + } + + action._inProgress = false; +} + +void GameNebular::unhandledAction() { + int randVal = _vm->getRandomNumber(1, 1000); + MADSAction &action = _scene._action; + + if (action.isAction(VERB_THROW, NOUN_BOMB) || action.isAction(VERB_THROW, NOUN_BOMBS) + || action.isAction(VERB_THROW, NOUN_TIMEBOMB) || action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB)) + _vm->_dialogs->show(42); + else if (action.isAction(VERB_DISASSEMBLE)) + _vm->_dialogs->show(435); + else if ((action.isAction(VERB_EAT, NOUN_DEAD_FISH) || action.isAction(VERB_EAT, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId))) + _vm->_dialogs->show(12); + else if ((action.isAction(VERB_SMELL, NOUN_DEAD_FISH) || action.isAction(VERB_SMELL, NOUN_STUFFED_FISH)) && _vm->_game->_objects.isInInventory(_vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId))) + _vm->_dialogs->show(13); + else if (action.isAction(VERB_EAT, NOUN_CHICKEN) && _vm->_game->_objects.isInInventory(OBJ_CHICKEN)) + _vm->_dialogs->show(912); + else if ((action.isAction(VERB_SHOOT) || action.isAction(VERB_HOSE_DOWN)) && action.isObject(NOUN_BLOWGUN)) { + if ((_scene._currentSceneId >= 104) && (_scene._currentSceneId <= 111)) + _vm->_dialogs->show(38); + else if (action.isObject(NOUN_PIRANHA)) + _vm->_dialogs->show(41); + else if (action.isObject(NOUN_CHICKEN) || action.isObject(NOUN_VULTURE) || action.isObject(NOUN_SPIDER) + || action.isObject(NOUN_YELLOW_BIRD) || action.isObject(NOUN_SWOOPING_CREATURE) || action.isObject(NOUN_CAPTIVE_CREATURE)) { + _vm->_dialogs->show(40); + } else + _vm->_dialogs->show(39); + } else if (action.isAction(VERB_TALKTO)) { + _globals[kTalkInanimateCount] = (_globals[kTalkInanimateCount] + 1) % 16; + if (!_globals[kTalkInanimateCount]) { + _vm->_dialogs->show(2); + } else { + Common::String tmpMsg = "\"Greetings, "; + tmpMsg += _vm->_game->_scene.getVocab(action._activeAction._objectNameId); + tmpMsg += "!\""; + _scene._kernelMessages.reset(); + _scene._kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, tmpMsg); + } + } else if (action.isAction(VERB_GIVE, NOUN_DOOR, NOUN_CEILING) || action.isAction(VERB_CLOSE, NOUN_CHAIR)) + _vm->_dialogs->show(3); + else if (action.isAction(VERB_THROW)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (objId < 0) + _vm->_dialogs->show(4); + else if (_vm->_game->_objects[objId]._roomNumber != 2) + _vm->_dialogs->show(5); + else + _vm->_dialogs->show(6); + } else if (action.isAction(VERB_LOOK)) { + if (action.isObject(NOUN_BINOCULARS) && (action._activeAction._indirectObjectId > 0)) + _vm->_dialogs->show(10); + else if (randVal < 600) + _vm->_dialogs->show(7); + else + _vm->_dialogs->show(21); + } else if (action.isAction(VERB_TAKE)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(16); + else if (randVal <= 333) + _vm->_dialogs->show(8); + else if (randVal <= 666) + _vm->_dialogs->show(22); + else + _vm->_dialogs->show(23); + } else if (action.isAction(VERB_CLOSE)) { + if (randVal <= 333) + _vm->_dialogs->show(9); + else + _vm->_dialogs->show(33); + } else if (action.isAction(VERB_OPEN)) { + if (randVal <= 500) + _vm->_dialogs->show(30); + else if (randVal <= 750) + _vm->_dialogs->show(31); + else + _vm->_dialogs->show(32); + } else if (action.isAction(VERB_PULL)) + _vm->_dialogs->show(18); + else if (action.isAction(VERB_PUSH)) { + if (randVal < 750) + _vm->_dialogs->show(19); + else + _vm->_dialogs->show(20); + } else if (action.isAction(VERB_PUT)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(25); + else + _vm->_dialogs->show(24); + } else if (action.isAction(VERB_GIVE)) { + int objId = _vm->_game->_objects.getIdFromDesc(action._activeAction._objectNameId); + if (!_vm->_game->_objects.isInInventory(objId)) + _vm->_dialogs->show(26); + else if (randVal <= 500) + _vm->_dialogs->show(28); + else + _vm->_dialogs->show(29); + } else if (!action.isAction(VERB_WALKTO) && !action.isAction(VERB_WALK_ACROSS) && !action.isAction(VERB_WALK_TOWARDS) && !action.isAction(VERB_WALK_DOWN) + && !action.isAction(VERB_SWIM_TO) && !action.isAction(VERB_SWIM_ACROSS) && !action.isAction(VERB_SWIM_INTO) && !action.isAction(VERB_SWIM_THROUGH) + && !action.isAction(VERB_SWIM_UNDER)) { + if (randVal <= 100) + _vm->_dialogs->show(36); + else if (randVal <= 200) + _vm->_dialogs->show(1); + else if (randVal <= 475) + _vm->_dialogs->show(34); + else if (randVal <= 750) + _vm->_dialogs->show(35); + else + _vm->_dialogs->show(37); + } +} + +void GameNebular::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) { + if (!_player._stopWalkerIndex) { + int randomVal = _vm->getRandomNumber(29999);; + if (_globals[kSexOfRex] == REX_MALE) { + switch (_player._facing) { + case FACING_SOUTHWEST: + case FACING_SOUTHEAST: + case FACING_NORTHWEST: + case FACING_NORTHEAST: + if (randomVal < 200) { + _player.addWalker(-1, 0); + _player.addWalker(1, 0); + } + break; + + case FACING_WEST: + case FACING_EAST: + if (randomVal < 500) { + for (int count = 0; count < 10; ++count) { + _player.addWalker(1, 0); + } + } + break; + + case FACING_SOUTH: + if (randomVal < 500) { + for (int count = 0; count < 10; ++count) { + _player.addWalker((randomVal < 250) ? 1 : 2, 0); + } + } else if (randomVal < 750) { + for (int count = 0; count < 5; ++count) { + _player.addWalker(1, 0); + } + + _player.addWalker(0, 0); + _player.addWalker(0, 0); + + for (int count = 0; count < 5; ++count) { + _player.addWalker(2, 0); + } + } + break; + + default: + break; + } + } + } + + *((uint32 *)&_globals[kWalkerTiming]) += 6; + } + } + + // Below is countdown to set the timebomb off in room 604 + if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) { + int diff = _scene._frameStartTime - *((uint32 *)&_globals[kTimebombClock]); + if ((diff >= 0) && (diff <= 60)) { + *((uint32 *)&_globals[kTimebombTimer]) += diff; + } else { + ++*((uint32 *)&_globals[kTimebombTimer]); + } + *((uint32 *)&_globals[kTimebombClock]) = _scene._frameStartTime; + } +} + +void GameNebular::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + if (phase1) { + _globals.synchronize(s); + s.syncAsByte(_storyMode); + s.syncAsByte(_difficulty); + } +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/game_nebular.h b/engines/mads/nebular/game_nebular.h new file mode 100644 index 0000000000..6620deaea6 --- /dev/null +++ b/engines/mads/nebular/game_nebular.h @@ -0,0 +1,153 @@ +/* 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 MADS_GAME_NEBULAR_H +#define MADS_GAME_NEBULAR_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Nebular { + +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum Difficulty { + DIFFICULTY_HARD = 1, DIFFICULTY_MEDIUM = 2, DIFFICULTY_EASY = 3 +}; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_BINOCULARS = 0, + OBJ_BURGER = 1, + OBJ_DEAD_FISH = 2, + OBJ_STUFFED_FISH = 3, + OBJ_REBREATHER = 4, + OBJ_TIMER_MODULE = 5, + OBJ_BIG_LEAVES = 6, + OBJ_POISON_DARTS = 7, + OBJ_PLANT_STALK = 8, + OBJ_BLOWGUN = 9, + OBJ_TWINKIFRUIT = 10, + OBJ_BONE = 11, + OBJ_CHICKEN = 12, + OBJ_SCALPEL = 13, + OBJ_AUDIO_TAPE = 14, + OBJ_CREDIT_CHIP = 15, + OBJ_SECURITY_CARD = 16, + OBJ_CHARGE_CASES = 17, + OBJ_ESTROTOXIN = 18, + OBJ_BOMB = 19, + OBJ_TIMEBOMB = 20, + OBJ_REPAIR_LIST = 21, + OBJ_ALIEN_LIQUOR = 22, + OBJ_TARGET_MODULE = 23, + OBJ_SHIELD_MODULATOR = 24, + OBJ_TAPE_PLAYER = 25, + OBJ_PHONE_CELLS = 26, + OBJ_PENLIGHT = 27, + OBJ_DURAFAIL_CELLS = 28, + OBJ_FAKE_ID = 29, + OBJ_ID_CARD = 30, + OBJ_POLYCEMENT = 31, + OBJ_FISHING_ROD = 32, + OBJ_FISHING_LINE = 33, + OBJ_PADLOCK_KEY = 34, + OBJ_DOOR_KEY = 35, + OBJ_REARVIEW_MIRROR = 36, + OBJ_COMPACT_CASE = 37, + OBJ_DETONATORS = 39, + OBJ_BOTTLE = 40, + OBJ_CHICKEN_BOMB = 41, + OBJ_VASE = 42, + OBJ_REMOTE = 43, + OBJ_COMPUTER_GAME = 44, + OBJ_PHONE_HANDSET = 45, + OBJ_BONES = 46, + OBJ_GUARDS_ARM = 47, + OBJ_LOG = 48, + OBJ_BOMBS = 49, + OBJ_NOTE = 50, + OBJ_COMBINATION = 51, + OBJ_FORMALDEHYDE = 52, + OBJ_PETROX = 53, + OBJ_LECITHIN = 54 +}; + +class GameNebular : public Game { + friend class Game; +protected: + GameNebular(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + NebularGlobals _globals; + StoryMode _storyMode; + Difficulty _difficulty; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + void showRecipe(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; +typedef Section1Handler Section6Handler; +typedef Section1Handler Section7Handler; +typedef Section1Handler Section8Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_NEBULAR_H */ diff --git a/engines/mads/nebular/globals_nebular.cpp b/engines/mads/nebular/globals_nebular.cpp new file mode 100644 index 0000000000..9f8b8a7888 --- /dev/null +++ b/engines/mads/nebular/globals_nebular.cpp @@ -0,0 +1,55 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Nebular { + +NebularGlobals::NebularGlobals() + : Globals() { + // Initialize lists + resize(210); + _spriteIndexes.resize(30); + _sequenceIndexes.resize(30); + + // Initialize game flags + _timebombClock = 0; + _timebombTimer = 0; +} + +void NebularGlobals::synchronize(Common::Serializer &s) { + Globals::synchronize(s); + + s.syncAsUint32LE(_timebombClock); + s.syncAsUint32LE(_timebombTimer); + _spriteIndexes.synchronize(s); + _sequenceIndexes.synchronize(s); +} + + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/globals_nebular.h b/engines/mads/nebular/globals_nebular.h new file mode 100644 index 0000000000..88605a290e --- /dev/null +++ b/engines/mads/nebular/globals_nebular.h @@ -0,0 +1,305 @@ +/* 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 MADS_GLOBALS_NEBULAR_H +#define MADS_GLOBALS_NEBULAR_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/game.h" +#include "mads/resources.h" + +namespace MADS { + +namespace Nebular { + +enum GlobalId { + kSexOfRex = 0, + kOldSexOfRex = 1, + kWalkerTiming = 2, +// kWalkerTiming0 = 3, + kTalkInanimateCount = 4, + kCopyProtectFailed = 5, + + /* Section #1 variables */ + kNeedToStandUp = 10, + kTurkeyExploded = 11, + kMedicineCabinetOpen = 12, + kMedicineCabinetVirgin = 13, + kWatchedViewScreen = 14, + kHoovicAlive = 15, + kHoovicSated = 16, + kHoovicFishEaten = 17, + kWaterInAPuddle = 18, + kFishIn105 = 19, + kFishIn107 = 20, + kFishIn108 = 21, + kRandomNumber = 29, + + /* Section #2 variables */ + kCurtainOpen = 30, + kLadderBroken = 31, + kBone202Status = 32, + kMeteorologistStatus = 33, + kRhotundaStatus = 34, + kLeavesStatus = 35, + kMonkeyStatus = 36, + kMeteorologistEverSeen = 37, + kMeteorologistWatch = 38, + kTeleporterCommand = 39, + + kTeleporterDestination = 40, + kTeleporterUnderstood = 41, + kConv205 = 42, + kChickenPermitted = 43, + kTwinklesStatus = 44, + kTwinklesApproached = 45, + kConvTwinkles1 = 46, + kConvTwinkles2 = 47, + kConvTwinkles3 = 48, + kConvTwinkles5 = 49, + + kConvTwinkles6 = 50, + kConvTwinkles7 = 51, + kConvTwinkles8 = 52, + kBlowgunStatus = 53, + + /* Section #3 Variables */ + kAfterHavoc = 60, + kHaveYourStuff = 61, + kRightView320 = 62, + kConvBuddy1 = 63, + kConvBuddy2 = 64, + kMetBuddyBeast = 65, + kKnowsBuddyBeast = 66, + kConvSlache1 = 67, + kConvSlache2 = 68, + kConvSlache3 = 69, + + kRexHasMetSlache = 70, + kConvIntern = 71, + kHasSeenProfPyro = 72, + kKickedIn391Grate = 73, + + /* Section #4 Variables */ + kArmoryDoorOpen = 80, + kStorageDoorOpen = 81, + kNextIngredient = 82, + kIngredientList = 83, + kIngredientList1 = 84, + kIngredientList2 = 85, + kIngredientList3 = 86, + kIngredientQuantity = 87, + kIngredientQuantity1 = 88, + kIngredientQuantity2 = 89, + + kIngredientQuantity3 = 90, + kconvPyro_1 = 91, + kconvPyro_2 = 92, + kconvPyro_3 = 93, + kconvPyro_4 = 94, + kBadFirstIngredient = 95, + kConvBartender1 = 96, + kConvBartender2 = 97, + kConvBartender3 = 98, + kConvBartender4 = 99, + + kHasPurchased = 100, + kBeenThruHelgaScene = 101, + kHasSaidBinocs = 102, + kHasSaidTimer = 103, + kBottleDisplayed = 104, + kHasBeenScanned = 105, + kSomeoneHasExploded = 106, + + /* Section #5 Variables */ + kBoatRaised = 110, + kCarStatus = 111, + kCityFlooded = 112, + kLaserOn = 113, + kLaserHoleIsThere = 114, + kCarIsGone = 115, + kRegisterOpen = 116, + kSafeStatus = 117, + kDogStatus = 118, + kLineStatus = 119, + + kHoverCarLocation = 120, + kHoverCarDestination = 121, + + /* Section #6 Variables */ + kConvHermit1 = 130, + kconvHermit2 = 131, + kHasTalkedToHermit = 132, + kExecuted_1_11 = 133, + kHandsetCellStatus = 134, + kBeenInVideoStore = 135, + kDurafailRecharged = 136, + kPenlightCellStatus = 137, + kTimebombStatus = 138, + kCheckDaemonTimebomb = 140, + + kResurrectRoom = 141, + + /* Section #6 Time-Bomb Variables */ + kTimebombClock = 142, +// kTimebombClock0 = 143, + kTimebombTimer = 144, +// kTimebombTimer0 = 145, + kWarnedFloodCity = 146, + + /* Section #7 Variables */ + kBottleStatus = 150, + kMonsterAlive = 151, + kConvBottleFillNode = 152, + kBoatStatus = 153, + + /* Section #8 Variables */ + kAntigravClock = 160, +// kAntigravClock0 = 161, + kAntigravTiming = 162, +// kAntigravTiming0 = 163, + kWindowFixed = 164, + kInSpace = 165, + kReturnFromCut = 166, + kBeamIsUp = 167, + kForceBeamDown = 168, + kCameFromCut = 169, + + kCutX = 170, + kCutY = 171, + kCutFacing = 172, + kDontRepeat = 173, + kHoppyDead = 174, + kHasWatchedAntigrav = 175, + kRemoteSequenceRan = 176, + kRemoteOnGround = 177, + kFromCockpit = 178, + kExitShip = 179, + + kBetweenRooms = 180, + kTopButtonPushed = 181, + kTargetModInstalled = 182, + kShieldModInstalled = 183, + kUpBecauseOfRemote = 184, + + kTeleporterRoom = 190, + kTeleporterCode = 200 +}; + +/* Enums used for specific individual globals */ +/* Section #1 */ +// Rex's sex/swimming state +enum { REX_MALE = 0, REX_MALE_SWIMMER = 1, REX_FEMALE = 2 }; +// State of Meteorologist in the outpost +enum { METEOROLOGIST_ABSENT = 0, METEOROLOGIST_PRESENT = 1, METEOROLOGIST_GONE = 2 }; + +// State of watching the Meteorologist +enum { METEOROLOGIST_NORMAL = 0, METEOROLOGIST_GROUND = 1, METEOROLOGIST_TOWER = 2 }; + +// The fat bouncy lady that can squish you on the plains +enum { RHOTUNDA_HUNGRY = 0, RHOTUNDA_STUCK = 1, RHOTUNDA_GONE = 2 }; + +// Flags for the bones you can take +enum { BONE_202_LEFT_GONE = 1, BONE_202_RIGHT_GONE = 2 }; + +// Leaves used to cover the trap +enum { LEAVES_ON_GROUND = 0, LEAVES_WITH_PLAYER = 1, LEAVES_ON_TRAP = 2 }; + +// Monkey ambush state +enum { MONKEY_AMBUSH_READY = 0, MONKEY_HAS_BINOCULARS = 1, MONKEY_IS_GONE = 2 }; + +// Teleporter status flags +enum { + TELEPORTER_NONE = 0, TELEPORTER_BEAM_IN = 1, TELEPORTER_BEAM_OUT = 2, + TELEPORTER_STEP_OUT = 3, TELEPORTER_WRONG = 4 +}; + +// TWinkies status +enum { TWINKLES_AT_HOME = 0, TWINKLES_GONE = 1 }; + +/* Section #4 */ +// Status of the explosives +enum { EXPLOSIVES_INSIDE = 3 }; + +/* Section # 5 */ +enum { LINE_NOT_DROPPED = 1, LINE_DROPPED = 2, LINE_TIED = 3, LINE_NOW_UNTIED = 4 }; + +/* Section #6 */ +enum { + NO_CELLS = 0, // Handset doesn't contain any cells + CHARGED_DURAFAIL = 1, // Handset has charged durafail cells + UNCHARGED_DURAFAIL = 2, // Handset has uncharged durafail cells */ + PHONE_CELLS = 3, // Handset has already charged phone cells + FIRST_TIME_PHONE_CELLS = 4, // First time phone cells are in the handset + FIRST_TIME_UNCHARGED_DURAFAIL = 5, // First time uncharged cells are in penlight + FIRST_TIME_CHARGED_DURAFAIL = 6 // First time charged cells are in penlight +}; + +// Time bomb status +enum { + TIMEBOMB_DEACTIVATED = 0, TIMEBOMB_ACTIVATED = 1, + TIMEBOMB_BLOW_UP = 2, TIMEBOMB_DEAD = 3 +}; + +/* Section #7 */ +// Status of the the bottle +enum { + BOTTLE_EMPTY = 0, BOTTLE_ONE_QUARTER_FULL = 1, BOTTLE_HALF_FULL = 2, + BOTTLE_THREE_QUARTERS_FULL = 3, BOTTLE_FULL = 4 +}; + +// Status of the boat +enum { + BOAT_UNFLOODED = 0, BOAT_ADRIFT = 1, BOAT_TIED_FLOATING = 2, + BOAT_TIED = 3, BOAT_GONE = 4 +}; + + +/* Miscellaneous defines */ +#define TELEPORTER_COUNT 10 // Total number of teleporters +#define TELEPORTER_WORK_COUNT 6 // Total number that actually work + + +class NebularGlobals : public Globals { +public: + SynchronizedList _spriteIndexes; + SynchronizedList _sequenceIndexes; + + int _timebombClock, _timebombTimer; +public: + /** + * Constructor + */ + NebularGlobals(); + + /** + * Synchronize the globals data + */ + virtual void synchronize(Common::Serializer &s); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GLOBALS_NEBULAR_H */ diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp new file mode 100644 index 0000000000..52b565016f --- /dev/null +++ b/engines/mads/nebular/nebular_scenes.cpp @@ -0,0 +1,628 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes1.h" +#include "mads/nebular/nebular_scenes2.h" +#include "mads/nebular/nebular_scenes3.h" +#include "mads/nebular/nebular_scenes4.h" +#include "mads/nebular/nebular_scenes5.h" +#include "mads/nebular/nebular_scenes6.h" +#include "mads/nebular/nebular_scenes7.h" +#include "mads/nebular/nebular_scenes8.h" + +namespace MADS { + +namespace Nebular { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + scene.addActiveVocab(NOUN_DROP); + scene.addActiveVocab(NOUN_DOLLOP); + scene.addActiveVocab(NOUN_DASH); + scene.addActiveVocab(NOUN_SPLASH); + scene.addActiveVocab(NOUN_ALCOHOL); + + switch (scene._nextSceneId) { + // Scene group #1 (ship, ocean, cave) + case 101: // Ship, cockpit + return new Scene101(vm); + case 102: // Ship, dining room + return new Scene102(vm); + case 103: // Ship, engine room + return new Scene103(vm); + case 104: // Ocean, northwest cliff + return new Scene104(vm); + case 105: // Ocean, northeast cliff with mine + return new Scene105(vm); + case 106: // Ocean, outside ship + return new Scene106(vm); + case 107: // Ocean, bushes + return new Scene107(vm); + case 108: // Ocean, southwest cliff + return new Scene108(vm); + case 109: // Ocean, tunnel + return new Scene109(vm); + case 110: // Ocean, cave with tunnel + return new Scene110(vm); + case 111: // Cave with pool and opening + return new Scene111(vm); + case 112: // cutscene, looking at view screen + return new Scene112(vm); + + // Scene group #2 (island) + case 201: // outside teleporter + return new Scene201(vm); + case 202: // village + return new Scene202(vm); + case 203: // tree with Rhotunda (fat woman) + return new Scene203(vm); + case 205: // village + return new Scene205(vm); + case 207: // outside witch doctor's hut + return new Scene207(vm); + case 208: // pit with leaves (trap) + return new Scene208(vm); + case 209: // palm tree and bamboo plant + return new Scene209(vm); + case 210: // outside native woman's hut + return new Scene210(vm); + case 211: // palm tree with monkey + return new Scene211(vm); + case 212: // outside cave + return new Scene212(vm); + case 213: // inside teleporter + return new Scene213(vm); + case 214: // inside witch doctor's hut + return new Scene214(vm); + case 215: // inside native woman's hut + return new Scene215(vm); + case 216: // cutscene, monitor showing Rex and native woman + return new Scene216(vm); + + // Scene group #3 (women's base, cell block) + case 301: // outside teleporter (before chaos) + return new Scene301(vm); + case 302: // room with statue (before chaos) + return new Scene302(vm); + case 303: // western corridor (before chaos) + return new Scene303(vm); + case 304: // crossing with traffic light (before chaos) + return new Scene304(vm); + case 307: // Rex's cell (before chaos) + return new Scene307(vm); + case 308: // sauropod's cell (before chaos) + return new Scene308(vm); + case 309: // multihand monster's cell (before chaos) + return new Scene309(vm); + case 310: // empty cell (before chaos) + return new Scene310(vm); + case 311: // warden's desk (before chaos) + return new Scene311(vm); + case 313: // air shaft overview + return new Scene313(vm); + case 316: // Gender Bender + return new Scene316(vm); + case 318: // doctor's gurney + return new Scene318(vm); + case 319: // doctor Slache closeup (lying on the gurney) + return new Scene319(vm); + case 320: // warden's desk closeup / monitors + return new Scene320(vm); + case 321: // gender bender sex change sequence + return new Scene321(vm); + case 322: // inside teleporter + return new Scene322(vm); + case 351: // outside teleporter (after chaos) + return new Scene351(vm); + case 352: // room with statue (after chaos) + return new Scene352(vm); + case 353: // western corridor (after chaos) + return new Scene353(vm); + case 354: // crossing with traffic light (after chaos) + return new Scene354(vm); + case 357: // Rex's cell (after chaos) + return new Scene357(vm); + case 358: // sauropod's cell (after chaos) + return new Scene358(vm); + case 359: // multihand monster's cell (after chaos) + return new Scene359(vm); + case 360: // empty cell (after chaos) + return new Scene360(vm); + case 361: // warden's desk (after chaos) + return new Scene361(vm); + case 366: // air shaft ending at Gender Bender + return new Scene366(vm); + case 387: // air shaft ending at cell + return new Scene387(vm); + case 388: // air shaft ending at sauropod's cell + return new Scene388(vm); + case 389: // air shaft ending at multihand monster's cell (before chaos) + return new Scene389(vm); + case 390: // air shaft ending at cell + return new Scene390(vm); + case 391: // air shaft ending at warden's desk + return new Scene391(vm); + case 399: // air shaft ending at multihand monster's cell (after chaos) + return new Scene399(vm); + + // Scene group #4 (women's base) + case 401: // outside bar + return new Scene401(vm); + case 402: // inside bar + return new Scene402(vm); + case 405: // outside armory + return new Scene405(vm); + case 406: // outside storage room + return new Scene406(vm); + case 407: // eastern corridor + return new Scene407(vm); + case 408: // inside armory + return new Scene408(vm); + case 409: // inside female only teleporter + return new Scene409(vm); + case 410: // inside storage room + return new Scene410(vm); + case 411: // lab + return new Scene411(vm); + case 413: // outside female only teleporter + return new Scene413(vm); + + // Scene group #5 (men's city, lower floor) + case 501: // outside car + return new Scene501(vm); + case 502: // inside male only teleporter + return new Scene502(vm); + case 503: // guard tower + return new Scene503(vm); + case 504: // inside car + return new Scene504(vm); + case 505: // car view screen + return new Scene505(vm); + case 506: // shopping street + return new Scene506(vm); + case 507: // inside software house + return new Scene507(vm); + case 508: // laser cannon + return new Scene508(vm); + case 511: // outside pleasure dome + return new Scene511(vm); + case 512: // inside pleasure dome + return new Scene512(vm); + case 513: // outside mall + return new Scene513(vm); + case 515: // overview + return new Scene515(vm); + case 551: // outside teleporter (with skeleton) + return new Scene551(vm); + + // Scene group #6 (men's city, upper floor) + case 601: // outside Bruce's house + return new Scene601(vm); + case 602: // Bruce's house, living room + return new Scene602(vm); + case 603: // Bruce's house, bedroom + return new Scene603(vm); + case 604: // viewport + return new Scene604(vm); + case 605: // viewport closeup + return new Scene605(vm); + case 607: // outside Abdul's garage + return new Scene607(vm); + case 608: // inside Abdul's garage + return new Scene608(vm); + case 609: // outside Buckluster video store + return new Scene609(vm); + case 610: // inside Buckluster video store + return new Scene610(vm); + case 611: // back alley + return new Scene611(vm); + case 612: // expressway / maintenance building + return new Scene612(vm); + case 620: // cutscene, viewport glass breaking + return new Scene620(vm); + + // Scene group #7 (submerged men's city / upper floor) + case 701: // outside elevator (after city is submerged) + return new Scene701(vm); + case 702: // outside teleporter (after city is submerged) + return new Scene702(vm); + case 703: // water + return new Scene703(vm); + case 704: // water, building in the distance + return new Scene704(vm); + case 705: // water, outside building + return new Scene705(vm); + case 706: // inside building, pedestral room, outside teleporter + return new Scene706(vm); + case 707: // teleporter + return new Scene707(vm); + case 710: // looking at pedestral room through binoculars + return new Scene710(vm); + case 711: // inside teleporter + return new Scene711(vm); + case 751: // outside elevator (before city is submerged) + return new Scene751(vm); + case 752: // outside teleporter (before city is submerged) + return new Scene752(vm); + + // Scene group #8 + case 801: // control room, outside teleporter + return new Scene801(vm); + case 802: // launch pad with destroyed ship + return new Scene802(vm); + case 803: // empty launch pad + return new Scene803(vm); + case 804: // inside Rex's ship - cockpit + return new Scene804(vm); + case 805: // service panel + return new Scene805(vm); + case 807: // teleporter + return new Scene807(vm); + case 808: // antigrav control + return new Scene808(vm); + case 810: // cutscene: Rex's ship leaving the planet + return new Scene810(vm); + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +NebularScene::NebularScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GameNebular *>(vm->_game)->_globals), + _game(*static_cast<GameNebular *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String NebularScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoNebular::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoNebular::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +/*------------------------------------------------------------------------*/ + +SceneTeleporter::SceneTeleporter(MADSEngine *vm) : NebularScene(vm) { + _buttonTyped = -1; + _curCode = -1; + _digitCount = -1; + _curMessageId = -1; + _handSpriteId = -1; + _handSequenceId = -1; + _finishedCodeCounter = -1; + _meteorologistNextPlace = -1; + _meteorologistCurPlace = -1; + _teleporterSceneId = -1; +} + +int SceneTeleporter::teleporterAddress(int code, bool working) { + int limit = working ? 6 : 10; + + for (int i = 0; i < limit; i++) { + if (code == _globals[kTeleporterCode + i]) + return _globals[kTeleporterRoom + i]; + } + + return -1; +} + +Common::Point SceneTeleporter::teleporterComputeLocation() { + Common::Point result; + + switch (_buttonTyped) { + case 0: + result = Common::Point(179, 200); + break; + + case 1: + result = Common::Point(166, 170); + break; + + case 2: + result = Common::Point(179, 170); + break; + + case 3: + result = Common::Point(192, 170); + break; + + case 4: + result = Common::Point(166, 180); + break; + + case 5: + result = Common::Point(179, 180); + break; + + case 6: + result = Common::Point(192, 180); + break; + + case 7: + result = Common::Point(166, 190); + break; + + case 8: + result = Common::Point(179, 190); + break; + + case 9: + result = Common::Point(192, 190); + break; + + case 10: + result = Common::Point(194, 200); + break; + + case 11: + result = Common::Point(164, 200); + break; + + default: + error("teleporterComputeLocation() - Unexpected button pressed"); + } + + return result; +} + +void SceneTeleporter::teleporterHandleKey() { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + Common::Point msgPos = teleporterComputeLocation(); + _handSequenceId = _scene->_sequences.startReverseCycle(_handSpriteId, false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_handSequenceId, msgPos); + _scene->_sequences.setDepth(_handSequenceId, 2); + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_events->hideCursor(); + + } + break; + + case 1: + _scene->_sequences.addSubEntry(_handSequenceId, SEQUENCE_TRIGGER_SPRITE, 3, 3); + if (_buttonTyped <= 9) { + if (_digitCount < 4) { + _curCode *= 10; + _curCode += _buttonTyped; + _digitCount++; + _msgText = Common::String::format("%d", _curCode); + if (_digitCount < 4) + _msgText += "_"; + + if (_scene->_currentSceneId != 711) + _vm->_sound->command(32); + } + } else if (_buttonTyped == 11) { + _digitCount = 0; + _curCode = 0; + _msgText = "_"; + if (_scene->_currentSceneId != 711) + _vm->_sound->command(33); + } else if (_digitCount == 4) { + if (_scene->_currentSceneId != 711) + _finishedCodeCounter = 1; + + if (teleporterAddress(_curCode, true) > 0) { + _vm->_palette->setEntry(252, 0, 63, 0); + if (_scene->_currentSceneId != 711) + _vm->_sound->command(34); + } else { + _vm->_palette->setEntry(252, 63, 0, 0); + if (_scene->_currentSceneId != 711) + _vm->_sound->command(35); + } + } + + if (_scene->_currentSceneId != 711) { + if (_curMessageId >= 0) + _scene->_kernelMessages.remove(_curMessageId); + _curMessageId = _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText); + } + break; + + case 2: + if (_finishedCodeCounter == 1) { + _finishedCodeCounter++; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_nextSceneId = 202; + else { + _vm->_events->showCursor(); + int destination = teleporterAddress(_curCode, true); + + if (destination > 0) { + _globals[kTeleporterCommand] = 2; + _scene->_nextSceneId = _teleporterSceneId; + _globals[kTeleporterDestination] = destination; + } else { + _globals[kTeleporterCommand] = 4; + _scene->_nextSceneId = _teleporterSceneId; + } + } + } else if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_sequences.addTimer(30, 230 + _meteorologistCurPlace); + + break; + + case 3: + if (!_finishedCodeCounter) { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) { + _game._player._stepEnabled = true; + _vm->_events->showCursor(); + } + } + break; + + default: + break; + } +} + +void SceneTeleporter::teleporterEnter() { + _game._player._visible = false; + _game._player._stepEnabled = (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL); + _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_TELE); + _scene->_textSpacing = 0; + _curCode = 0; + _digitCount = 0; + _finishedCodeCounter = 0; + _curMessageId = -1; + _msgText = "_"; + + if (_scene->_priorSceneId == -2) + _scene->_priorSceneId = _globals[kTeleporterDestination]; + + if (_scene->_priorSceneId < 101) + _scene->_priorSceneId = 201; + + _globals[kTeleporterDestination] = _scene->_priorSceneId; + _vm->_palette->setEntry(252, 63, 63, 0); + _vm->_palette->setEntry(253, 0, 0, 0); + _teleporterSceneId = _scene->_priorSceneId; + if (_teleporterSceneId == 202) + _teleporterSceneId = 201; + + int tmpVal = 0; + for (int i = 0; i < 10; i++) { + if (_teleporterSceneId == _globals[kTeleporterRoom + i]) + tmpVal = _globals[kTeleporterRoom + i]; + + if (_globals[kTeleporterRoom + i] == 301) + _meteorologistNextPlace = _globals[kTeleporterCode + i]; + } + + Common::String msgText2 = Common::String::format("#%.4d", tmpVal); + + if (_scene->_currentSceneId != 711) { + _scene->_kernelMessages.add(Common::Point(133, 34), 0, 32, 0, 9999999, msgText2); + _scene->_kernelMessages.add(Common::Point(143, 61), 0xFDFC, 16, 0, 9999999, _msgText); + } + + _meteorologistCurPlace = 0; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _scene->_sequences.addTimer(30, 230); + + _vm->_sound->command(36); +} + +bool SceneTeleporter::teleporterActions() { + bool retVal = false; + static int _buttonList[12] = { NOUN_0_KEY, NOUN_1_KEY, NOUN_2_KEY, NOUN_3_KEY, NOUN_4_KEY, NOUN_5_KEY, NOUN_6_KEY, NOUN_7_KEY, NOUN_8_KEY, NOUN_9_KEY, NOUN_SMILE_KEY, NOUN_FROWN_KEY }; + + if (_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) { + for (int i = 0; i < 12; i++) { + if (_action._activeAction._objectNameId == _buttonList[i]) + _buttonTyped = i; + } + teleporterHandleKey(); + retVal = true; + } + + if (_action.isAction(VERB_EXIT_FROM, NOUN_DEVICE)) { + _globals[kTeleporterCommand] = 3; + _scene->_nextSceneId = _teleporterSceneId; + retVal = true; + } + + return (retVal); +} + +void SceneTeleporter::teleporterStep() { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + return; + + if (_game._trigger >= 230) { + int place = _game._trigger - 230; + int digit; + + if (place < 4) { + digit = _meteorologistNextPlace; + for (int i = 0; i < (3 - place); i++) + digit = digit / 10; + + digit = digit % 10; + } else { + digit = 10; + } + _buttonTyped = digit; + _meteorologistCurPlace = place + 1; + _game._trigger = -1; + } + + if (_game._trigger) { + if (_game._trigger == -1) + _game._trigger = 0; + teleporterHandleKey(); + } +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes.h b/engines/mads/nebular/nebular_scenes.h new file mode 100644 index 0000000000..6195395fd6 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes.h @@ -0,0 +1,1417 @@ +/* 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 MADS_NEBULAR_SCENES_H +#define MADS_NEBULAR_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/game_nebular.h" +#include "mads/nebular/globals_nebular.h" + + +namespace MADS { + +namespace Nebular { + +enum { + SEX_MALE = 0, SEX_UNKNOWN = 1, SEX_FEMALE = 2 +}; + +enum Verb { + VERB_ACTIVATE = 0x00E, + VERB_ATTACH = 0x019, + VERB_BREAK = 0x032, + VERB_BREATHE_AIR = 0x033, + VERB_CAST = 0x03D, + VERB_CLIMB_DOWN = 0x04E, + VERB_CLIMB_THROUGH = 0x04F, + VERB_CLIMB_UP = 0x050, + VERB_CUT = 0x061, + VERB_DAMPEN = 0x064, + VERB_DISASSEMBLE = 0x06C, + VERB_DIVE_INTO = 0x06D, + VERB_DRINK = 0x072, + VERB_EAT = 0x075, + VERB_EJECT = 0x076, + VERB_EMPTY = 0x077, + VERB_EXAMINE = 0x07D, + VERB_FILL = 0x085, + VERB_FONDLE = 0x08C, + VERB_HOSE_DOWN = 0x0A6, + VERB_IGNITE = 0x0B4, + VERB_INFLATE = 0x0B5, + VERB_INSERT = 0x0B6, + VERB_INSPECT = 0x0B7, + VERB_GNAW_ON = 0x098, + VERB_GORGE_ON = 0x099, + VERB_HURL = 0x0A9, + VERB_LICK = 0x0CB, + VERB_LOOK_AT = 0x0D1, + VERB_LOOK_IN = 0x0D2, + VERB_LOOK_THROUGH = 0x0D3, + VERB_PEER_THROUGH = 0x103, + VERB_PLAY = 0x112, + VERB_PRESS = 0x11A, + VERB_PRY = 0x11C, + VERB_READ = 0x11F, + VERB_SET = 0x132, + VERB_SHAKE_HANDS = 0x133, + VERB_SHARPEN = 0x134, + VERB_SHOOT = 0x13A, + VERB_SIT_IN = 0x13F, + VERB_SMELL = 0x147, + VERB_SNIFF = 0x149, + VERB_STARE_AT = 0x155, + VERB_SWIM_ACROSS = 0x159, + VERB_SWIM_INTO = 0x15A, + VERB_SWIM_THROUGH = 0x15B, + VERB_SWIM_TO = 0x15C, + VERB_SWIM_TOWARDS = 0x15D, + VERB_SWIM_UNDER = 0x15E, + VERB_TIE = 0x170, + VERB_UNLOCK = 0x17B, + VERB_WALK_ACROSS = 0x187, + VERB_WALK_INSIDE = 0x188, + VERB_WALK_OUTSIDE = 0x18A, + VERB_WALK_THROUGH = 0x18B, + VERB_WALK_TOWARDS = 0x18C, + VERB_WEAR = 0x191, + VERB_WALK_DOWN = 0x1AD, + VERB_LEAVE = 0x1CD, + VERB_EXIT_FROM = 0x1CE, + VERB_USE = 0x20C, + VERB_GAZE_INTO = 0x212, + VERB_SIT_AT = 0x21F, + VERB_WALK_UP = 0x227, + VERB_WALK_INTO = 0x242, + VERB_EXIT = 0x298, + VERB_WALK_ONTO = 0x2B5, + VERB_RETURN_TO = 0x2D5, + VERB_CLIMB_INTO = 0x2F7, + VERB_STEP_INTO = 0x2F9, + VERB_CRAWL_TO = 0x2FB, + VERB_CRAWL_DOWN = 0x301, + VERB_SIT_ON = 0x30B, + VERB_WALK_ALONG = 0x312, + VERB_GET_INSIDE = 0x325, + VERB_WALK = 0x32F, + VERB_REFLECT = 0x365, + VERB_GET_INTO = 0x36A, + VERB_APPLY = 0x3A6, + VERB_STEER_TOWARDS = 0x3B1, + VERB_NIBBLE_ON = 0x3B7, + VERB_ENTER = 0x3B8, + VERB_PUT_DOWN = 0x46F, + VERB_INSTALL = 0x474, + VERB_REMOVE = 0x476, + VERB_DEFACE = 0x489, + VERB_MASSAGE = 0x4A3, + VERB_MANGLE = 0x4A4, + VERB_RUB = 0x4A5, + VERB_JUGGLE = 0x4A6, + VERB_SMASH = 0x4A7, + VERB_GUZZLE = 0x4A8, + VERB_FOLD = 0x4AB, + VERB_SPINDLE = 0x4AC, + VERB_MUTILATE = 0x4AD +}; + +enum Noun { + //NOUN_GAME = 0x1, + //NOUN_QSAVE = 0x2, + //NOUN_LOOK = 0x3, + //NOUN_TAKE = 0x4, + //NOUN_PUSH = 0x5, + //NOUN_OPEN = 0x6, + //NOUN_PUT = 0x7, + //NOUN_TALK_TO = 0x8, + //NOUN_GIVE = 0x9, + //NOUN_PULL = 0xA, + //NOUN_CLOSE = 0xB, + //NOUN_THROW = 0xC, + //NOUN_WALK_TO = 0xD, + //NOUN_ACTIVATE = 0xE, + //NOUN_ADMIRE = 0xF, + NOUN_ADSM = 0x10, + NOUN_AIR_VENT = 0x11, + NOUN_ALOE_PLANT = 0x12, + NOUN_ANEMONE = 0x13, + NOUN_ANOMOMETER = 0x14, + NOUN_AREA_AROUND_HUT = 0x15, + NOUN_AREA_TO_SOUTH = 0x16, + NOUN_AREA_TO_WEST = 0x17, + NOUN_AROMATIC_MEAT = 0x18, + //NOUN_ATTACH = 0x19, + NOUN_AUDIO_TAPE = 0x1A, + NOUN_AUXILIARY_POWER = 0x1B, + NOUN_BADMITTON_BRAT = 0x1C, + NOUN_BAG = 0x1D, + NOUN_BAMBOO_TREE = 0x1E, + NOUN_BATS = 0x1F, + NOUN_BAWLEMER_ORIOLE_HUN = 0x20, + NOUN_BEAR_RUG = 0x21, + NOUN_BEASTLY_TROPHY = 0x22, + NOUN_BIG_LEAVES = 0x23, + NOUN_BIG_PIPES = 0x24, + NOUN_BIG_SKY = 0x25, + NOUN_BIG_STONE = 0x26, + NOUN_BINOCULARS = 0x27, + NOUN_BIRDIES = 0x28, + NOUN_BLOWGUN = 0x29, + NOUN_BOMB = 0x2A, + NOUN_BOMBS = 0x2B, + NOUN_BONE = 0x2C, + NOUN_BONES = 0x2D, + NOUN_BOTTLE = 0x2E, + NOUN_BOULDER = 0x2F, + NOUN_BOULDERS = 0x30, + NOUN_BRA = 0x31, + //NOUN_BREAK = 0x32, + //NOUN_BREATHE_AIR = 0x33, + NOUN_BULKHEAD = 0x34, + NOUN_BURGER = 0x35, + NOUN_BURN = 0x36, + NOUN_BURNT_OUT_WARP_COIL = 0x37, + NOUN_BUSH_LIKE_FORMATION = 0x38, + NOUN_BUSHES = 0x39, + NOUN_BUSHY_FERN = 0x3A, + NOUN_CACTUS = 0x3B, + NOUN_CARD = 0x3C, + //NOUN_CAST = 0x3D, + NOUN_CAULDRON = 0x3E, + NOUN_CAVE = 0x3F, + NOUN_CAVE_CEILING = 0x40, + NOUN_CAVE_ENTRANCE = 0x41, + NOUN_CAVE_EXIT = 0x42, + NOUN_CAVE_FLOOR = 0x43, + NOUN_CAVE_TO_EAST = 0x44, + NOUN_CAVE_WALL = 0x45, + NOUN_CEILING = 0x46, + NOUN_CHAIR = 0x47, + NOUN_CHARGE_CASES = 0x48, + NOUN_CHICKEN = 0x49, + NOUN_CHICKEN_BOMB = 0x4A, + NOUN_CLEARING_TO_EAST = 0x4B, + NOUN_CLEARING_TO_SOUTH = 0x4C, + NOUN_CLIFF_FACE = 0x4D, + NOUN_CLIMB_DOWN = 0x4E, + NOUN_CLIMB_THROUGH = 0x4F, + NOUN_CLIMB_UP = 0x50, + NOUN_CLOCK = 0x51, + NOUN_CLOSET = 0x52, + NOUN_CLOTHESLINE = 0x53, + NOUN_CLUMP_OF_TREES = 0x54, + NOUN_COAL = 0x55, + NOUN_COCOANUT = 0x56, + NOUN_COMPACT_CASE = 0x57, + NOUN_COMPUTER_GAME = 0x58, + NOUN_CONTROL_PANEL = 0x59, + NOUN_CORAL = 0x5A, + NOUN_CRAB = 0x5B, + NOUN_CREDIT_CHIP = 0x5C, + NOUN_CUMULOUS_CLOUD = 0x5D, + NOUN_CURIOUS_WEED_PATCH = 0x5E, + NOUN_CURTAIN = 0x5F, + NOUN_CURTAINS = 0x60, + //NOUN_CUT = 0x61, + NOUN_DAMAGE_CONTROL = 0x62, + NOUN_DAMAGE_CONTROL_PANEL = 0x63, + //NOUN_DAMPEN = 0x64, + NOUN_DEAD_FISH = 0x65, + NOUN_DEAD_PURPLE_MONSTER = 0x66, + NOUN_DECLIVITOUS_CHASM = 0x67, + NOUN_DEEP_DARK_FOREST = 0x68, + NOUN_DENSE_FOREST = 0x69, + NOUN_DETONATORS = 0x6A, + NOUN_DINO_MITE = 0x6B, + //NOUN_DISASSEMBLE = 0x6C, + //NOUN_DIVE_INTO = 0x6D, + NOUN_DOOR = 0x6E, + NOUN_DOOR_KEY = 0x6F, + NOUN_DOORWAY = 0x70, + NOUN_DRAWER = 0x71, + //NOUN_DRINK = 0x72, + NOUN_DURAFAIL_CELLS = 0x73, + NOUN_EASTERN_CLIFF_FACE = 0x74, + //NOUN_EAT = 0x75, + //NOUN_EJECT = 0x76, + //NOUN_EMPTY = 0x77, + NOUN_ENGINEERING_CONTROLS = 0x78, + NOUN_ENGINEERING_SECTION = 0x79, + NOUN_ENTER_KEY = 0x7A, + NOUN_ESCAPE_HATCH = 0x7B, + NOUN_ESTROTOXIN = 0x7C, + //NOUN_EXAMINE = 0x7D, + NOUN_EXPERIMENT_CAGE = 0x7E, + NOUN_EXTINGUISH = 0x7F, + NOUN_FACE_ID = 0x80, + NOUN_FERN = 0x81, + NOUN_FIELD_TO_NORTH = 0x82, + NOUN_FIELD_TO_SOUTH = 0x83, + NOUN_FIELD_TO_WEST = 0x84, + //NOUN_FILL = 0x85, + NOUN_FIRE_PIT = 0x86, + NOUN_FISHING_LINE = 0x87, + NOUN_FISHING_ROD = 0x88, + NOUN_FLOOR = 0x89, + NOUN_FLOOR_OF_HUT = 0x8A, + NOUN_FLOOR_TILE = 0x8B, + //NOUN_FONDLE = 0x8C, + NOUN_FOREST_TO_EAST = 0x8D, + NOUN_FRONT_WINDOW = 0x8E, + NOUN_FUNGOIDS = 0x8F, + NOUN_FURNACE = 0x90, + NOUN_FUZZY_DICE = 0x91, + //NOUN_GAZE = 0x92, + //NOUN_GAZE_AT = 0x93, + //NOUN_GAZE_IN = 0x94, + //NOUN_GLANCE_AT = 0x95, + NOUN_GLOVE = 0x96, + NOUN_GNARLY_SHRUB = 0x97, + //NOUN_GNAW_ON = 0x98, + //NOUN_GORGE_ON = 0x99, + NOUN_GRAIN_ALCHOHOL = 0x9A, + NOUN_GRASSLAND_TO_EAST = 0x9B, + NOUN_GRASSLAND_TO_SOUTH = 0x9C, + NOUN_GRASSY_AREA = 0x9D, + NOUN_GRASSY_AREA_TO_NORTH = 0x9E, + NOUN_GRASSY_KNOLL = 0x9F, + //NOUN_GRIND = 0xA0, + NOUN_GROOVILACTIC_TREE = 0xA1, + NOUN_GUARDS_ARM = 0xA2, + NOUN_HATCHWAY = 0xA3, + //NOUN_HOOK_UP = 0xA4, + NOUN_HORIZON = 0xA5, + //NOUN_HOSE_DOWN = 0xA6, + NOUN_HOTPANTS = 0xA7, + NOUN_HULL = 0xA8, + //NOUN_HURL = 0xA9, + NOUN_HUT = 0xAA, + NOUN_HUT_AREA = 0xAB, + NOUN_HUT_TO_EAST = 0xAC, + NOUN_HUT_TO_SOUTH = 0xAD, + NOUN_HUT_TO_THE_SOUTH = 0xAE, + NOUN_HUT_TO_WEST = 0xAF, + NOUN_HUTS_TO_NORTH = 0xB0, + NOUN_HYDROSPANNER = 0xB1, + NOUN_HYPERDRIVE_JUMP_UNIT = 0xB2, + NOUN_ID_CARD = 0xB3, + //NOUN_IGNITE = 0xB4, + //NOUN_INFLATE = 0xB5, + //NOUN_INSERT = 0xB6, + //NOUN_INSPECT = 0xB7, + NOUN_JUNGLE = 0xB8, + NOUN_JUNGLE_TO_EAST = 0xB9, + NOUN_JUNGLE_TO_WEST = 0xBA, + NOUN_KEY_1 = 0xBB, + NOUN_KEY_2 = 0xBC, + NOUN_KEY_3 = 0xBD, + NOUN_KEY_4 = 0xBE, + NOUN_KEY_5 = 0xBF, + NOUN_KEY_6 = 0xC0, + NOUN_KEY_7 = 0xC1, + NOUN_KEY_8 = 0xC2, + NOUN_KEY_9 = 0xC3, + NOUN_KEYPAD = 0xC4, + NOUN_KNEELING_WOMAN = 0xC5, + NOUN_KNIFE = 0xC6, + NOUN_LADDER = 0xC7, + NOUN_LARGE_STALAGMITE = 0xC8, + //NOUN_LEER_AT = 0xC9, + NOUN_LIBRARY_COMPUTER = 0xCA, + //NOUN_LICK = 0xCB, + NOUN_LIFE_SUPPORT_SECTION = 0xCC, + NOUN_LIGHT = 0xCD, + //NOUN_LOAD = 0xCE, + //NOUN_LOCK = 0xCF, + NOUN_LOG = 0xD0, + //NOUN_LOOK_AT = 0xD1, + //NOUN_LOOK_IN = 0xD2, + //NOUN_LOOK_THROUGH = 0xD3, + NOUN_LOUNGE_AREA = 0xD4, + NOUN_LOVE_ALTAR = 0xD5, + NOUN_LOWLANDS = 0xD6, + NOUN_MACHINE = 0xD7, + NOUN_MAGNET = 0xD8, + NOUN_MAIN_AIRLOCK = 0xD9, + NOUN_MANTA_RAY = 0xDA, + NOUN_MARSHY_WETLANDS = 0xDB, + NOUN_MATCH = 0xDC, + NOUN_MEDICAL_WASTE = 0xDD, + NOUN_MEDICINE_CABINET = 0xDE, + NOUN_MEN_WHO_CAME_BEFORE = 0xDF, + NOUN_MINE = 0xE0, + NOUN_MIRROR = 0xE1, + NOUN_MONITOR = 0xE2, + NOUN_MONKEY = 0xE3, + NOUN_MONKEY_LIVER_JUICE = 0xE4, + NOUN_MONSTER_SLUDGE = 0xE5, + NOUN_MOUNTAIN = 0xE6, + NOUN_MOUNTAIN_RANGE = 0xE7, + NOUN_MOUNTAINS = 0xE8, + NOUN_MTAM = 0xE9, + NOUN_MUSHROOMS = 0xEA, + NOUN_NAVIGATION_CONTROLS = 0xEB, + NOUN_NORTH_PATH = 0xEC, + NOUN_NORTHERN_EXPOSURE = 0xED, + NOUN_NORTHERN_SEA_CLIFF = 0xEE, + NOUN_OBSTACLE = 0xEF, + NOUN_OCEAN_FLOOR = 0xF0, + NOUN_ODD_ROCK_FORMATION = 0xF1, + NOUN_OOGLY_BOOGLY_JUICE = 0xF2, + NOUN_OPEN_AREA_TO_EAST = 0xF3, + NOUN_OPEN_AREA_TO_NORTH = 0xF4, + NOUN_OPEN_AREA_TO_SOUTH = 0xF5, + NOUN_OPEN_AREA_TO_WEST = 0xF6, + NOUN_OPEN_FIELD = 0xF7, + NOUN_OUTER_HULL = 0xF8, + NOUN_OUTSIDE = 0xF9, + NOUN_OVEN = 0xFA, + NOUN_OVERHANG_TO_EAST = 0xFB, + NOUN_OVERHANG_TO_WEST = 0xFC, + NOUN_OVERHEAD_LAMP = 0xFD, + NOUN_PAD_OF_PAPER = 0xFE, + NOUN_PADLOCK_KEY = 0xFF, + NOUN_PALM_TREE = 0x100, + NOUN_PASSAGE_WAY_TO_SOUTH = 0x101, + NOUN_PASSION_PUSS = 0x102, + NOUN_PEER_THROUGH = 0x103, + NOUN_PENCIL = 0x104, + NOUN_PENDULOUS_CRAG = 0x105, + NOUN_PENLIGHT = 0x106, + NOUN_PHONE_CELLS = 0x107, + NOUN_PHONE_HANDSET = 0x108, + NOUN_PILE_OF_ROCKS = 0x109, + NOUN_PILLOW = 0x10A, + NOUN_PILOTS_CHAIR = 0x10B, + NOUN_PIPE = 0x10C, + NOUN_PIRANHA = 0x10D, + NOUN_PLANT = 0x10E, + NOUN_PLANT_STALK = 0x10F, + NOUN_PLANTS = 0x110, + NOUN_PLASTIC_JESUS = 0x111, + //NOUN_PLAY = 0x112, + NOUN_PLUNGER = 0x113, + NOUN_POISON_DARTS = 0x114, + NOUN_POLYCEMENT = 0x115, + NOUN_POOL = 0x116, + NOUN_POSTER = 0x117, + NOUN_POWER_STATUS_PANEL = 0x118, + NOUN_PRECIPICE = 0x119, + //NOUN_PRESS = 0x11A, + NOUN_PRESSURE_GAUGE = 0x11B, + //NOUN_PRY = 0x11C, + NOUN_RAGING_RIVER = 0x11D, + NOUN_RAMOLYAN_RUGBY_RATS = 0x11E, + //NOUN_READ = 0x11F, + NOUN_REARVIEW_MIRROR = 0x120, + NOUN_REBREATHER = 0x121, + NOUN_REFRIGERATOR = 0x122, + NOUN_REMOTE = 0x123, + NOUN_REPAIR_LIST = 0x124, + NOUN_RIVER = 0x125, + NOUN_RIVER_TO_WEST = 0x126, + NOUN_ROBO_KITCHEN = 0x127, + NOUN_ROCK = 0x128, + NOUN_ROCKS = 0x129, + NOUN_ROCKY_AREA = 0x12A, + NOUN_ROLLING_HILL = 0x12B, + NOUN_SCALPEL = 0x12C, + NOUN_SCENIC_MOUNTAINS = 0x12D, + NOUN_SEA_CLIFF = 0x12E, + NOUN_SEAWEED = 0x12F, + NOUN_SEAWEED_BANK = 0x130, + NOUN_SECURITY_CARD = 0x131, + //NOUN_SET = 0x132, + //NOUN_SHAKE_HANDS = 0x133, + //NOUN_SHARPEN = 0x134, + NOUN_SHIELD_ACCESS_PANEL = 0x135, + NOUN_SHIELD_GENERATOR = 0x136, + NOUN_SHIELD_MODULATOR = 0x137, + NOUN_SHIELD_STATUS_PANEL = 0x138, + NOUN_SHIP = 0x139, + //NOUN_SHOOT = 0x13A, + NOUN_SHOVEL = 0x13B, + //NOUN_SHRED = 0x13C, + NOUN_SHRUNKEN_HEADS = 0x13D, + NOUN_SINGED_MEAT = 0x13E, + //NOUN_SIT_IN = 0x13F, + NOUN_SKULL = 0x140, + NOUN_SKULL_AND_CROSSBONES = 0x141, + NOUN_SKY = 0x142, + //NOUN_SLEEP_ON = 0x143, + NOUN_SLITHERING_SNAKE = 0x144, + NOUN_SLUG_SECRETION = 0x145, + NOUN_SMALL_HOLE = 0x146, + //NOUN_SMELL = 0x147, + NOUN_SNAKE = 0x148, + //NOUN_SNIFF = 0x149, + //NOUN_SOAK = 0x14A, + NOUN_SPECIAL_KEY_1 = 0x14B, + NOUN_SPECIAL_KEY_2 = 0x14C, + NOUN_SPIDER = 0x14D, + NOUN_SPILT_MILK = 0x14E, + NOUN_SPIT_FIRE = 0x14F, + //NOUN_SPRAY = 0x150, + //NOUN_STAB = 0x151, + NOUN_STAIRS = 0x152, + NOUN_STALAGMITES = 0x153, + //NOUN_STAND_INSIDE = 0x154, + //NOUN_STARE_AT = 0x155, + NOUN_STEPS = 0x156, + NOUN_STUFFED_FISH = 0x157, + NOUN_SURFACE = 0x158, + //NOUN_SWIM_ACROSS = 0x159, + //NOUN_SWIM_INTO = 0x15A, + //NOUN_SWIM_THROUGH = 0x15B, + //NOUN_SWIM_TO = 0x15C, + //NOUN_SWIM_TOWARDS = 0x15D, + //NOUN_SWIM_UNDER = 0x15E, + NOUN_SWOOPING_CREATURE = 0x15F, + NOUN_TABLE = 0x160, + //NOUN_TAKE_LIVER = 0x161, + //NOUN_TAKE_OFF = 0x162, + //NOUN_TAKE_PAGE = 0x163, + NOUN_TALL_GRASS = 0x164, + NOUN_TAPE_PLAYER = 0x165, + NOUN_TARGET_COMPUTER = 0x166, + NOUN_TARGET_MODULE = 0x167, + NOUN_TARGETTING_COMPUTER = 0x168, + NOUN_TASMANIAN_DEVIL = 0x169, + NOUN_TASTY_TURKEY = 0x16A, + NOUN_TELEPORT_DEVICE = 0x16B, + NOUN_TELEPORTER = 0x16C, + NOUN_THATCHED_ROOF = 0x16D, + NOUN_THORNS = 0x16E, + NOUN_THORNY_BUSH = 0x16F, + //NOUN_TIE = 0x170, + NOUN_TIMEBOMB = 0x171, + NOUN_TIMER = 0x172, + NOUN_TIMER_MODULE = 0x173, + NOUN_TREE = 0x174, + NOUN_TREES = 0x175, + NOUN_TRODDEN_PATH = 0x176, + NOUN_TUBE = 0x177, + NOUN_TUNNEL = 0x178, + NOUN_TWINKIE_BUSH = 0x179, + NOUN_TWINKIFRUIT = 0x17A, + //NOUN_UNLOCK = 0x17B, + NOUN_UZI = 0x17C, + NOUN_VASE = 0x17D, + NOUN_VIDEO_GAME = 0x17E, + //NOUN_VIEW = 0x17F, + NOUN_VIEW_SCREEN = 0x180, + NOUN_VIEWPORT = 0x181, + NOUN_VILLAGE_AREA = 0x182, + NOUN_VILLAGE_TO_WEST = 0x183, + NOUN_VOLCANO = 0x184, + NOUN_VULTURE = 0x185, + NOUN_WAD_OF_CATTLE_PARTS = 0x186, + //NOUN_WALK_ACROSS = 0x187, + //NOUN_WALK_INSIDE = 0x188, + //NOUN_WALK_ON = 0x189, + //NOUN_WALK_OUTSIDE = 0x18A, + //NOUN_WALK_THROUGH = 0x18B, + //NOUN_WALK_TOWARDS = 0x18C, + NOUN_WALL = 0x18D, + NOUN_WATCH_TOWER = 0x18E, + NOUN_WATER = 0x18F, + NOUN_WEAPONS_DISPLAY = 0x190, + //NOUN_WEAR = 0x191, + NOUN_WEATHER_STATION = 0x192, + NOUN_WEATHER_VANE = 0x193, + NOUN_WEIGHT_MACHINE = 0x194, + NOUN_WESTERN_CLIFF_FACE = 0x195, + NOUN_WHEEL = 0x196, + NOUN_WINDOW = 0x197, + NOUN_WITCHDOCTOR_HUT = 0x198, + NOUN_WORKBENCH = 0x199, + //NOUN_WRITE_ON = 0x19A, + NOUN_YELLOW_BIRDY = 0x19B, + NOUN_GRASS = 0x19C, + NOUN_BOUNCING_REPTILE = 0x19D, + NOUN_DEEP_PIT = 0x19E, + NOUN_LOWLANDS_TO_NORTH = 0x19F, + NOUN_SMALL_BUSH = 0x1A0, + NOUN_SMALL_CACTUS = 0x1A1, + NOUN_ROCKY_AREA_TO_NORTH = 0x1A2, + NOUN_BAMBOO_LIKE_PLANT = 0x1A3, + NOUN_MOUNTAINSIDE = 0x1A4, + NOUN_FIELD = 0x1A5, + NOUN_GRASSY_FIELD = 0x1A6, + NOUN_CRAG = 0x1A7, + NOUN_HUGE_LEGS = 0x1A8, + NOUN_LEAF_COVERED_PIT = 0x1A9, + NOUN_PILE_OF_LEAVES = 0x1AA, + NOUN_OPEN_FIELD_TO_EAST = 0x1AB, + NOUN_LAWN = 0x1AC, + //NOUN_WALK_DOWN = 0x1AD, + NOUN_PATH_TO_WEST = 0x1AE, + NOUN_HEDGE = 0x1AF, + NOUN_VILLAGE_PATH = 0x1B0, + NOUN_PATH_TO_NORTHEAST = 0x1B1, + NOUN_JUNGLE_PATH = 0x1B2, + NOUN_THICK_UNDERGROWTH = 0x1B3, + NOUN_OCEAN = 0x1B4, + NOUN_OCEAN_IN_DISTANCE = 0x1B5, + NOUN_STRANGE_DEVICE = 0x1B6, + NOUN_BUSH = 0x1B7, + NOUN_ANEMOMETER = 0x1B8, + NOUN_ISLAND_IN_DISTANCE = 0x1B9, + NOUN_PATH = 0x1BA, + NOUN_TROPHY = 0x1BB, + NOUN_SPECIMEN_JARS = 0x1BC, + NOUN_BOWL = 0x1BD, + NOUN_LARGE_BOWL = 0x1BE, + NOUN_PATH_TO_NORTH = 0x1BF, + NOUN_HUT_TO_NORTH = 0x1C0, + NOUN_PATH_TO_EAST = 0x1C1, + NOUN_CHICKEN_ON_SPIT = 0x1C2, + NOUN_CAPTIVE_CREATURE = 0x1C3, + NOUN_TWINKIFRUIT_BUSH = 0x1C4, + NOUN_STREAM = 0x1C5, + NOUN_OPPOSITE_SHORE = 0x1C6, + NOUN_PATH_TO_SOUTH = 0x1C7, + NOUN_OPPOSITE_BANK = 0x1C8, + NOUN_BROKEN_LADDER = 0x1C9, + NOUN_BAG_OF_TWINKIFRUITS = 0x1CA, + NOUN_BED = 0x1CB, + NOUN_DISPLAY = 0x1CC, + //NOUN_LEAVE = 0x1CD, + //NOUN_EXIT_FROM = 0x1CE, + NOUN_DEVICE = 0x1CF, + NOUN_0_KEY = 0x1D0, + NOUN_1_KEY = 0x1D1, + NOUN_2_KEY = 0x1D2, + NOUN_3_KEY = 0x1D3, + NOUN_4_KEY = 0x1D4, + NOUN_5_KEY = 0x1D5, + NOUN_6_KEY = 0x1D6, + NOUN_7_KEY = 0x1D7, + NOUN_8_KEY = 0x1D8, + NOUN_9_KEY = 0x1D9, + NOUN_FROWN_KEY = 0x1DA, + NOUN_SMILE_KEY = 0x1DB, + NOUN_NATIVE_WOMAN = 0x1DC, + NOUN_YELLOW_BIRD = 0x1DD, + NOUN_BLEEPER = 0x1DE, + NOUN_SIZEMOMETER = 0x1DF, + NOUN_PANEL = 0x1E0, + NOUN_PRINTER = 0x1E1, + NOUN_HARD_DRIVE = 0x1E2, + NOUN_BATHROOM = 0x1E3, + NOUN_DESK = 0x1E4, + NOUN_PASSAGEWAY = 0x1E5, + NOUN_FIRE_HYDRANT = 0x1E6, + NOUN_FREEZER = 0x1E7, + NOUN_EQUIDIGITIZER = 0x1E8, + NOUN_VISION_VIEW = 0x1E9, + NOUN_TELEDETECTOR = 0x1EA, + NOUN_POLE = 0x1EB, + NOUN_TRANSPOSITION_DEVICE = 0x1EC, + NOUN_STATUESQUE = 0x1ED, + NOUN_TEMPERATURE_GAUGE = 0x1EE, + NOUN_CHECK = 0x1EF, + NOUN_WATCH = 0x1F0, + NOUN_ELECTRO_SCANNER = 0x1F1, + NOUN_HALL = 0x1F2, + NOUN_SCANNER = 0x1F3, + //NOUN_PLACE_HAND_ON = 0x1F4, + NOUN_SECURITY_MONITOR = 0x1F5, + NOUN_DIGITORAMA = 0x1F6, + NOUN_RAIL_BEAM = 0x1F7, + NOUN_VAULT = 0x1F8, + NOUN_HALLWAY = 0x1F9, + NOUN_PIPES = 0x1FA, + NOUN_AIR_VENT_GRATE = 0x1FB, + NOUN_SECURITY_OFFICE = 0x1FC, + NOUN_SIGNAL = 0x1FD, + NOUN_BLEEP = 0x1FE, + NOUN_BLIP = 0x1FF, + NOUN_LOFT = 0x200, + NOUN_ELECTRONIC_ANT_FARM = 0x201, + NOUN_ELECTRIC_WIRING = 0x202, + NOUN_SECURITY_PANEL = 0x203, + NOUN_CORRIDOR = 0x204, + NOUN_CIRCUIT_CONTROLS = 0x205, + NOUN_AIR_DUCT = 0x206, + NOUN_CELL_WALL = 0x207, + NOUN_LIGHTS = 0x208, + //NOUN_STARE_INTO = 0x209, + NOUN_CELL_CONTROLS = 0x20A, + NOUN_COMMODE = 0x20B, + //NOUN_USE = 0x20C, + NOUN_BASIN = 0x20D, + //NOUN_JUMP_INSIDE = 0x20E, + NOUN_PREVIOUS_CELL = 0x20F, + NOUN_NEXT_ROOM = 0x210, + NOUN_ZINK = 0x211, + //NOUN_GAZE_INTO = 0x212, + NOUN_THRONE = 0x213, + NOUN_SACK = 0x214, + NOUN_LIMB = 0x215, + NOUN_SINK = 0x216, + NOUN_JOHNNY_ON_THE_SPOT = 0x217, + NOUN_DEBRIS = 0x218, + NOUN_BUNK = 0x219, + NOUN_NEXT_CELL = 0x21A, + NOUN_TOILET = 0x21B, + NOUN_MONITOR_AREA = 0x21C, + NOUN_SIDEWALL = 0x21D, + NOUN_COFFEE_MUG = 0x21E, + //NOUN_SIT_AT = 0x21F, + NOUN_LIGHTING_FIXTURE = 0x220, + NOUN_MONITORS = 0x221, + NOUN_GENDER_CONTROLS = 0x222, + NOUN_NEURO_ANALYZER = 0x223, + NOUN_MOLECULAR_RECORDER = 0x224, + NOUN_MAINTENANCE_PANEL = 0x225, + NOUN_RAMP = 0x226, + //NOUN_WALK_UP = 0x227, + NOUN_SUBSONIC_ATOMIZER = 0x228, + NOUN_EIGHT_BALL = 0x229, + NOUN_DNA_INVERTER = 0x22A, + NOUN_DNA_CONVERTER = 0x22B, + NOUN_PLATFORM = 0x22C, + NOUN_GUINEA_PIG_TEST_BOX = 0x22D, + NOUN_GASEOUS_PROBE_WARPER = 0x22E, + NOUN_TOOL_CABINET = 0x22F, + NOUN_SURGICAL_BOXES = 0x230, + NOUN_FETAL_HEART_MONITOR = 0x231, + NOUN_XRAY_CABINET = 0x232, + NOUN_STERILIZATION_SINK = 0x233, + NOUN_DRIPOLATOR = 0x234, + NOUN_SHOCK_MACHINE = 0x235, + NOUN_INTERROGATION_TABLE = 0x236, + NOUN_LIE_DOWN_ON = 0x237, + //NOUN_DECIPHER = 0x238, + NOUN_GUARD = 0x239, + NOUN_RIP_IN_FLOOR = 0x23A, + NOUN_TELEPORT_AREA = 0x23B, + NOUN_BROKEN_BEAM = 0x23C, + NOUN_ROCK_CHUNK = 0x23D, + NOUN_BLOODY_CELL_WALL = 0x23E, + NOUN_WALL_BOARD = 0x23F, + NOUN_GENDER_SCANNER = 0x240, + NOUN_BAR = 0x241, + //NOUN_WALK_INTO = 0x242, + NOUN_HALLWAY_TO_SOUTH = 0x243, + NOUN_SIGN = 0x244, + NOUN_HALLWAY_TO_NORTH = 0x245, + NOUN_BOTTLES = 0x246, + NOUN_UPPER_DANCE_FLOOR = 0x247, + NOUN_DANCE_FLOOR = 0x248, + NOUN_RAILING = 0x249, + NOUN_BAR_STOOL = 0x24A, + NOUN_LADY = 0x24B, + NOUN_UPPER_LEVEL = 0x24C, + NOUN_ALCOVE = 0x24D, + NOUN_DISCO_BALL = 0x24E, + NOUN_LADIES = 0x24F, + NOUN_COACH_LAMP = 0x250, + NOUN_CARD_SLOT = 0x251, + NOUN_HOOP = 0x252, + NOUN_CANNONBALLS = 0x253, + NOUN_WATER_FOUNTAIN = 0x254, + NOUN_HALLWAY_TO_EAST = 0x255, + NOUN_HALLWAY_TO_WEST = 0x256, + NOUN_SUPPORT = 0x257, + NOUN_BACKBOARD = 0x258, + NOUN_WIDE_DOOR = 0x259, + NOUN_SIGN_POST = 0x25A, + NOUN_FIRE_EXTINGUISHER = 0x25B, + NOUN_TRASH = 0x25C, + NOUN_MISSILES = 0x25D, + NOUN_TANK = 0x25E, + NOUN_TWO_TON_WEIGHT = 0x25F, + NOUN_ONE_TON_TOMATO = 0x260, + NOUN_ANVIL = 0x261, + NOUN_MINUTEMAN_IV_ICBM = 0x262, + NOUN_CHEST = 0x263, + NOUN_ARMOR = 0x264, + NOUN_CARTON = 0x265, + NOUN_POWDER = 0x266, + NOUN_RAFT = 0x267, + NOUN_WHATZIT = 0x268, + NOUN_CATAPULT = 0x269, + NOUN_HAND_GRENADE = 0x26A, + NOUN_BARRELS = 0x26B, + NOUN_LOADING_RAMP = 0x26C, + NOUN_BLIMP = 0x26D, + NOUN_FLOUR = 0x26E, + NOUN_FLY_PAPER = 0x26F, + NOUN_RUG = 0x270, + NOUN_CARPET = 0x271, + NOUN_CAN = 0x272, + NOUN_RUBBER_DUCKIE = 0x273, + NOUN_GOLF_CLUBS = 0x274, + NOUN_RAT = 0x275, + NOUN_BARREL = 0x276, + NOUN_BUCKET_OF_TAR = 0x277, + NOUN_SACKS = 0x278, + NOUN_STORAGE = 0x279, + NOUN_120V_3_PHASE_400HZ = 0x27A, + NOUN_LAB_EQUIPMENT = 0x27B, + NOUN_AIR_HORN = 0x27C, + NOUN_JAR = 0x27D, + NOUN_SEVERED_CABLE = 0x27E, + NOUN_PROBE_ASSEMBLY = 0x27F, + NOUN_KNIFE_SWITCH = 0x280, + NOUN_WORK_BENCH = 0x281, + NOUN_HEATER = 0x282, + NOUN_TOXIC_WASTE = 0x283, + NOUN_EXPERIMENT = 0x284, + NOUN_DRAWING_BOARD = 0x285, + NOUN_MISHAP = 0x286, + NOUN_AIR_PURIFIER = 0x287, + NOUN_DUMMY = 0x288, + NOUN_PICTURE = 0x289, + NOUN_BAGGAGE_CHECK = 0x28A, + NOUN_DEPARTURE_SCHEDULE = 0x28B, + NOUN_SHADE_OF_PALE = 0x28C, + NOUN_ITINERARY = 0x28D, + NOUN_BARGAIN_VAT = 0x28E, + NOUN_PENCILS = 0x28F, + NOUN_PAD_IF_PAPER = 0x290, + NOUN_DEEPEST_DEPTHS = 0x291, + NOUN_ROLODEX = 0x292, + NOUN_MONA_TISA = 0x293, + NOUN_ABSTRACT_ART = 0x294, + NOUN_SPACE_QUESTING_VIII = 0x295, + NOUN_THEATRICAL_ART = 0x296, + NOUN_METAL_POLE = 0x297, + NOUN_EXIT = 0x298, + NOUN_SWIRLING_LIGHT = 0x299, + NOUN_REGISTER = 0x29A, + NOUN_PEACHY_BUNS = 0x29B, + NOUN_OUR_TOWN = 0x29C, + NOUN_EMBROIDERED_ART = 0x29D, + NOUN_GEORGE_BUSH_ALIKE = 0x29E, + NOUN_COUNTER = 0x29F, + NOUN_SENSOR = 0x2A0, + NOUN_SOFTWARE_INFORMATION = 0x2A1, + NOUN_WALK_BEHIND = 0x2A2, + NOUN_BARGAINS = 0x2A3, + NOUN_SCAN_LIGHT = 0x2A4, + NOUN_OLD_SOFTWARE_STAND = 0x2A5, + NOUN_SOFTWARE_SHELF = 0x2A6, + NOUN_HOTTEST_SOFTWARE = 0x2A7, + NOUN_GREAT_PAINTBALL_ART = 0x2A8, + NOUN_SCENIC_VISTA = 0x2A9, + NOUN_LASER = 0x2AA, + NOUN_LASER_JET = 0x2AB, + NOUN_LEVER = 0x2AC, + NOUN_BULLSEYE = 0x2AD, + NOUN_STAND = 0x2AE, + NOUN_CONTROL_STATION = 0x2AF, + NOUN_STRANGE_MONSTER = 0x2B0, + NOUN_GHASTLY_BEAST = 0x2B1, + //NOUN_GAWK_AT = 0x2B2, + NOUN_CORRIDOR_TO_SOUTH = 0x2B3, + NOUN_CORRIDOR_TO_NORTH = 0x2B4, + NOUN_WALK_ONTO = 0x2B5, + NOUN_ROCK_WALL = 0x2B6, + NOUN_WOMAN = 0x2B7, + NOUN_WOMEN = 0x2B8, + NOUN_CORRIDOR_TO_EAST = 0x2B9, + NOUN_CORRIDOR_TO_WEST = 0x2BA, + NOUN_AMMUNITION = 0x2BB, + NOUN_ARMORED_VEHICLE = 0x2BC, + NOUN_TOMATO = 0x2BD, + NOUN_MISSILE = 0x2BE, + NOUN_SUIT_OF_ARMOR = 0x2BF, + NOUN_POWDER_CONTAINER = 0x2C0, + NOUN_INFLATABLE_RAFT = 0x2C1, + NOUN_GRENADE = 0x2C2, + NOUN_FENCE = 0x2C3, + NOUN_WOODEN_STATUE = 0x2C4, + NOUN_CONVEYER_BELT = 0x2C5, + NOUN_CONTROLS = 0x2C6, + NOUN_EQUIPMENT = 0x2C7, + NOUN_SHELF = 0x2C8, + NOUN_CABINETS = 0x2C9, + NOUN_CONTROL_CONSOLE = 0x2CA, + NOUN_FAUCET = 0x2CB, + NOUN_PANEL_BOX = 0x2CC, + NOUN_STATUE = 0x2CD, + NOUN_GAUGE = 0x2CE, + NOUN_CIRCUIT_PANEL = 0x2CF, + NOUN_CATWALK = 0x2D0, + NOUN_CIRCUITS = 0x2D1, + NOUN_BLOOD_STAIN = 0x2D2, + NOUN_GRATE = 0x2D3, + NOUN_AIR_SHAFT = 0x2D4, + //NOUN_RETURN_TO = 0x2D5, + NOUN_FORMALDEHYDE = 0x2D6, + NOUN_PETROX = 0x2D7, + NOUN_SODIUM_BENZOATE = 0x2D8, + NOUN_GURNEY = 0x2D9, + NOUN_IRONING_BOARD = 0x2DA, + NOUN_LEFT_MONITOR = 0x2DB, + NOUN_RIGHT_MONITOR = 0x2DC, + NOUN_RED_BUTTON = 0x2DD, + NOUN_GREEN_BUTTON = 0x2DE, + NOUN_RIGHT_ONE_KEY = 0x2DF, + NOUN_RIGHT_1_KEY = 0x2E0, + NOUN_RIGHT_2_KEY = 0x2E1, + NOUN_RIGHT_3_KEY = 0x2E2, + NOUN_RIGHT_4_KEY = 0x2E3, + NOUN_RIGHT_5_KEY = 0x2E4, + NOUN_RIGHT_6_KEY = 0x2E5, + NOUN_RIGHT_7_KEY = 0x2E6, + NOUN_RIGHT_8_KEY = 0x2E7, + NOUN_LEFT_1_KEY = 0x2E8, + NOUN_LEFT_2_KEY = 0x2E9, + NOUN_LEFT_3_KEY = 0x2EA, + NOUN_LEFT_4_KEY = 0x2EB, + NOUN_CORRIDOR_WALL = 0x2EC, + NOUN_MUG = 0x2ED, + NOUN_DOUGHNUT = 0x2EE, + NOUN_SECURITY_STATION = 0x2EF, + NOUN_NEWSPAPER = 0x2F0, + NOUN_MAGAZINE = 0x2F1, + NOUN_CLIPBOARD = 0x2F2, + NOUN_PAPER_FOOTBALL = 0x2F3, + NOUN_YOUR_STUFF = 0x2F4, + NOUN_OTHER_STUFF = 0x2F5, + NOUN_LAMP = 0x2F6, + NOUN_CLIMB_INTO = 0x2F7, + NOUN_LIGHT_BULB = 0x2F8, + //NOUN_STEP_INTO = 0x2F9, + NOUN_ROOM = 0x2FA, + //NOUN_CRAWL_TO = 0x2FB, + NOUN_FOURTH_CELL = 0x2FC, + NOUN_THIRD_CELL = 0x2FD, + NOUN_SECOND_CELL = 0x2FE, + NOUN_FIRST_CELL = 0x2FF, + NOUN_EQUIPMENT_ROOM = 0x300, + //NOUN_CRAWL_DOWN = 0x301, + NOUN_DESCENDING_SHAFT = 0x302, + NOUN_SAUROPOD = 0x303, + NOUN_MONSTER = 0x304, + NOUN_FAKE_ID = 0x305, + NOUN_ALIEN_LIQUOR = 0x306, + NOUN_INTERN = 0x307, + NOUN_INSTRUMENT_TABLE = 0x308, + NOUN_WOMAN_ON_BALCONY = 0x309, + NOUN_WOMAN_IN_CHAIR = 0x30A, + //NOUN_SIT_ON = 0x30B, + NOUN_WOMAN_IN_ALCOVE = 0x30C, + NOUN_KETTLE = 0x30D, + NOUN_BARTENDER = 0x30E, + NOUN_WHISKEY = 0x30F, + NOUN_ALCOHOL = 0x310, + NOUN_RIM = 0x311, + //NOUN_WALK_ALONG = 0x312, + NOUN_SUBMERGED_CITY = 0x313, + NOUN_GOVERNORS_HOUSE = 0x314, + NOUN_RIM_TOWARDS_EAST = 0x315, + NOUN_CEMENT_PYLON = 0x316, + NOUN_ELEVATOR = 0x317, + NOUN_ELEVATOR_SHAFT = 0x318, + NOUN_CONVEYOR_BELT = 0x319, + NOUN_CANNON_BALLS = 0x31A, + NOUN_ELECTRICAL_OVERHANG = 0x31B, + NOUN_GUTTER_PIPE = 0x31C, + NOUN_SIDEWALK = 0x31D, + NOUN_STREET = 0x31E, + NOUN_BARRICADE = 0x31F, + NOUN_DOOR_CONTROL_SLOT = 0x320, + NOUN_STREET_TO_EAST = 0x321, + NOUN_SIDEWALK_TO_EAST = 0x322, + NOUN_BUILDING = 0x323, + NOUN_CAR = 0x324, + //NOUN_GET_INSIDE = 0x325, + NOUN_MARQUEE = 0x326, + NOUN_BUILDING_ENTRANCE = 0x327, + NOUN_GUARD_STATION = 0x328, + NOUN_TECHNICAL_EQUIPMENT = 0x329, + NOUN_GUARD_TURRET = 0x32A, + NOUN_PILLAR = 0x32B, + NOUN_PAPERS = 0x32C, + NOUN_FILE_CABINET = 0x32D, + NOUN_WINDOWS = 0x32E, + //NOUN_WALK = 0x32F, + NOUN_STORAGE_BOX = 0x330, + NOUN_WATER_COOLER = 0x331, + NOUN_BOX = 0x332, + NOUN_RIFLES = 0x333, + NOUN_SLINGSHOT = 0x334, + NOUN_MAUSOLEUM = 0x335, + NOUN_SOFTWARE_STORE = 0x336, + NOUN_CONCRETE_BUILDING = 0x337, + NOUN_HUMONGOUS_MONITOR = 0x338, + NOUN_SPACE_BIKE = 0x339, + NOUN_BILLBOARD = 0x33A, + NOUN_LACK_OF_NOOKIE_MOTEL = 0x33B, + NOUN_BIDETS_XCREETZA_HUT = 0x33C, + NOUN_BUILDINGS = 0x33D, + NOUN_SKYSCRAPER = 0x33E, + NOUN_SOFTWARE_LOGO = 0x33F, + NOUN_GIANT_TELESCOPE = 0x340, + NOUN_HANDLE = 0x341, + NOUN_HOLE = 0x342, + NOUN_LASER_BEAM = 0x343, + NOUN_PEDESTAL = 0x344, + NOUN_BOAT = 0x345, + NOUN_GIANT_MONUMENT = 0x346, + NOUN_ROPE = 0x347, + NOUN_SAND_BAR_RESTAURANT = 0x348, + NOUN_PORTHOLE = 0x349, + NOUN_TICKET_BOOTH = 0x34A, + NOUN_POLLYS_ENTRANCE = 0x34B, + NOUN_RESTAURANT_ENTRANCE = 0x34C, + NOUN_THE_PLEASURE_DOME = 0x34D, + NOUN_STARFISH = 0x34E, + NOUN_FLIPPER = 0x34F, + NOUN_SAND_DOLLAR = 0x350, + NOUN_SHELL = 0x351, + NOUN_GUEST_LIST = 0x352, + NOUN_WEIRD_ANIMAL_HEAD = 0x353, + NOUN_SHIPS_WHEEL = 0x354, + NOUN_HANDICAP_SIGN = 0x355, + NOUN_ELEVATOR_CONTROLS = 0x356, + NOUN_BRICK_WALL = 0x357, + NOUN_BIKE_RACK = 0x358, + NOUN_ODONALDS_SIGN = 0x359, + NOUN_ELEVATOR_ENTRANCE = 0x35A, + NOUN_SPECIAL_SALE_SIGN = 0x35B, + NOUN_ATTORNEYS_AT_LAW = 0x35C, + NOUN_SLEDGE_MALL = 0x35D, + NOUN_SKELETON = 0x35E, + NOUN_STRANGE_EQUIPMENT = 0x35F, + NOUN_STREET_TO_WEST = 0x360, + NOUN_SIDEWALK_TO_WEST = 0x361, + NOUN_TELEPORTER_ENTRANCE = 0x362, + NOUN_SOFTWARE_DOOR = 0x363, + NOUN_SPINACH_PATCH_DOLL = 0x364, + //NOUN_REFLECT = 0x365, + NOUN_REGISTER_DRAWER = 0x366, + NOUN_ELEVATOR_DOOR = 0x367, + NOUN_HYDRAULIC_SUPPORT = 0x368, + NOUN_EQUIPMENT_OVERHEAD = 0x369, + //NOUN_GET_INTO = 0x36A, + NOUN_WARNING_LABEL = 0x36B, + NOUN_NUCLEAR_SLINGSHOT = 0x36C, + NOUN_DISPLAY_CASE = 0x36D, + NOUN_PHOTON_RIFLES = 0x36E, + NOUN_MONITORING_EQUIPMENT = 0x36F, + NOUN_TELESCOPE = 0x370, + NOUN_MOTEL = 0x371, + NOUN_RESTAURANT = 0x372, + NOUN_SOFTWARE_STORE_SIGN = 0x373, + NOUN_ADVERTISING_POSTER = 0x374, + NOUN_ADVERTISEMENT = 0x375, + NOUN_OLD_SOFTWARE = 0x376, + NOUN_CASH_REGISTER = 0x377, + NOUN_ENTRANCE = 0x378, + NOUN_LASER_CANNON = 0x379, + NOUN_SAND_BAGS = 0x37A, + NOUN_PLEASURE_DOME = 0x37B, + NOUN_DOME_ENTRANCE = 0x37C, + NOUN_LABORATORY = 0x37D, + NOUN_STREET_TO_SOUTH = 0x37E, + NOUN_ELEVATOR_ACCESS_SLOT = 0x37F, + NOUN_CAR_CONTROLS = 0x380, + NOUN_SCENT_PACKET = 0x381, + NOUN_KITTY = 0x382, + NOUN_GLOVE_COMPARTMENT = 0x383, + NOUN_MOLDY_SOCK = 0x384, + NOUN_SODA_CANS = 0x385, + NOUN_WINDSHIELD = 0x386, + NOUN_DASHBOARD = 0x387, + NOUN_INTERIOR_OF_CAR = 0x388, + NOUN_VIEW_RIGHT_BUTTON = 0x389, + NOUN_BLACK_BUTTON = 0x38A, + NOUN_WHITE_BUTTON = 0x38B, + NOUN_INSIDE_OF_CAR = 0x38C, + NOUN_RIM_TOWARDS_WEST = 0x38D, + NOUN_CEMENT_BLOCK = 0x38E, + NOUN_CITY = 0x38F, + NOUN_SPEAKER = 0x390, + NOUN_EYE_CHART = 0x391, + NOUN_LAUNCH_PAD = 0x392, + NOUN_BUILDING_TO_WEST = 0x393, + NOUN_PAD_TO_EAST = 0x394, + NOUN_PAD_TO_WEST = 0x395, + NOUN_TOWER = 0x396, + NOUN_LOOK_OUT = 0x397, + NOUN_SERVICE_PANEL = 0x398, + NOUN_CRACK = 0x399, + NOUN_THROTTLE = 0x39A, + NOUN_GRAB = 0x39B, + NOUN_INSTRUMENTATION = 0x39C, + NOUN_TP = 0x39D, + NOUN_SEAT = 0x39E, + NOUN_STATUS_PANEL = 0x39F, + NOUN_SHIPS_CONTROLS = 0x3A0, + NOUN_PROFESSOR = 0x3A1, + NOUN_PROFESSORS_GURNEY = 0x3A2, + NOUN_WELCOME_MAT = 0x3A3, + NOUN_MELON_MUSH = 0x3A4, + NOUN_BADMINTON_BRAT = 0x3A5, + //NOUN_APPLY = 0x3A6, + NOUN_COMBINATION = 0x3A7, + NOUN_NOTE = 0x3A8, + NOUN_LECITHIN = 0x3A9, + NOUN_REPAIR_WOMAN = 0x3AA, + NOUN_EXPLOSIVES = 0x3AB, + NOUN_DOLLOP = 0x3AC, + NOUN_DROP = 0x3AD, + NOUN_DASH = 0x3AE, + NOUN_SPLASH = 0x3AF, + NOUN_DOCK_TO_SOUTH = 0x3B0, + //NOUN_STEER_TOWARDS = 0x3B1, + NOUN_BUILDING_TO_NORTH = 0x3B2, + NOUN_VOLCANO_RIM = 0x3B3, + NOUN_OPEN_WATER_TO_SOUTH = 0x3B4, + NOUN_PROJECTOR = 0x3B5, + NOUN_GUARDS_ARM2 = 0x3B6, + //NOUN_NIBBLE_ON = 0x3B7, + //NOUN_ENTER = 0x3B8, + NOUN_ = 0x3B9, + NOUN_TIMER_BUTTON_1 = 0x3BA, + NOUN_REMOTE_BUTTON_1 = 0x3BB, + NOUN_START_BUTTON_2 = 0x3BC, + NOUN_REMOTE_BUTTON_2 = 0x3BD, + NOUN_TIMER_BUTTON_2 = 0x3BE, + NOUN_START_BUTTON_1 = 0x3BF, + NOUN_ANTIGRAV_CONTROLS = 0x3C0, + NOUN_BRUCES_TREE = 0x3C1, + NOUN_COLISEUM = 0x3C2, + NOUN_BRUCES_GARDEN_ROOM = 0x3C3, + NOUN_FOUNTAIN = 0x3C4, + NOUN_HOUSE_OF_BRUCE = 0x3C5, + NOUN_CITY_BACKDROP = 0x3C6, + NOUN_BRUCES_BALCONY = 0x3C7, + NOUN_BRUCES_ENTRANCE = 0x3C8, + NOUN_BRUCES_LOGO = 0x3C9, + NOUN_LOUNGE_CHAIR = 0x3CA, + NOUN_LIVING_ROOM_FLOOR = 0x3CB, + NOUN_LIVINGROOM_FLOOR = 0x3CC, + NOUN_PERFUME_BOTTLE = 0x3CD, + NOUN_COOL_NEON_LIGHT = 0x3CE, + NOUN_FLOWER_POT = 0x3CF, + NOUN_COFFEE_TABLE = 0x3D0, + NOUN_FLOWERS = 0x3D1, + NOUN_ART_DECO_CHAIR = 0x3D2, + NOUN_SAFE = 0x3D3, + NOUN_SPLASHY_DECOR = 0x3D4, + NOUN_THEATRICAL_FACES = 0x3D5, + NOUN_ART_DECO_PIECE = 0x3D6, + NOUN_END_OF_ROOM = 0x3D7, + NOUN_FIREPLACE = 0x3D8, + NOUN_ARTWORK = 0x3D9, + NOUN_COOL_NEON_LIGHTS = 0x3DA, + NOUN_GLASS_PLATED_WINDOW = 0x3DB, + NOUN_BEDROOM_FLOOR = 0x3DC, + NOUN_BAUBLE = 0x3DD, + NOUN_SNAPSHOT = 0x3DE, + NOUN_PERFUME = 0x3DF, + NOUN_CLAPBOARD = 0x3E0, + NOUN_BERET = 0x3E1, + NOUN_HORSE_WHIP = 0x3E2, + NOUN_CORNER_TABLE = 0x3E3, + NOUN_BOA = 0x3E4, + NOUN_WIG_STAND = 0x3E5, + NOUN_PARTITION = 0x3E6, + NOUN_MEGAPHONE = 0x3E7, + NOUN_SLIP = 0x3E8, + NOUN_SCONCE = 0x3E9, + NOUN_VANITY = 0x3EA, + NOUN_BEDBOARD = 0x3EB, + NOUN_LOVE_SEAT = 0x3EC, + NOUN_SOUVENIR_TICKETS = 0x3ED, + NOUN_REVIEW = 0x3EE, + NOUN_BRUCE_AT_THE_GALA = 0x3EF, + NOUN_ART_DECO_RUG = 0x3F0, + NOUN_LIVINGROOM = 0x3F1, + NOUN_SCULPTURE = 0x3F2, + NOUN_SPECIMEN_EPITHET = 0x3F3, + NOUN_VENT = 0x3F4, + NOUN_FLOWER_BOX = 0x3F5, + NOUN_LEDGE = 0x3F6, + NOUN_BOLT = 0x3F7, + NOUN_OBSERVATION_WINDOW = 0x3F8, + NOUN_AIR_HOSE = 0x3F9, + NOUN_AUTO_SHOP = 0x3FA, + NOUN_MANHOLE = 0x3FB, + NOUN_AUTO_SHOP_ENTRANCE = 0x3FC, + NOUN_BROKEN_WINDOW = 0x3FD, + NOUN_WOMANHOLE = 0x3FE, + NOUN_GARAGE_DOOR = 0x3FF, + NOUN_SCRATCH_PAD = 0x400, + NOUN_GAS_PRICES = 0x401, + NOUN_UP_BUTTON = 0x402, + NOUN_DOWN_BUTTON = 0x403, + NOUN_SPARE_PARTS_LIST = 0x404, + NOUN_SKYLIGHT = 0x405, + NOUN_TOOL_BOX = 0x406, + NOUN_CAR_LIFT = 0x407, + NOUN_CAR_SEAT = 0x408, + NOUN_GARAGE_FLOOR = 0x409, + NOUN_GARAGE_DOOR_CONTROLS = 0x40A, + NOUN_AMISH_HAT = 0x40B, + NOUN_JACK = 0x40C, + NOUN_COILS = 0x40D, + NOUN_OIL_CAN = 0x40E, + NOUN_FAN_BELTS = 0x40F, + NOUN_REAR_OF_GARAGE = 0x410, + NOUN_FRONT_OF_GARAGE = 0x411, + NOUN_MUFFLER = 0x412, + NOUN_SPARE_PART = 0x413, + NOUN_HUBCAP = 0x414, + NOUN_CANDLE = 0x415, + NOUN_RATES = 0x416, + NOUN_GREASE_CAN = 0x417, + NOUN_CALENDAR = 0x418, + NOUN_FORK_LIFT = 0x419, + NOUN_TRASH_CAN = 0x41A, + NOUN_SHAKER_CHAIR = 0x41B, + NOUN_QUARTER_PANEL = 0x41C, + NOUN_AREA_BEHIND_CAR = 0x41D, + NOUN_DANGER_ZONE = 0x41E, + NOUN_NEWSSTAND = 0x41F, + NOUN_LADY_GODIVA_MONUMENT = 0x420, + NOUN_SPOT_A_POT = 0x421, + NOUN_GUARD_RAIL = 0x422, + NOUN_ALLEY = 0x423, + NOUN_DITCH = 0x424, + NOUN_VIDEO_STORE_DOOR = 0x425, + NOUN_BUCKLUSTER_MARQUEE = 0x426, + NOUN_VIDEO_STORE = 0x427, + NOUN_HORMONE_BILLBOARD = 0x428, + NOUN_PHONE_ANTENNA = 0x429, + NOUN_RETURN_SLOT = 0x42A, + NOUN_NOOSE = 0x42B, + NOUN_COMEDY_VIDEOS = 0x42C, + NOUN_SMELLY_SNEAKER = 0x42D, + NOUN_PIPPYS_STOCKING = 0x42E, + NOUN_PHONE_CRADLE = 0x42F, + NOUN_DRAMA_VIDEOS = 0x430, + NOUN_SPOTLIGHT = 0x431, + NOUN_STOREROOM_FLOOR = 0x432, + NOUN_ALL_SALES_FINAL = 0x433, + NOUN_MACHOPROSE_TEE_SHIRT = 0x434, + NOUN_UNKNOWN_COMIC_HANDS = 0x435, + NOUN_WET_CEMENT = 0x436, + NOUN_PIPPYS_TINY_IMPRINT = 0x437, + NOUN_OBNOXIOUS_DOG_PAWS = 0x438, + NOUN_LEG_AND_A_LEG_JEANS = 0x439, + NOUN_VIDEO_STORE_EXIT = 0x43A, + NOUN_AISLE = 0x43B, + NOUN_VIDEO_MONITOR = 0x43C, + NOUN_POLLY_PIGS_IMPRINT = 0x43D, + NOUN_JOHN_WYNNS_IMPRINT = 0x43E, + NOUN_MR_NEDS_IMPRINT = 0x43F, + NOUN_PEG_LEG_PETE_IMPRINT = 0x440, + NOUN_MARX_BROS_POSTER = 0x441, + NOUN_PIPPY_BILLBOARD = 0x442, + NOUN_VIDEOS_NOONE_WANTS = 0x443, + NOUN_MORE_CLASSIC_VIDEOS = 0x444, + NOUN_JOIN_OUR_PRICE_CLUB = 0x445, + NOUN_EDUCATIONAL_VIDEOS = 0x446, + NOUN_DEEP_DISCOUNT_TITLES = 0x447, + NOUN_WORLD_CHAMPS_POSTER = 0x448, + NOUN_WORKOUT_VIDEOS = 0x449, + NOUN_20_PERCENT_OFF_SIGN = 0x44A, + NOUN_CIVILIZATION_AD = 0x44B, + NOUN_NEW_RELEASE_VIDEOS = 0x44C, + NOUN_PORNO_VIDEOS = 0x44D, + NOUN_FOREIGN_VIDEOS = 0x44E, + NOUN_CLASSIC_VIDEOS = 0x44F, + NOUN_ADVENTURE_VIDEOS = 0x450, + NOUN_BUCKLUSTER_LOGO = 0x451, + NOUN_WINE_BOTTLE = 0x452, + NOUN_DIRT_PILE = 0x453, + NOUN_MAMMOTH_PENCIL_HEAD = 0x454, + NOUN_WREAKY_PUMPKIN = 0x455, + NOUN_MILK_CARTON = 0x456, + NOUN_BUCKET = 0x457, + NOUN_EMPTY_BOX = 0x458, + NOUN_DIAPER_BOX = 0x459, + NOUN_HERMIT = 0x45A, + NOUN_METAL_PIPE = 0x45B, + NOUN_CONCRETE_SUPPORT = 0x45C, + NOUN_VARIOUS_TRASH = 0x45D, + NOUN_ARMATURE = 0x45E, + NOUN_CONTROL_BOX = 0x45F, + NOUN_TOP_OF_DOME = 0x460, + NOUN_EXPRESSWAY_TO_EAST = 0x461, + NOUN_GO_TOWARDS = 0x462, + NOUN_EXPRESSWAY_TO_WEST = 0x463, + NOUN_DOME = 0x464, + NOUN_VIEW_OF_CITY = 0x465, + NOUN_EXPRESSWAY = 0x466, + NOUN_HOOK = 0x467, + NOUN_SEA_MONSTER = 0x468, + NOUN_EDGE_OF_VOLCANO = 0x469, + NOUN_JUMP_THROUGH = 0x46A, + NOUN_OLD_TEA_CUP = 0x46B, + NOUN_NAME_PLATE = 0x46C, + NOUN_OLD_VASE = 0x46D, + NOUN_PORTRAIT = 0x46E, + //NOUN_PUT_DOWN = 0x46F, + NOUN_TALL_BUILDING = 0x470, + NOUN_OBNOXIOUS_DOG = 0x471, + NOUN_GUTS = 0x472, + NOUN_BIG_HEADS = 0x473, + NOUN_INSTALL = 0x474, + NOUN_LIFE_SUPPORT_MODULE = 0x475, + //NOUN_REMOVE = 0x476, + NOUN_LARGE_BLADE = 0x477, + NOUN_SIDE_ENTRANCE = 0x478, + NOUN_INDICATOR = 0x479, + NOUN_SIGNPOST = 0x47A, + NOUN_PIN = 0x47B, + NOUN_POWDER_PUFF = 0x47C, + NOUN_SHELVES = 0x47D, + NOUN_ELECTRODES = 0x47E, + NOUN_MISHAP2 = 0x47F, + NOUN_ISLD_SUPERSTRUCTURE = 0x480, + NOUN_FILE_CABINETS = 0x481, + NOUN_CYCLE_SHOP = 0x482, + NOUN_AIR_BIKE = 0x483, + NOUN_EMERGENCY_LIGHT = 0x484, + NOUN_TARGET_AREA = 0x485, + NOUN_ICE_CHESTS = 0x486, + NOUN_BIRDS = 0x487, + NOUN_DOCTORS_OFFICE = 0x488, + //NOUN_DEFACE = 0x489, + NOUN_LARGE_HEADS = 0x48A, + NOUN_SMALL_TABLE = 0x48B, + NOUN_COLLOSSEUM = 0x48C, + NOUN_HOUSE = 0x48D, + NOUN_BALCONY = 0x48E, + NOUN_GARDEN_ROOM = 0x48F, + NOUN_COVE_LIGHTS = 0x490, + NOUN_MASKS = 0x491, + NOUN_NEON_LIGHTS = 0x492, + NOUN_GLASS_BLOCK_WALL = 0x493, + NOUN_SCREEN = 0x494, + NOUN_SPARE_RIBS = 0x495, + NOUN_BANNER = 0x496, + NOUN_INSTRUCTIONAL_VIDEOS = 0x497, + NOUN_CEMENT = 0x498, + NOUN_STORE = 0x499, + NOUN_CARDBOARD_BOX = 0x49A, + NOUN_GRAFFITTI = 0x49B, + NOUN_GRAFFITI = 0x49C, + NOUN_PHOTOGRAPH = 0x49D, + NOUN_DIRECTORS_SLATE = 0x49E, + NOUN_CROP = 0x49F, + NOUN_HAT = 0x4A0, + NOUN_LOGO = 0x4A1, + NOUN_MAINTENANCE_BUILDING = 0x4A2, + //NOUN_MASSAGE = 0x4A3, + //NOUN_MANGLE = 0x4A4, + //NOUN_RUB = 0x4A5, + //NOUN_JUGGLE = 0x4A6, + //NOUN_SMASH = 0x4A7, + //NOUN_GUZZLE = 0x4A8, + NOUN_WEST_END_OF_PLATFORM = 0x4A9, + NOUN_EAST_END_OF_PLATFORM = 0x4AA + //NOUN_FOLD = 0x4AB, + //NOUN_SPINDLE = 0x4AC, + //NOUN_MUTILATE = 0x4AD +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Rex Nebular game scenes + */ +class NebularScene : public SceneLogic { +protected: + NebularGlobals &_globals; + GameNebular &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering various rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + NebularScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoNebular : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoNebular(MADSEngine *vm) : SceneInfo(vm) {} +}; + +class SceneTeleporter : public NebularScene { +protected: + int _buttonTyped; + int _curCode; + int _digitCount; + int _curMessageId; + int _handSpriteId; + int _handSequenceId; + int _finishedCodeCounter; + int _meteorologistNextPlace; + int _meteorologistCurPlace; + int _teleporterSceneId; + Common::String _msgText; + + int teleporterAddress(int code, bool working); + + void teleporterHandleKey(); + Common::Point teleporterComputeLocation(); + void teleporterEnter(); + bool teleporterActions(); + void teleporterStep(); + +protected: + /** + * Constructor + */ + SceneTeleporter(MADSEngine *vm); +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES_H */ diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp new file mode 100644 index 0000000000..8cf4107ad4 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -0,0 +1,3168 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes1.h" + +namespace MADS { + +namespace Nebular { + +void Scene1xx::setAAName() { + int idx = (_scene->_nextSceneId > 103 && _scene->_nextSceneId < 112) ? 1 : 0; + _game._aaName = Resources::formatAAName(idx); +} + +void Scene1xx::sceneEntrySound() { + if (_vm->_musicFlag) { + switch (_scene->_nextSceneId) { + case 101: + _vm->_sound->command(11); + break; + case 102: + _vm->_sound->command(12); + break; + case 103: + _vm->_sound->command(3); + _vm->_sound->command(25); + break; + case 109: + _vm->_sound->command(13); + break; + case 110: + _vm->_sound->command(10); + break; + case 111: + _vm->_sound->command(3); + break; + case 112: + _vm->_sound->command(15); + break; + default: + if (_scene->_priorSceneId < 104 || _scene->_priorSceneId > 108) + _vm->_sound->command(10); + break; + } + } +} + +void Scene1xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + if (_scene->_nextSceneId <= 103 || _scene->_nextSceneId == 111) { + if (_globals[kSexOfRex] == SEX_FEMALE) + _game._player._spritesPrefix = "ROX"; + else { + _game._player._spritesPrefix = "RXM"; + _globals[kSexOfRex] = SEX_MALE; + } + } else if (_scene->_nextSceneId <= 110) { + _game._player._spritesPrefix = "RXSW"; + _globals[kSexOfRex] = SEX_UNKNOWN; + } else if (_scene->_nextSceneId == 112) + _game._player._spritesPrefix = ""; + + if (oldName == _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + if (_scene->_nextSceneId == 105 || (_scene->_nextSceneId == 109 && _globals[kHoovicAlive])) { + _game._player._spritesChanged = true; + _game._player._loadsFirst = false; + } + + _game._player._trigger = 0; + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +/*------------------------------------------------------------------------*/ + +Scene101::Scene101(MADSEngine *vm) : Scene1xx(vm) { + _sittingFl = false; + _panelOpened = false; + _messageNum = 0; + _posY = 0; + _shieldSpriteIdx = 0; + _chairHotspotId = 0; + _oldSpecial = 0; +} + +void Scene101::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_sittingFl); + s.syncAsByte(_panelOpened); + s.syncAsSint16LE(_messageNum); + s.syncAsSint16LE(_posY); + s.syncAsSint16LE(_shieldSpriteIdx); + s.syncAsSint16LE(_chairHotspotId); + s.syncAsSint16LE(_oldSpecial); +} + +void Scene101::setup() { + _scene->_animationData->preLoad(formAnimName('A', -1), 3); + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene101::sayDang() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _vm->_sound->command(17); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 2, 0, 0); + break; + + case 72: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _scene->_kernelMessages.add(Common::Point(143, 61), 0x1110, 0, 0, 60, _game.getQuote(57)); + _scene->_sequences.addTimer(120, 73); + break; + + case 73: + _vm->_dialogs->show(10117); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene101::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 6)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 7)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 8)); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 25); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 0, 1, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 2, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 70); + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 10, 0, 0, 60); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 0, 1, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 2, 0); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 0, 10, 4); + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6, 0, 32, 47); + + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + _panelOpened = false; + + // HACK: set the prior scene to 102 for now when the game starts, to avoid Rex's getting up animation + if (_scene->_priorSceneId == -1) + _scene->_priorSceneId = 102; + + if (_scene->_priorSceneId != -1) + _globals[kNeedToStandUp] = false; + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(100, 152); + + if ((_scene->_priorSceneId == 112) || ((_scene->_priorSceneId == -2) && _sittingFl )) { + _game._player._visible = false; + _sittingFl = true; + _game._player._playerPos = Common::Point(161, 123); + _game._player._facing = FACING_NORTHEAST; + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _scene->_hotspots.activate(NOUN_CHAIR, false); + _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36)); + if (_scene->_priorSceneId == 112) + sayDang(); + } else { + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4); + } + + _game.loadQuoteSet(0x31, 0x32, 0x39, 0x36, 0x37, 0x38, 0); + + if (_globals[kNeedToStandUp]) { + _scene->loadAnimation(Resources::formatName(101, 'S', -1, EXT_AA, ""), 71); + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(68, 140); + _game._player._facing = FACING_WEST; + + _messageNum = 0; + _posY = 30; + } + + _oldSpecial = false; + + sceneEntrySound(); +} + +void Scene101::step() { + if (_oldSpecial != _game._player._special) { + _oldSpecial = _game._player._special; + if (_oldSpecial) + _vm->_sound->command(39); + else + _vm->_sound->command(11); + } + + switch (_game._trigger) { + case 70: + _vm->_sound->command(9); + break; + + case 71: + _globals[kNeedToStandUp] = false; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + break; + + case 72: + case 73: + sayDang(); + break; + + default: + break; + } + + if (_scene->_activeAnimation != nullptr) { + if ((_scene->_activeAnimation->getCurrentFrame() >= 6) && (_messageNum == 0)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(49)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 7) && (_messageNum == 1)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(54)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 10) && (_messageNum == 2)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(55)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 17) && (_messageNum == 3)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(56)); + _posY += 14; + } + + if ((_scene->_activeAnimation->getCurrentFrame() >= 20) && (_messageNum == 4)) { + _messageNum++; + _scene->_kernelMessages.add(Common::Point(63, _posY), 0x1110, 0, 0, 240, _game.getQuote(50)); + _posY += 14; + } + } +} + +void Scene101::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _game._player._needToWalk = true; + + if (_sittingFl) { + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_CHAIR) || _action.isAction(VERB_TALKTO) || _action.isAction(VERB_PEER_THROUGH) || _action.isAction(VERB_EXAMINE)) + _game._player._needToWalk = false; + + if (_game._player._needToWalk) { + switch (_game._trigger) { + case 0: + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17); + _vm->_sound->command(16); + break; + + case 1: + _sittingFl = false; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + _scene->_hotspots.activate(71, true); + _scene->_dynamicHotspots.remove(_chairHotspotId); + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 4); + break; + + default: + break; + } + } + } + + if (_panelOpened && !(_action.isObject(NOUN_SHIELD_ACCESS_PANEL) || _action.isObject(NOUN_SHIELD_MODULATOR))) { + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + } + break; + + case 1: + _game._player._stepEnabled = true; + _panelOpened = false; + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + break; + + default: + break; + } + } +} + +void Scene101::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10125); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_LIFE_SUPPORT_SECTION)) { + _scene->_nextSceneId = 102; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) || (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && !_sittingFl)) { + if (!_sittingFl) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 1, 17); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 10, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _game._player._stepEnabled = false; + _game._player._visible = false; + _action._inProgress = false; + return; + + case 1: + _vm->_sound->command(16); + break; + + case 2: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _game._player._stepEnabled = true; + _sittingFl = true; + _scene->_hotspots.activate(71, false); + _chairHotspotId = _scene->_dynamicHotspots.add(NOUN_CHAIR, VERB_SIT_IN, -1, Common::Rect(159, 84, 159 + 33, 84 + 36)); + if (!_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) { + _action._inProgress = false; + return; + } + _game._trigger = 0; + break; + + default: + break; + } + } else { + _vm->_dialogs->show(10131); + _action._inProgress = false; + return; + } + } + + if ((_action.isAction(VERB_WALKTO, NOUN_SHIELD_ACCESS_PANEL) || _action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL)) && !_panelOpened) { + switch (_game._trigger) { + case 0: + _shieldSpriteIdx = _game._objects.isInRoom(OBJ_SHIELD_MODULATOR) ? 13 : 14; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[_shieldSpriteIdx], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _game._player._stepEnabled = true; + _panelOpened = true; + if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, true); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) || _action.isAction(VERB_PULL, NOUN_SHIELD_MODULATOR)) && _game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) { + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[14], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_hotspots.activate(NOUN_SHIELD_MODULATOR, false); + _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 10120); + _vm->_sound->command(22); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SHIELD_ACCESS_PANEL) || (_action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) ) { + if (_panelOpened) { + if (_game._objects.isInRoom(OBJ_SHIELD_MODULATOR)) + _vm->_dialogs->show(10128); + else + _vm->_dialogs->show(10129); + } else + _vm->_dialogs->show(10127); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_SHIELD_ACCESS_PANEL) && _panelOpened) { + _vm->_dialogs->show(10130); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN) && _sittingFl) { + if (_globals[kWatchedViewScreen]) + sayDang(); + else { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _vm->_sound->command(17); + break; + + case 1: + _globals._sequenceIndexes[11] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 21); + break; + + case 2: + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 3, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[11], 17, 17); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _globals[kWatchedViewScreen] = true; + _sittingFl = true; + _scene->_nextSceneId = 112; + break; + + default: + break; + } + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CHAIR)) { + _vm->_dialogs->show(10101); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PEER_THROUGH)) && (_action.isObject(NOUN_FRONT_WINDOW) || _action.isObject(NOUN_OUTSIDE))) { + _vm->_dialogs->show(10102); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_HULL) || _action.isAction(VERB_LOOK, NOUN_OUTER_HULL) || _action.isAction(VERB_EXAMINE, NOUN_HULL) || _action.isAction(VERB_EXAMINE, NOUN_OUTER_HULL)) { + _vm->_dialogs->show(10103); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FUZZY_DICE)) { + _vm->_dialogs->show(10104); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MIRROR) || _action.isAction(VERB_LOOK_IN, NOUN_MIRROR)) { + _vm->_dialogs->show(10105); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CURTAINS)) { + _vm->_dialogs->show(10106); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PLASTIC_JESUS)) { + _vm->_dialogs->show(10107); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH) || (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) && !_game._objects.isInInventory(OBJ_REBREATHER))) { + _vm->_dialogs->show(10109); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH)) { + _vm->_dialogs->show(10110); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TARGET_COMPUTER)) { + _vm->_dialogs->show(10111); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_LIBRARY_COMPUTER)) { + _vm->_dialogs->show(10126); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DAMAGE_CONTROL_PANEL)) { + _vm->_dialogs->show(10112); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_NAVIGATION_CONTROLS)) { + _vm->_dialogs->show(10113); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_CONTROLS)) { + _vm->_dialogs->show(10114); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WEAPONS_DISPLAY)) { + _vm->_dialogs->show(10115); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SHIELD_STATUS_PANEL)) { + _vm->_dialogs->show(10116); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_PLASTIC_JESUS)) { + _vm->_dialogs->show(10118); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_FUZZY_DICE)) { + _vm->_dialogs->show(10119); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_DAMAGE_CONTROL_PANEL)) { + _vm->_dialogs->show(10121); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_CURTAINS)) { + _vm->_dialogs->show(10122); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_CURTAINS)) { + _vm->_dialogs->show(10123); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_LOOK) || _action.isAction(VERB_PLAY)) && _action.isObject(NOUN_VIDEO_GAME)) { + _vm->_dialogs->show(10124); + _action._inProgress = false; + return; + } +} + +/*------------------------------------------------------------------------*/ + +Scene102::Scene102(MADSEngine *vm) : Scene1xx(vm) { + _fridgeOpenedFl = false; + _fridgeOpenedDescr = false; + _fridgeFirstOpenFl = false; + _chairDescrFl = false; + _drawerDescrFl = false; + _activeMsgFl = false; + _fridgeCommentCount = 0; +} + +void Scene102::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_fridgeOpenedFl); + s.syncAsByte(_fridgeOpenedDescr); + s.syncAsByte(_fridgeFirstOpenFl); + s.syncAsByte(_chairDescrFl); + s.syncAsByte(_drawerDescrFl); + s.syncAsByte(_activeMsgFl); + + s.syncAsSint16LE(_fridgeCommentCount); +} + +void Scene102::setup() { + _scene->_animationData->preLoad(formAnimName('A', -1), 3); + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene102::addRandomMessage() { + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + int quoteId = _vm->getRandomNumber(65, 69); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 73, 120, _game.getQuote(quoteId)); + _activeMsgFl = true; +} + +void Scene102::enter() { + sceneEntrySound(); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('e', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 170, 0, 1, 6); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 2, 3); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 0, 1, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 3, 0, 0, 5); + + if (_game._objects.isInRoom(OBJ_BINOCULARS)) + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 24, 0, 0, 24); + else + _scene->_hotspots.activate(NOUN_BINOCULARS, false); + + _scene->_hotspots.activate(NOUN_BURGER, false); + + if (_globals[kMedicineCabinetOpen]) { + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + } + + if (_scene->_priorSceneId == 101) { + _game._player._playerPos = Common::Point(229, 109); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 2, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } else if (_scene->_priorSceneId == 103) + _game._player._playerPos = Common::Point(47, 152); + else if (_scene->_priorSceneId != -2) { + _game._player._facing = FACING_NORTHWEST; + _game._player._playerPos = Common::Point(32, 129); + } + + if (_scene->_priorSceneId != 106) { + if (_globals[kWaterInAPuddle]) { + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + } + } else { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + _vm->_sound->command(24); + _vm->_sound->command(28); + } + + _fridgeOpenedFl = false; + _fridgeOpenedDescr = false; + _fridgeCommentCount = 0; + _fridgeFirstOpenFl = true; + _chairDescrFl = false; + _activeMsgFl = false; + + _game.loadQuoteSet(0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x45, 0x43, 0); + + if (_scene->_priorSceneId == 101) + _vm->_sound->command(20); +} + +void Scene102::step() { + if (_game._trigger == 70) + _game._player._stepEnabled = true; + + if (_game._trigger == 72) { + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 5); + _scene->_sequences.addTimer(48, 90); + } + + if (_game._trigger >= 90) { + if (_game._trigger >= 94) { + _scene->loadAnimation(formAnimName('B', -1), 71); + _game._player._stepEnabled = false; + _game._player._visible = false; + + _globals[kWaterInAPuddle] = true; + _vm->_sound->command(24); + } else { + _vm->_sound->command(23); + _scene->_sequences.addTimer(48, _game._trigger + 1); + } + } + + if (_game._trigger == 71) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + + if (_fridgeOpenedFl && !_fridgeOpenedDescr) { + _fridgeCommentCount++; + if (_fridgeCommentCount > 16384) { + _fridgeOpenedDescr = true; + _vm->_dialogs->show(10213); + } + } + + if (!_activeMsgFl && (_game._player._playerPos == Common::Point(177, 114)) && (_game._player._facing == FACING_NORTH) + && (_vm->getRandomNumber(1, 5000) == 1)) { + _scene->_kernelMessages.reset(); + _activeMsgFl = false; + addRandomMessage(); + } + + if (_game._trigger == 73) + _activeMsgFl = false; +} + +void Scene102::preActions() { + if (_action.isObject(NOUN_REFRIGERATOR) || _action.isObject(NOUN_POSTER)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (_fridgeOpenedFl && !_action.isObject(NOUN_REFRIGERATOR)) { + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + } + break; + + case 1: + if (_game._objects.isInRoom(OBJ_BURGER)) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _scene->_hotspots.activate(NOUN_BURGER, false); + } + _fridgeOpenedFl = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + + if (_game._player._needToWalk) + _scene->_kernelMessages.reset(); +} + +void Scene102::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10234); + _action._inProgress = false; + return; + } + + bool justOpenedFl = false; + if (_action.isObject(NOUN_REFRIGERATOR) && !_fridgeOpenedFl) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + if (_game._objects.isInRoom(OBJ_BURGER)) { + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 14); + } + _game._player._stepEnabled = false; + _vm->_sound->command(20); + _action._inProgress = false; + return; + + case 1: + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + int delay; + if (_action.isAction(VERB_WALKTO) && !_fridgeFirstOpenFl) + delay = 0; + else + delay = 48; + _scene->_sequences.addTimer(delay, 2); + _action._inProgress = false; + return; + + case 2: + _fridgeOpenedFl = true; + _fridgeOpenedDescr = false; + _fridgeCommentCount = 0; + _game._player._stepEnabled = true; + justOpenedFl = true; + if (_game._objects.isInRoom(OBJ_BURGER)) + _scene->_hotspots.activate(NOUN_BURGER, true); + break; + + default: + break; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR) || _action.isAction(VERB_OPEN, NOUN_REFRIGERATOR)) { + if (_game._objects.isInRoom(OBJ_BURGER)) + _vm->_dialogs->show(10230); + else + _vm->_dialogs->show(10229); + + _fridgeFirstOpenFl = false; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_REFRIGERATOR) && justOpenedFl) { + _fridgeFirstOpenFl = false; + int quoteId = _vm->getRandomNumber(59, 63); + Common::String curQuote = _game.getQuote(quoteId); + int width = _vm->_font->getWidth(curQuote, -1); + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(210, 60), 0x1110, 0, 73, 120, curQuote); + _scene->_kernelMessages.add(Common::Point(214 + width, 60), 0x1110, 0, 73, 120, _game.getQuote(64)); + _activeMsgFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_REFRIGERATOR)) { + _vm->_dialogs->show(10213); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR)) { + _vm->_dialogs->show(8); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _scene->_nextSceneId = 101; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_ENGINEERING_SECTION)) { + _scene->_nextSceneId = 103; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_POSTER) || _action.isAction(VERB_LOOK, NOUN_POSTER) || _action.isAction(VERB_WALKTO, NOUN_BINOCULARS)) { + addRandomMessage(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WEIGHT_MACHINE)) { + _vm->_dialogs->show(10212); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ENGINEERING_SECTION)) { + _vm->_dialogs->show(10205); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DOOR)) { + _vm->_dialogs->show(10204); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_STARE_AT, NOUN_CEILING) || _action.isAction(VERB_LOOK, NOUN_CEILING)) { + _vm->_dialogs->show(10203); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_STARE_AT, NOUN_OVERHEAD_LAMP) || _action.isAction(VERB_LOOK, NOUN_OVERHEAD_LAMP)) { + _vm->_dialogs->show(10202); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10215); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(OBJ_BURGER)) { + _vm->_dialogs->show(10216); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_REFRIGERATOR) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + _vm->_dialogs->show(10217); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_ROBO_KITCHEN) || _action.isAction(VERB_PUT, NOUN_STUFFED_FISH, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10230); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_ROBO_KITCHEN)) { + _vm->_dialogs->show(10218); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CLOSET)) { + _vm->_dialogs->show(10219); + _action._inProgress = false; + return; + } + + if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_LOOK) || _action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH))) { + if (_game._objects.isInInventory(OBJ_REBREATHER)) { + if (!_action.isAction(VERB_CLIMB_UP) && !_action.isAction(VERB_CLIMB_THROUGH)) { + _vm->_dialogs->show(10231); + _action._inProgress = false; + return; + } + } else if (_action.isAction(VERB_LOOK) || (_game._difficulty != DIFFICULTY_EASY)) { + _vm->_dialogs->show(10222); + _action._inProgress = false; + return; + } + } + + if ((_action.isObject(NOUN_LADDER) || _action.isObject(NOUN_HATCHWAY)) && (_action.isAction(VERB_CLIMB_UP) || _action.isAction(VERB_CLIMB_THROUGH)) ) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(formAnimName('A', -1), 1); + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + + case 1: + _vm->_sound->command(24); + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + case 3: + case 4: + _vm->_sound->command(23); + _scene->_sequences.addTimer(48, _game._trigger + 1); + break; + + case 5: + _vm->_sound->command(24); + _scene->_sequences.addTimer(48, _game._trigger + 1); + break; + + case 6: + if (_game._objects.isInInventory(OBJ_REBREATHER) && !_game._visitedScenes.exists(106)) + _vm->_dialogs->show(10237); + _scene->_nextSceneId = 106; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_POWER_STATUS_PANEL)) { + _vm->_dialogs->show(10226); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_WINDOW) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDOW)) { + _vm->_dialogs->show(10227); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DOORWAY) || _action.isAction(VERB_WALKTO, NOUN_DOORWAY)) { + _vm->_dialogs->show(10228); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_DRAWER) || ((_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) && !_drawerDescrFl)) { + _vm->_dialogs->show(10220); + _drawerDescrFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_DRAWER) || _action.isAction(VERB_PUSH, NOUN_DRAWER)) { + _vm->_dialogs->show(10221); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_DRAWER)) { + _vm->_dialogs->show(10236); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || (_action.isAction(VERB_SIT_IN, NOUN_CHAIR) && !_chairDescrFl)) { + _chairDescrFl = true; + _vm->_dialogs->show(10210); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_SIT_IN, NOUN_CHAIR)) { + _vm->_dialogs->show(10211); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MEDICINE_CABINET)) { + if (_globals[kMedicineCabinetOpen]) + _vm->_dialogs->show(10207); + else + _vm->_dialogs->show(10206); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_CLOSE, NOUN_MEDICINE_CABINET) && _globals[kMedicineCabinetOpen]) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(21); + break; + + case 1: + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + _game._player._stepEnabled = true; + _globals[kMedicineCabinetOpen] = false; + _vm->_dialogs->show(10209); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_MEDICINE_CABINET) && !_globals[kMedicineCabinetOpen]) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(21); + break; + + case 1: + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + _scene->_sequences.addTimer(48, 2); + break; + + case 2: + _game._player._stepEnabled = true; + _globals[kMedicineCabinetOpen] = true; + if (_globals[kMedicineCabinetVirgin]) { + _vm->_dialogs->show(10208); + } else { + _vm->_dialogs->show(10207); + } + _globals[kMedicineCabinetVirgin] = false; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && _game._objects.isInRoom(OBJ_BINOCULARS)) { + switch (_game._trigger) { + case 0: + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._visible = false; + _game._player._stepEnabled = false; + break; + + case 1: + _game._objects.addToInventory(OBJ_BINOCULARS); + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _scene->_hotspots.activate(NOUN_BINOCULARS, false); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_sound->command(22); + _vm->_dialogs->showItem(OBJ_BINOCULARS, 10201); + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) { + if (_game._trigger == 0) { + _vm->_dialogs->showItem(OBJ_BURGER, 10235); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _game._objects.addToInventory(OBJ_BURGER); + _scene->_hotspots.activate(NOUN_BURGER, false); + _vm->_sound->command(22); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_POSTER)) { + _vm->_dialogs->show(10224); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_WEIGHT_MACHINE)) { + _vm->_dialogs->show(10225); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) { + _vm->_dialogs->show(10232); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && !_game._objects.isInInventory(OBJ_BINOCULARS)) { + _vm->_dialogs->show(10233); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BURGER) && (_action._mainObjectSource == 4)) { + _vm->_dialogs->show(801); + _action._inProgress = false; + } +} + +void Scene102::postActions() { + if (_action.isAction(VERB_PUT, NOUN_ROBO_KITCHEN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + _vm->_dialogs->show(10217); + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +Scene103::Scene103(MADSEngine *vm) : Scene1xx(vm) { + _updateClock = 0; +} + +void Scene103::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + byte dummy = 0; + s.syncAsByte(dummy); // In order to avoid to break savegame compatibility + s.syncAsUint32LE(_updateClock); +} + +void Scene103::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene103::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_2"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RXMRD_3"); + _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 7, 0, 1, 0); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 2, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 72); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 1, 37); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 73); + + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6); + + if (_game._objects.isInRoom(OBJ_TIMER_MODULE)) + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6); + else + _vm->_game->_scene._hotspots.activate(371, false); + + if (_game._objects.isInRoom(OBJ_REBREATHER)) + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 6); + else + _vm->_game->_scene._hotspots.activate(289, false); + + if (_globals[kTurkeyExploded]) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2); + _scene->_hotspots.activate(362, false); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(237, 74); + + if (_scene->_priorSceneId == 102) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } + + sceneEntrySound(); + _vm->_game->loadQuoteSet(70, 51, 71, 7, 73, 0); + + if (!_game._visitedScenes._sceneRevisited) { + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(70)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + + if (_scene->_priorSceneId == 102) + _vm->_sound->command(20); + + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 10); + _updateClock = _scene->_frameStartTime; +} + +void Scene103::step() { + switch (_vm->_game->_trigger) { + case 70: + _vm->_game->_player._stepEnabled = true; + break; + + case 72: { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 58, pt.y - 93); + _vm->_sound->command(27, (dist * -128 / 378) + 127); + } + break; + + case 73: { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 266, pt.y - 81); + _vm->_sound->command(27, (dist * -127 / 378) + 127); + } + break; + + default: + break; + } + + if (_scene->_frameStartTime >= _updateClock) { + Common::Point pt = _vm->_game->_player._playerPos; + int dist = _vm->hypotenuse(pt.x - 79, pt.y - 137); + _vm->_sound->command(29, (dist * -127 / 378) + 127); + + pt = _vm->_game->_player._playerPos; + dist = _vm->hypotenuse(pt.x - 69, pt.y - 80); + _vm->_sound->command(30, (dist * -127 / 378) + 127); + + pt = _vm->_game->_player._playerPos; + dist = _vm->hypotenuse(pt.x - 266, pt.y - 138); + _vm->_sound->command(32, (dist * -127 / 378) + 127); + + _updateClock = _scene->_frameStartTime + _vm->_game->_player._ticksAmount; + } +} + +void Scene103::actions() { + if (_action._savedFields._lookFlag) + _vm->_dialogs->show(10322); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) { + switch (_vm->_game->_trigger) { + case 0: + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + _vm->_sound->command(20); + break; + + case 1: + _vm->_sound->command(1); + _scene->_nextSceneId = 102; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TIMER_MODULE) && _game._objects.isInRoom(OBJ_TIMER_MODULE)) { + switch (_vm->_game->_trigger) { + case 0: + _scene->changeVariant(1); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 3, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[13]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_SPRITE, 7, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_game->_player._visible = false; + _vm->_game->_player._stepEnabled = false; + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + break; + + case 2: + _vm->_sound->command(22); + _game._objects.addToInventory(OBJ_TIMER_MODULE); + _scene->changeVariant(0); + _scene->drawElements(kTransitionNone, false); + _scene->_hotspots.activate(371, false); + _vm->_game->_player._visible = true; + _vm->_game->_player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_REBREATHER, 805); + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, 289, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { + switch (_vm->_game->_trigger) { + case 0: + _scene->changeVariant(1); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 3, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_game->_player._visible = false; + _vm->_game->_player._stepEnabled = false; + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + break; + + case 2: + _vm->_sound->command(22); + _game._objects.addToInventory(OBJ_REBREATHER); + _scene->_hotspots.activate(289, false); + _vm->_game->_player._visible = true; + _vm->_game->_player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_REBREATHER, 804); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, 362)) + _vm->_dialogs->show(10301); + else if (_action.isAction(VERB_TAKE, 362)) { + // Take Turkey + if (!_vm->_game->_trigger) + _vm->_sound->command(31); + + if (_vm->_game->_trigger < 2) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, _vm->_game->_trigger < 1 ? 1 : 0); + if (_vm->_game->_trigger) { + // Lock the turkey into a permanent "exploded" frame + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], -2, -2); + + // Rex says "Gads.." + Common::String msg = _game.getQuote(51); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 0, 60, msg); + _scene->_sequences.addTimer(120, _vm->_game->_trigger + 1); + } else { + // Initial turky explosion + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } + } + + // Re-enable player if sequence is ended, and set global flag + _game._player._stepEnabled = _game._trigger == 2; + _globals[kTurkeyExploded] = -1; + + if (_game._trigger == 2) { + // Show exposition dialog at end of sequence + _vm->_dialogs->show(10302); + _scene->_hotspots.activate(362, false); + } + } else if (_action.isAction(VERB_LOOK, 250)) + _vm->_dialogs->show(!_globals[kTurkeyExploded] ? 10323 : 10303); + else if (_action.isAction(VERB_TALKTO, 27)) { + switch (_vm->_game->_trigger) { + case 0: { + _game._player._stepEnabled = false; + Common::String msg = _game.getQuote(71); + _scene->_kernelMessages.add(Common::Point(), 0x1110, 18, 1, 120, msg); + break; + } + + case 1: { + Common::String msg = _game.getQuote(72); + _scene->_kernelMessages.add(Common::Point(310, 132), 0xFDFC, 16, 2, 120, msg); + break; + } + + case 2: + _scene->_kernelMessages.reset(); + _scene->_sequences.addTimer(1, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->show(10306); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, 27)) + _vm->_dialogs->show(10304); + else if (_action.isAction(VERB_LOOK, 36)) + _vm->_dialogs->show(10307); + else if (_action.isAction(VERB_LOOK, 55)) + _vm->_dialogs->show(10308); + else if (_action.isAction(VERB_TAKE, 315)) + _vm->_dialogs->show(10309); + else if (_action.isAction(VERB_TAKE, 85)) + _vm->_dialogs->show(10310); + else if (_action.isAction(VERB_LOOK, 144)) + _vm->_dialogs->show(10312); + else if (_action.isAction(VERB_OPEN, 144)) + _vm->_dialogs->show(10313); + else if (_action.isAction(VERB_CLOSE, 27)) + _vm->_dialogs->show(10314); + else if (_action.isAction(VERB_LOOK, 310)) + _vm->_dialogs->show(10315); + else if (_action.isAction(VERB_LOOK, 178)) + _vm->_dialogs->show(10316); + else if (_action.isAction(VERB_LOOK, 283)) + _vm->_dialogs->show(10317); + else if (_action.isAction(VERB_LOOK, 120)) + _vm->_dialogs->show(10318); + else if (_action.isAction(VERB_LOOK, 289) && _game._objects.isInInventory(OBJ_REBREATHER)) + _vm->_dialogs->show(10319); + else if (_action.isAction(VERB_LOOK, 371) && _game._objects.isInInventory(OBJ_TIMER_MODULE)) + _vm->_dialogs->show(10320); + else if (_action.isAction(VERB_LOOK, 137)) + _vm->_dialogs->show(10321); + else if (_action.isAction(VERB_LOOK, 409)) + _vm->_dialogs->show(_game._objects.isInInventory(OBJ_TIMER_MODULE) ? 10324 : 10325); + else + return; + + _action._inProgress = false; +} + +void Scene103::postActions() { + if (_action.isObject(NOUN_AUXILIARY_POWER) && !_action.isAction(VERB_WALKTO)) { + _vm->_dialogs->show(10305); + _action._inProgress = false; + } else if (_action.isAction(VERB_PUT, NOUN_COAL, NOUN_FURNACE)) { + Common::String msg = _game.getQuote(73); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, msg); + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +Scene104::Scene104(MADSEngine *vm) : Scene1xx(vm) { + _kargShootingFl = false; + _loseFl = false; +} + +void Scene104::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_kargShootingFl); + s.syncAsByte(_loseFl); +} + +void Scene104::setup() { + // Preloading has been skipped + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene104::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 1); + + if (_scene->_priorSceneId == 105) + _game._player._playerPos = Common::Point(302, 107); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(160, 134); + + _loseFl = false; + _game.loadQuoteSet(0x35, 0x34, 0); + _kargShootingFl = false; + + if (_vm->getRandomNumber(1, 3) == 1) { + _scene->loadAnimation(Resources::formatName(104, 'B', -1, EXT_AA, ""), 0); + _kargShootingFl = true; + } + + sceneEntrySound(); +} + +void Scene104::step() { + if ((_game._player._playerPos == Common::Point(189, 70)) && (_game._trigger || !_loseFl)) { + if (_game._player._facing == FACING_SOUTHWEST || _game._player._facing == FACING_SOUTHEAST) + _game._player._facing = FACING_SOUTH; + + if (_game._player._facing == FACING_NORTHWEST || _game._player._facing == FACING_NORTHEAST) + _game._player._facing = FACING_NORTH; + + bool mirrorFl = false; + if (_game._player._facing == FACING_WEST) { + _game._player._facing = FACING_EAST; + mirrorFl = true; + } + + _loseFl = true; + + switch (_game._player._facing) { + case FACING_EAST: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], mirrorFl, 7, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2); + _scene->_sequences.addTimer(90, 2); + break; + + case 2: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + + case FACING_SOUTH: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 15, 32); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + _scene->_sequences.addTimer(90, 3); + break; + + case 3: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + + case FACING_NORTH: + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + if (_game._storyMode >= STORYMODE_NICE) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 15, 2); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(198, 143)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -2, -2); + _scene->_sequences.addTimer(90, 2); + break; + + case 2: + _vm->_dialogs->show(10406); + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } + break; + default: + break; + } + + if (!_game._trigger) + _vm->_sound->command(34); + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(189, 70), FACING_NONE); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if (_kargShootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + _kargShootingFl = false; + } +} + +void Scene104::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_EASTERN_CLIFF_FACE)) + _game._player._walkOffScreenSceneId = 105; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 106; +} + +void Scene104::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10405); + else if (_action.isAction(VERB_LOOK, NOUN_CURIOUS_WEED_PATCH)) + _vm->_dialogs->show(10404); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10403); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10401); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10402); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene105::Scene105(MADSEngine *vm) : Scene1xx(vm) { + _explosionFl = false; +} + +void Scene105::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_explosionFl); +} + +void Scene105::setup() { + // Preloading has been skipped + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene105::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('m', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 4)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 0); + + if (_globals[kFishIn105]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(48, 144)); + + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(56, 141), FACING_NORTHWEST); + } + + if (_scene->_priorSceneId == 104) + _game._player._playerPos = Common::Point(13, 97); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(116, 147); + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + _explosionFl = false; + + sceneEntrySound(); +} + +void Scene105::step() { + if ((_game._player._playerPos == Common::Point(170, 87)) && (_game._trigger || !_explosionFl)) { + _explosionFl = true; + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _game._player._stepEnabled = false; + _game._player._visible = false; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 3)); + _vm->_sound->command(33); + _scene->clearSequenceList(); + _vm->_palette->refreshSceneColors(); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + + if (_game._storyMode >= STORYMODE_NICE) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 8, 3); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 1, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], _globals._sequenceIndexes[0]); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 9, 0, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.addTimer(90, 3); + } + break; + + case 3: + _vm->_dialogs->show(10507); + _scene->_reloadSceneFlag = true; + _scene->_sequences.addTimer(90, 4); + break; + + default: + break; + } + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(170, 87), FACING_NONE); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && _game._player._stepEnabled) + _game._player._stepEnabled = false; +} + +void Scene105::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_WESTERN_CLIFF_FACE)) + _game._player._walkOffScreenSceneId = 104; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 107; + + if (_action.isObject(NOUN_MINE) && (_action.isAction(VERB_TALKTO) || _action.isAction(VERB_LOOK))) + _game._player._needToWalk = false; +} + +void Scene105::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10512); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn105]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn105] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802, 0); + } + } else if (_action.isAction(VERB_LOOK, NOUN_WESTERN_CLIFF_FACE)) + _vm->_dialogs->show(10501); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10502); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10503); + else if (_action.isAction(VERB_LOOK, NOUN_MEDICAL_WASTE)) + _vm->_dialogs->show(10504); + else if (_action.isAction(VERB_TAKE, NOUN_MEDICAL_WASTE)) + _vm->_dialogs->show(10505); + else if (_action.isAction(VERB_LOOK, NOUN_MINE)) + _vm->_dialogs->show(10506); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH)) + _vm->_dialogs->show(10508); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10509); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH)) + _vm->_dialogs->show(10510); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10511); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene106::Scene106(MADSEngine *vm) : Scene1xx(vm) { + _backToShipFl = false; + _shadowFl = false; + _firstEmergingFl = false; + _positionY = 0; +} + +void Scene106::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_backToShipFl); + s.syncAsByte(_shadowFl); + s.syncAsByte(_firstEmergingFl); + s.syncAsSint32LE(_positionY); +} + +void Scene106::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + if ((_scene->_priorSceneId == 102) && !_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged) + _game._player._spritesPrefix = ""; + + _vm->_dialogs->_defaultPosition.y = 100; +} + +void Scene106::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('H', -1)); + + if (_game._objects.isInInventory(OBJ_REBREATHER) || (_scene->_priorSceneId != 102) || _scene->_roomChanged) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('A', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('A', 1)); + } + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('G', -1)); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 21, 0, 0, 0); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('I', -1)); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 32, 47); + + if (_scene->_priorSceneId == 102) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 1, 4, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._facing = FACING_EAST; + _game._player._playerPos = Common::Point(106, 69); + } else if (_scene->_priorSceneId != -2) { + if (_scene->_priorSceneId == 107) { + _game._player._playerPos = Common::Point(319, 84); + _game._player._facing = _game._player._prepareWalkFacing = FACING_WEST; + } else { + _game._player._playerPos = Common::Point(319, 44); + _game._player._facing = _game._player._prepareWalkFacing = FACING_SOUTHWEST; + _scene->_sprites[_game._player._spritesStart + 3]->_charInfo->_velocity = 24; + } + + _game._player._prepareWalkPos = Common::Point(246, 69); + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_scene->_priorSceneId != 102) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14); + } + + _backToShipFl = false; + _shadowFl = false; + _firstEmergingFl = false; + + _game.loadQuoteSet(0x31, 0x32, 0x34, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0); + sceneEntrySound(); +} + +void Scene106::step() { + if (_game._trigger == 70) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 14); + + if (!_game._objects.isInInventory(OBJ_REBREATHER) && !_scene->_roomChanged) { + _scene->loadAnimation(Resources::formatName(106, 'A', -1, EXT_AA, ""), 75); + } else { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 28, 71); + } + } + + if (_game._trigger == 71) { + _game._player._prepareWalkPos = Common::Point(246, 69); + _game._player._prepareWalkFacing = FACING_EAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + _game._player._visible = true; + + if (_game._visitedScenes._sceneRevisited) { + _game._player._stepEnabled = true; + } else { + _game._player._prepareWalkFacing = FACING_SOUTHWEST; + _firstEmergingFl = true; + _scene->loadAnimation(Resources::formatName(106, 'B', -1, EXT_AA, ""), 80); + } + } + + if (_firstEmergingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _firstEmergingFl = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + } + + if ((_game._trigger >= 80) && (_game._trigger <= 87)) { + int tmpVal = _game._trigger - 80; + int msgId = -1; + switch (tmpVal) { + case 0: + _positionY = 26; + msgId = 49; + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + msgId = 76 + tmpVal; + break; + + case 6: + msgId = 50; + break; + + default: + msgId = -1; + _game._player._stepEnabled = true; + break; + } + + if (msgId >= 0) { + int nextAbortVal = _game._trigger + 1; + _scene->_kernelMessages.add(Common::Point(15, _positionY), 0x1110, 0, 0, 360, _game.getQuote(msgId)); + _scene->_sequences.addTimer(150, nextAbortVal); + _positionY += 14; + } + } + + if (_backToShipFl) { + if (!_shadowFl) { + if (_game._player._playerPos.x < 204) { + _shadowFl = true; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 44, 73); + } + } else if (_game._trigger == 73) + _game._player._visible = false; + else if (_game._trigger == 72) + _scene->_sequences.addTimer(24, 74); + else if (_game._trigger == 74) + _scene->_nextSceneId = 102; + } + + if (_game._trigger == 75) { + _game._visitedScenes.pop_back(); + _scene->_nextSceneId = 102; + } +} + +void Scene106::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_SEA_CLIFF) || _action.isAction(VERB_SWIM_TOWARDS, NOUN_SEAWEED_BANK)) { + _game._player._stepEnabled = false; + _scene->_sprites[_game._player._spritesStart + 1]->_charInfo->_velocity = 24; + _game._player._walkOffScreenSceneId = 104; + } + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_EAST)) + _game._player._walkOffScreenSceneId = 107; +} + +void Scene106::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10614); + else if (_action.isAction(VERB_SWIM_TO, NOUN_MAIN_AIRLOCK)) { + _game._player._stepEnabled = false; + _game._player._prepareWalkPos = Common::Point(95, 72); + _game._player._prepareWalkFacing = FACING_WEST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + _game._player._frameNumber = 9; + _backToShipFl = true; + } else if (_action.isAction(VERB_LOOK, NOUN_ANEMONE) || _action.isAction(VERB_LOOK_AT, NOUN_ANEMONE)) + _vm->_dialogs->show(10601); + else if (_action.isAction(VERB_TAKE, NOUN_ANEMONE)) + _vm->_dialogs->show(10602); + else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED) || _action.isAction(VERB_LOOK, NOUN_SEAWEED_BANK)) + _vm->_dialogs->show(10603); + else if (_action.isAction(VERB_TAKE, NOUN_SEAWEED) || _action.isAction(VERB_TAKE, NOUN_SEAWEED_BANK)) + _vm->_dialogs->show(10604); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_EAST)) + _vm->_dialogs->show(10605); + else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_ROCKS) || _action.isAction(VERB_LOOK_AT, NOUN_PILE_OF_ROCKS)) + _vm->_dialogs->show(10606); + else if (_action.isObject(NOUN_PILE_OF_ROCKS) && (_action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE))) + _vm->_dialogs->show(10607); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP) || _action.isAction(VERB_LOOK_AT, NOUN_SHIP)) + _vm->_dialogs->show(10608); + else if (_action.isAction(VERB_LOOK, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10609); + else if (_action.isAction(VERB_OPEN, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10610); + else if (_action.isAction(VERB_CLOSE, NOUN_MAIN_AIRLOCK)) + _vm->_dialogs->show(10611); + else if (_action.isAction(VERB_LOOK, NOUN_SEA_CLIFF)) + _vm->_dialogs->show(10612); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10613); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene107::Scene107(MADSEngine *vm) : Scene1xx(vm) { + _shootingFl = false; +} + +void Scene107::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_shootingFl); +} + +void Scene107::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_MANTA_RAY); +} + +void Scene107::enter() { + for (int i = 0; i < 3; i++) + _globals._spriteIndexes[i + 1] = _scene->_sprites.addSprites(formAnimName('G', i)); + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, "")); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 0, 0, 7); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 13); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 19, 0, 0, 9); + + for (int i = 1; i < 4; i++) + _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0); + + if (_globals[kFishIn107]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(68, 151)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(78, 135), FACING_SOUTHWEST); + } + + if (_scene->_priorSceneId == 105) + _game._player._playerPos = Common::Point(132, 47); + else if (_scene->_priorSceneId == 106) + _game._player._playerPos = Common::Point(20, 91); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(223, 151); + + if (((_scene->_priorSceneId == 105) || (_scene->_priorSceneId == 106)) && (_vm->getRandomNumber(1, 3) == 1)) { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(Resources::formatName(105, 'R', 1, EXT_SS, "")); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], true, 4, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[0], Common::Point(270, 150)); + _scene->_sequences.setMotion(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, -200, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 2); + _scene->_dynamicHotspots.add(218, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + } + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + _shootingFl = false; + + if (_vm->getRandomNumber(1, 3) == 1) { + _scene->loadAnimation(Resources::formatName(107, 'B', -1, EXT_AA, ""), 0); + _shootingFl = true; + } + + sceneEntrySound(); +} + +void Scene107::step() { + if (_shootingFl && (_scene->_activeAnimation->getCurrentFrame() >= 19)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(52)); + _shootingFl = false; + } +} + +void Scene107::preActions() { + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_WEST)) + _game._player._walkOffScreenSceneId = 106; + + if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 108; +} + +void Scene107::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10708); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn107]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn107] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 802); + } + } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_NORTHERN_SEA_CLIFF)) + _scene->_nextSceneId = 105; + else if (_action.isAction(VERB_LOOK, NOUN_NORTHERN_SEA_CLIFF)) + _vm->_dialogs->show(10701); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(10702); + else if (_action.isAction(VERB_LOOK, NOUN_BUSH_LIKE_FORMATION)) + _vm->_dialogs->show(10703); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(10704); + else if (_action.isAction(VERB_LOOK, NOUN_SEAWEED)) + _vm->_dialogs->show(10705); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_SOUTH)) + _vm->_dialogs->show(10706); + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10707); + else if (_action.isAction(VERB_LOOK, NOUN_MANTA_RAY)) + _vm->_dialogs->show(10709); + else if (_action.isAction(VERB_TAKE, NOUN_MANTA_RAY)) + _vm->_dialogs->show(10710); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene108::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene108::enter() { + if (_globals[kHoovicSated] == 2) + _globals[kHoovicSated] = 0; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(105, 'f', 4, EXT_SS, "")); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 13, 0, 0, 7); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 0, 0, 9); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 3); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 13); + + for (int i = 0; i <= 3; i++) + _scene->_sequences.setDepth(_globals._sequenceIndexes[i], 0); + + if (_globals[kFishIn108]) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(41, 109)); + int idx = _scene->_dynamicHotspots.add(101, 348, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(41, 109), FACING_NORTHWEST); + } + + if (_scene->_priorSceneId == 107) + _game._player._playerPos = Common::Point(138, 58); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(305, 98); + + _game.loadQuoteSet(0x4A, 0x4B, 0x4C, 0x35, 0x34, 0); + sceneEntrySound(); +} + +void Scene108::preActions() { + if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_EAST)) + _game._player._walkOffScreenSceneId = 109; +} + +void Scene108::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(10812); + else if (_action.isAction(VERB_TAKE, NOUN_DEAD_FISH) && _globals[kFishIn108]) { + if (_game._objects.isInInventory(OBJ_DEAD_FISH)) { + int randVal = _vm->getRandomNumber(74, 76); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _game._objects.addToInventory(OBJ_DEAD_FISH); + _globals[kFishIn108] = false; + _vm->_dialogs->showItem(OBJ_DEAD_FISH, 10808); + } + } else if (_action.isAction(VERB_SWIM_TOWARDS, NOUN_OPEN_AREA_TO_NORTH)) + _scene->_nextSceneId = 107; + else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) + _vm->_dialogs->show(10801); + else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10802); + else if (_action.isAction(VERB_LOOK, NOUN_ODD_ROCK_FORMATION)) + _vm->_dialogs->show(10803); + else if (_action.isAction(VERB_TAKE, NOUN_ODD_ROCK_FORMATION)) + _vm->_dialogs->show(10804); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10805); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(10806); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_FISH)) + _vm->_dialogs->show(10807); + else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_EAST)) + _vm->_dialogs->show(10809); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_NORTH)) + _vm->_dialogs->show(10810); + else if (_action.isAction(VERB_LOOK, NOUN_SURFACE)) + _vm->_dialogs->show(10811); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene109::Scene109(MADSEngine *vm) : Scene1xx(vm) { + _rexThrowingObject = false; + _hoovicDifficultFl = false; + _beforeEatingRex = false; + _eatingRex = false; + _hungryFl = false; + _eatingFirstFish = false; + + _throwingObjectId = -1; + _hoovicTrigger = 0; +} + +void Scene109::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_rexThrowingObject); + s.syncAsByte(_hoovicDifficultFl); + s.syncAsByte(_beforeEatingRex); + s.syncAsByte(_eatingRex); + s.syncAsByte(_hungryFl); + s.syncAsByte(_eatingFirstFish); + s.syncAsSint32LE(_throwingObjectId); + s.syncAsSint32LE(_hoovicTrigger); +} + +void Scene109::setup() { + _scene->addActiveVocab(NOUN_DEAD_PURPLE_MONSTER); + _scene->addActiveVocab(NOUN_MONSTER_SLUDGE); + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene109::enter() { + _globals[kFishIn105] = true; + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*RXSWRC_6"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('O', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('O', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('O', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('H', 4)); + + _rexThrowingObject = false; + _throwingObjectId = 0; + _beforeEatingRex = false; + _eatingRex = false; + _hungryFl = false; + + if (_scene->_priorSceneId == 110) { + _game._player._playerPos = Common::Point(248, 38); + _globals[kHoovicSated] = 2; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(20, 68); + _game._player._facing = FACING_EAST; + } + + if (!_globals[kHoovicAlive]) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + + int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 267, 87)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 265, 90)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 253, 94)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + } + + if (!_globals[kHoovicAlive] || _globals[kHoovicSated]) + _scene->changeVariant(1); + + if (_game._objects.isInRoom(OBJ_BURGER)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -2, -2); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + } else if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BURGER); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_DEAD_FISH); + _game._objects.addToInventory(OBJ_STUFFED_FISH); + } + + _vm->_palette->setEntry(252, 50, 50, 63); + _vm->_palette->setEntry(253, 30, 30, 50); + + _game.loadQuoteSet(0x53, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0); + _eatingFirstFish = (!_game._visitedScenes._sceneRevisited) && (_scene->_priorSceneId < 110); + + if (_eatingFirstFish) { + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(Resources::formatName(105, 'F', 1, EXT_SS, "")); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('H', 1)); + + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], true, 4, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 5); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(126, 39)); + _scene->_sequences.setMotion(_globals._sequenceIndexes[10], 0, 200, 0); + _scene->_sequences.setScale(_globals._sequenceIndexes[10], 80); + _game._player._stepEnabled = false; + } + + sceneEntrySound(); +} + +void Scene109::step() { + if (_beforeEatingRex) { + if (!_eatingRex) { + if (_game._player._playerPos.x > 205) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 70); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + + _eatingRex = true; + _vm->_sound->command(34); + } + } else { + switch (_game._trigger) { + case 70: + _game._player._visible = false; + break; + + case 71: + _scene->_reloadSceneFlag = true; + break; + } + } + } + + if (_hungryFl && (_game._player._playerPos == Common::Point(160, 32)) && (_game._player._facing == FACING_EAST)) { + _game._player.walk(Common::Point(226, 24), FACING_EAST); + _game._player._stepEnabled = false; + _hungryFl = false; + _beforeEatingRex = true; + _scene->_sprites.remove(_globals._spriteIndexes[6]); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('H', 0)); + _vm->_palette->refreshSceneColors(); + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0) && _globals[kHoovicAlive] && !_globals[kHoovicSated] && !_hungryFl && !_beforeEatingRex) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(160, 32), FACING_EAST); + _scene->_rails.resetNext(); + _hungryFl = true; + } + + if (_eatingFirstFish && (_scene->_sequences[_globals._sequenceIndexes[10]]._position.x >= 178)) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 4, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_SPRITE, 29, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 29, 73); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]); + _eatingFirstFish = false; + _game._player._stepEnabled = true; + _vm->_sound->command(34); + } + + if (_game._trigger == 72) + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + if (_game._trigger == 73) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _scene->_sprites.remove(_globals._spriteIndexes[9]); + _scene->_sprites.remove(_globals._spriteIndexes[10]); + + _scene->_spriteSlots.clear(); + _scene->_spriteSlots.fullRefresh(); + + int randVal = _vm->getRandomNumber(85, 88); + int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(randVal)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + _scene->_kernelMessages._entries[idx]._frameTimer = _scene->_frameStartTime + 4; + } +} + +void Scene109::preActions() { + if (_action.isAction(VERB_SWIM_UNDER, NOUN_OVERHANG_TO_WEST)) + _game._player._walkOffScreenSceneId = 108; + + if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE) || _action.isAction(VERB_PUT)) + && (_action.isObject(NOUN_SMALL_HOLE) || _action.isObject(NOUN_TUNNEL)) + && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { + int idx = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if ((idx >= 0) && _game._objects.isInInventory(idx)) { + _game._player._prepareWalkPos = Common::Point(106, 38); + _game._player._prepareWalkFacing = FACING_EAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + } + + if ((_action.isAction(VERB_SWIM_INTO, NOUN_TUNNEL) || _action.isAction(VERB_SWIM_TO, NOUN_SMALL_HOLE)) + && (!_globals[kHoovicAlive] || _globals[kHoovicSated]) && (_action.isObject(NOUN_TUNNEL))) + _game._player._walkOffScreenSceneId = 110; + + _hungryFl = false; +} + +void Scene109::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(10912); + _action._inProgress = false; + return; + } + + if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE)) && (_action.isTarget(NOUN_SMALL_HOLE) || _action.isTarget(NOUN_TUNNEL))) { + if (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER)) { + _throwingObjectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if (_throwingObjectId >= 0) { + if ((_game._objects.isInInventory(_throwingObjectId) && _globals[kHoovicAlive]) || _rexThrowingObject) { + switch (_game._trigger) { + case 0: + _rexThrowingObject = true; + _hoovicDifficultFl = false; + _game._objects.setRoom(_throwingObjectId, NOWHERE); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 4, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[0]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._visible = false; + _game._player._stepEnabled = false; + + switch (_throwingObjectId) { + case OBJ_DEAD_FISH: + case OBJ_STUFFED_FISH: + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', 1)); + break; + + case OBJ_BURGER: + _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_EASY); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', (_hoovicDifficultFl ? 3 : 1))); + break; + } + + _vm->_palette->refreshSceneColors(); + break; + + case 1: + _game._player._visible = true; + _hoovicTrigger = 4; + switch (_throwingObjectId) { + case OBJ_BURGER: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, (_hoovicDifficultFl ? 4 : 6), 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 2, 2); + if (_hoovicDifficultFl) { + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 30); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } else { + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + _hoovicTrigger = 3; + } + break; + case OBJ_DEAD_FISH: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 2); + break; + case OBJ_STUFFED_FISH: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 2); + _hoovicTrigger = 3; + break; + } + break; + + case 2: + if (_hoovicDifficultFl) + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 4, 2, 0, 0); + else + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 4, 1, 0, 0); + + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, _hoovicTrigger); + _vm->_sound->command(34); + break; + + case 3: + _scene->loadAnimation(Resources::formatName(109, 'H', 2, EXT_AA, ""), 4); + _vm->_sound->command(35); + _globals[kHoovicAlive] = false; + break; + + case 4: + if (!_globals[kHoovicAlive]) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + int idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(256, 57, 256 + 12, 57 + 31)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(102, 348, -1, Common::Rect(242, 79, 242 + 24, 79 + 12)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(229, 348, -1, Common::Rect(231, 88, 231 + 23, 88 + 7)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(241, 91), FACING_NORTHEAST); + _scene->changeVariant(1); + } else { + if (_throwingObjectId == OBJ_DEAD_FISH) { + ++_globals[kHoovicFishEaten]; + int threshold; + switch (_game._difficulty) { + case DIFFICULTY_HARD: + threshold = 1; + break; + case DIFFICULTY_MEDIUM: + threshold = 3; + break; + default: + threshold = 50; + break; + } + + if (_globals[kHoovicFishEaten] >= threshold) { + int randVal = _vm->getRandomNumber(83, 84); + _scene->_kernelMessages.add(Common::Point(230, 24), 0xFDFC, 0, 0, 120, _game.getQuote(randVal)); + _globals[kHoovicFishEaten] = 0; + _globals[kHoovicSated] = 1; + _scene->changeVariant(1); + } + } + } + _scene->freeAnimation(); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _scene->_sprites.remove(_globals._spriteIndexes[8]); + _scene->_spriteSlots.clear(); + _scene->_spriteSlots.fullRefresh(); + _scene->_sequences.scan(); + if (_game._player._visible) { + _game._player._forceRefresh = true; + _game._player.update(); + } + + _game._player._stepEnabled = true; + _rexThrowingObject = false; + break; + + case 5: { + _game._objects.setRoom(OBJ_BURGER, _scene->_currentSceneId); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 30, 30); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _scene->_sequences.addTimer(65, 6); + } + break; + + case 6: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 46); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + } + break; + + case 7: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + int idx = _scene->_dynamicHotspots.add(53, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-3, 0), FACING_NORTHEAST); + _vm->_dialogs->show(10915); + } + break; + + case 8: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 16); + break; + } + _action._inProgress = false; + return; + } else if (_game._objects.isInInventory(_throwingObjectId)) { + // Nothing. + } + } + } + } + + if (_action.isAction(VERB_TAKE, NOUN_BURGER) && _game._objects.isInRoom(OBJ_BURGER)) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._objects.addToInventory(OBJ_BURGER); + } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_FLOOR)) + _vm->_dialogs->show(10901); + else if (_action.isAction(VERB_LOOK, NOUN_CORAL)) + _vm->_dialogs->show(10902); + else if ((_action.isAction(VERB_TAKE) || _action.isAction(VERB_PULL)) && _action.isObject(NOUN_CORAL)) + _vm->_dialogs->show(10903); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(10904); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(10905); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_WALL)) + _vm->_dialogs->show(10906); + else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL)) { + if (_globals[kHoovicAlive]) + _vm->_dialogs->show(10907); + else + _vm->_dialogs->show(10913); + } else if (_action.isAction(VERB_LOOK, NOUN_SMALL_HOLE)) + _vm->_dialogs->show(10908); + else if (_action.isAction(VERB_LOOK, NOUN_OVERHANG_TO_WEST)) + _vm->_dialogs->show(10911); + else if (_action.isAction(VERB_PUT, NOUN_SMALL_HOLE)) + _vm->_dialogs->show(10910); + else if (_action.isAction(VERB_LOOK, NOUN_DEAD_PURPLE_MONSTER)) + _vm->_dialogs->show(10914); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene110::Scene110(MADSEngine *vm) : Scene1xx(vm) { + _crabsFl = false; +} + +void Scene110::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_crabsFl); +} + +void Scene110::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_CRAB); +} + +void Scene110::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 3)); + + _crabsFl = false; + + if (_scene->_priorSceneId == 109) { + _game._player._playerPos = Common::Point(59, 71); + + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + + _crabsFl = true; + + int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(194, 23); + _game._player._facing = FACING_SOUTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(Resources::formatName(110, 'T', 1,EXT_AA, ""), 70); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x59, 0); + + if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId == 109)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(109)); +} + +void Scene110::step() { + if (_game._trigger == 70) { + _game._player._visible = true; + _game._player._stepEnabled = true; + } +} + +void Scene110::preActions() { + if (_action.isAction(VERB_SWIM_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 109; + + if (_crabsFl) { + _crabsFl = false; + + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 16, 1, 0, 0); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 16, 1, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 16, 1, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 16, 1, 0, 0); + + int idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[0], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(91, 348, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-1, 0), FACING_NONE); + } +} + +void Scene110::actions() { + if (_action.isAction(VERB_SWIM_THROUGH, NOUN_TUNNEL)) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(Resources::formatName(110, 'T', 0, EXT_AA, ""), 1); + _scene->_activeAnimation->setNextFrameTimer(_game._player._ticksAmount + _game._player._priorTimer); + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + case 1: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_nextSceneId = 111; + break; + } + } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_CAVE)) + _vm->_dialogs->show(11001); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_CEILING) || _action.isAction(VERB_LOOK_AT, NOUN_CAVE_CEILING)) + _vm->_dialogs->show(11002); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(11003); + else if (_action.isAction(VERB_TAKE, NOUN_ROCKS)) + _vm->_dialogs->show(11004); + else if (_action.isAction(VERB_LOOK, NOUN_TUNNEL)) + _vm->_dialogs->show(11005); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(11006); + else if (_action.isAction(VERB_LOOK, NOUN_FUNGOIDS)) + _vm->_dialogs->show(11007); + else if (_action.isAction(VERB_TAKE, NOUN_FUNGOIDS)) + _vm->_dialogs->show(11008); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene111::Scene111(MADSEngine *vm) : Scene1xx(vm) { + _stampedFl = false; + _launch1Fl = false; + _launched2Fl = false; + _rexDivingFl = false; +} + +void Scene111::synchronize(Common::Serializer &s) { + Scene1xx::synchronize(s); + + s.syncAsByte(_stampedFl); + s.syncAsByte(_launch1Fl); + s.syncAsByte(_launched2Fl); + s.syncAsByte(_rexDivingFl); +} + +void Scene111::setup() { + _scene->addActiveVocab(NOUN_BATS); + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene111::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('B', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('B', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('B', 2)); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 8, 0, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 9, 73); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_SPRITE, 13, 73); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 71, 71); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + + _launch1Fl = false; + _launched2Fl = false; + _stampedFl = false; + + if ((_scene->_priorSceneId < 201) && (_scene->_priorSceneId != -2)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(Resources::formatName(111, 'A', 0, EXT_AA, ""), 70); + _game._player._playerPos = Common::Point(234, 116); + _game._player._facing = FACING_EAST; + + _launch1Fl = true; + _launched2Fl = true; + + _vm->_sound->command(36); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(300, 130); + _game._player._facing = FACING_WEST; + } + + _rexDivingFl = false; + + sceneEntrySound(); +} + +void Scene111::step() { + if (_game._trigger == 70) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _launch1Fl = false; + _launched2Fl = false; + } + + if ((_game._trigger == 71) && !_stampedFl) { + _stampedFl = true; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 18, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + + if (_game._trigger == 72) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 20); + } + + if (!_launch1Fl && (_vm->getRandomNumber(1, 5000) == 1)) { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _launch1Fl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + } + + if (!_launched2Fl && (_vm->getRandomNumber(1, 30000) == 1)) { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_BATS, VERB_LOOK_AT, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + _launched2Fl = true; + } + + if (_game._trigger == 73) + _vm->_sound->command(37); + + if (_rexDivingFl && (_scene->_activeAnimation->getCurrentFrame() >= 9)) { + _vm->_sound->command(36); + _rexDivingFl = false; + } +} + +void Scene111::preActions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 212; +} + +void Scene111::actions() { + if (_action.isAction(VERB_DIVE_INTO, NOUN_POOL) && _game._objects.isInInventory(OBJ_REBREATHER)) { + switch (_game._trigger) { + case 0: + _scene->loadAnimation(Resources::formatName(111, 'A', 1, EXT_AA, ""), 1); + _rexDivingFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + break; + + case 1: + _scene->_nextSceneId = 110; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_CAVE_FLOOR)) + _vm->_dialogs->show(11101); + else if (_action.isAction(VERB_LOOK, NOUN_POOL)) + _vm->_dialogs->show(11102); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(11103); + else if (_action.isAction(VERB_LOOK, NOUN_STALAGMITES)) + _vm->_dialogs->show(11104); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_STALAGMITE)) + _vm->_dialogs->show(11105); + else if ((_action.isAction(VERB_PULL) || _action.isAction(VERB_TAKE)) && (_action.isObject(NOUN_STALAGMITES) || _action.isObject(NOUN_LARGE_STALAGMITE))) + _vm->_dialogs->show(11106); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene112::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene112::enter() { + sceneEntrySound(); + + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('X', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('X', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('X', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('X', 5)); + + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 10, 0, 17, 20); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 3, 0); + + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + + _scene->loadAnimation(Resources::formatName(112, 'X', -1, EXT_AA, ""), 70); +} + +void Scene112::step() { + if ((_scene->_activeAnimation != nullptr) && (_game._storyMode == STORYMODE_NICE)) { + if (_scene->_activeAnimation->getCurrentFrame() >= 54) { + _scene->freeAnimation(); + _game._trigger = 70; + } + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 3, 0, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_game._trigger == 71) { + _scene->_nextSceneId = 101; + _game._player._stepEnabled = true; + _game._player._visible = true; + } +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes1.h b/engines/mads/nebular/nebular_scenes1.h new file mode 100644 index 0000000000..1afa7fccc1 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes1.h @@ -0,0 +1,264 @@ +/* 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 MADS_NEBULAR_SCENES1_H +#define MADS_NEBULAR_SCENES1_H + +#include "common/scummsys.h" +#include "common/serializer.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene1xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound(); + + /** + *Sets the AA file to use for the scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); +public: + Scene1xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene101 : public Scene1xx { +private: + bool _sittingFl; + bool _panelOpened; + + int _messageNum; + int _posY; + int _shieldSpriteIdx; + int _chairHotspotId; + int _oldSpecial; + + void sayDang(); + +public: + Scene101(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene102 : public Scene1xx { +private: + bool _fridgeOpenedFl; + bool _fridgeOpenedDescr; + bool _fridgeFirstOpenFl; + bool _chairDescrFl; + bool _drawerDescrFl; + bool _activeMsgFl; + + int _fridgeCommentCount; + + void addRandomMessage(); + +public: + Scene102(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); + virtual void postActions(); +}; + +class Scene103 : public Scene1xx { +private: + uint32 _updateClock; + +public: + Scene103(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); + virtual void postActions(); +}; + +class Scene104 : public Scene1xx { +private: + bool _kargShootingFl; + bool _loseFl; + +public: + Scene104(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene105 : public Scene1xx { +private: + bool _explosionFl; + +public: + Scene105(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene106 : public Scene1xx { +private: + bool _backToShipFl; + bool _shadowFl; + bool _firstEmergingFl; + + int _positionY; + +public: + Scene106(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene107 : public Scene1xx { +private: + bool _shootingFl; + +public: + Scene107(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene108 : public Scene1xx { +public: + Scene108(MADSEngine *vm) : Scene1xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene109 : public Scene1xx { +private: + bool _rexThrowingObject; + bool _hoovicDifficultFl; + bool _beforeEatingRex; + bool _eatingRex; + bool _hungryFl; + bool _eatingFirstFish; + + int _throwingObjectId; + int _hoovicTrigger; + +public: + Scene109(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene110 : public Scene1xx { +private: + bool _crabsFl; + +public: + Scene110(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene111 : public Scene1xx { +private: + bool _stampedFl; + bool _launch1Fl; + bool _launched2Fl; + bool _rexDivingFl; + +public: + Scene111(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene112 : public Scene1xx { +public: + Scene112(MADSEngine *vm) : Scene1xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES1_H */ diff --git a/engines/mads/nebular/nebular_scenes2.cpp b/engines/mads/nebular/nebular_scenes2.cpp new file mode 100644 index 0000000000..36e7107609 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes2.cpp @@ -0,0 +1,5380 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes2.h" + +namespace MADS { + +namespace Nebular { + +void Scene2xx::setAAName() { + int idx = (_scene->_nextSceneId == 216) ? 4 : 2; + _game._aaName = Resources::formatAAName(idx); +} + +void Scene2xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + switch(_scene->_nextSceneId) { + case 213: + case 216: + _game._player._spritesPrefix = ""; + break; + default: + if (_globals[kSexOfRex] != SEX_MALE) { + _game._player._spritesPrefix = "ROX"; + } else { + _game._player._spritesPrefix = "RXM"; + } + break; + } + + _game._player._scalingVelocity = (_scene->_nextSceneId <= 212); + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + if ((_scene->_nextSceneId == 203 || _scene->_nextSceneId == 204) && _globals[kRhotundaStatus]) + _game._player._loadsFirst = false; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene2xx::sceneEntrySound() { + if (_vm->_musicFlag) { + switch (_scene->_nextSceneId) { + case 201: + if ((_globals[kTeleporterCommand] == 2) || (_globals[kTeleporterCommand] == 4) || (_globals[kMeteorologistStatus] != 1)) + _vm->_sound->command(9); + else + _vm->_sound->command(17); + break; + case 202: + case 203: + case 204: + case 205: + case 208: + case 209: + case 212: + _vm->_sound->command(9); + break; + case 206: + case 211: + case 215: + _vm->_sound->command(10); + break; + case 207: + case 214: + _vm->_sound->command(11); + break; + case 210: + if (_globals[kTwinklesStatus] == 0) + _vm->_sound->command(15); + else + _vm->_sound->command(10); + break; + case 213: + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_sound->command(1); + else + _vm->_sound->command(9); + break; + case 216: + _vm->_sound->command(16); + break; + default: + _vm->_sound->command(10); + break; + } + } else + _vm->_sound->command(2); +} + +/*------------------------------------------------------------------------*/ + +Scene201::Scene201(MADSEngine *vm) : Scene2xx(vm) { + _pterodactylFlag = false; +} + +void Scene201::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_pterodactylFlag); +} + +void Scene201::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_SWOOPING_CREATURE); + _scene->addActiveVocab(NOUN_BIRDS); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene201::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*SC002Z1"); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 1, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 50); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 4, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(185, 46)); + + int idx = _scene->_dynamicHotspots.add(NOUN_BIRDS, 209, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 81), FACING_NORTH); + + if ((_scene->_priorSceneId == 202) || (_scene->_priorSceneId == -1)) { + _game._player._playerPos = Common::Point(165, 152); + } else { + _game._player._playerPos = Common::Point(223, 149); + _game._player._facing = FACING_SOUTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u'; + // Guess values. What is the default value used by the compiler? + int suffixNum = -1; + int abortTimers = -1; + switch(_globals[kTeleporterCommand]) { + case 1: + suffixNum = 3; + abortTimers = 76; + _globals[kTeleporterUnderstood] = true; + break; + case 2: + suffixNum = 1; + abortTimers = 77; + break; + case 3: + _game._player._visible = true; + _game._player._stepEnabled = true; + suffixNum = -1; + break; + case 4: + suffixNum = 2; + abortTimers = 78; + break; + } + _globals[kTeleporterCommand] = 0; + if (suffixNum >= 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), abortTimers); + } + + if ((_scene->_priorSceneId == 202) && (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) && !_scene->_roomChanged) { + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _game.loadQuoteSet(90, 91, 0); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -1, 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 12, 70); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _pterodactylFlag = false; + _game._player.walk(Common::Point(157, 143), FACING_NORTH); + _vm->_palette->setEntry(252, 45, 63, 45); + _vm->_palette->setEntry(253, 20, 45, 20); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 2, 0, 120, _game.getQuote(90)); + } else + _pterodactylFlag = true; + + if (_globals[kTeleporterUnderstood]) + _scene->_hotspots.activate(NOUN_STRANGE_DEVICE, false); + + sceneEntrySound(); +} + +void Scene201::step() { + if (_pterodactylFlag && (_vm->getRandomNumber(5000) == 9)) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 5, 1, 6, 0); + int idx = _scene->_dynamicHotspots.add(351, 13, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(270, 80), FACING_EAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8); + _vm->_sound->command(14); + _pterodactylFlag = false; + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _game._player._visible = false; + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 12, 16); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 1, 0, 0); + _vm->_sound->command(42); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 3, 81); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + + if (_game._trigger == 81) { + _scene->_kernelMessages.reset(); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + } + + if (_game._trigger == 73) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 17, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + } + + if (_game._trigger == 74) { + _vm->_sound->command(40); + + _scene->_kernelMessages.add(Common::Point(125, 56), 0xFDFC, 32, 82, 180, _game.getQuote(91)); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 9, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], -2, -2); + _scene->_sequences.addTimer(180, 75); + } + + if (_game._trigger == 75) { + _globals[kMeteorologistEverSeen] = 0; + _scene->_nextSceneId = 202; + } + + if (_game._trigger == 76) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + + if (_game._trigger == 77) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 78) { + _vm->_sound->command(40); + _vm->_dialogs->show(20114); + _scene->_reloadSceneFlag = true; + } +} + +void Scene201::actions() { + if (_action._lookFlag == false) { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) + _scene->_nextSceneId = 202; + else if (_action.isAction(VERB_CLIMB_UP, NOUN_STEPS) || (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) || (_action.isAction(VERB_WALK_INSIDE, NOUN_STRANGE_DEVICE))) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + int sepChar = (_globals[kSexOfRex] == SEX_MALE) ? 't' : 'u'; + _scene->loadAnimation(formAnimName(sepChar, 0), 1); + } else if (_game._trigger == 1) { + _scene->_nextSceneId = 213; + } + } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20101); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) { + _vm->_dialogs->show(20102); + } else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH)) { + _vm->_dialogs->show(20103); + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20104); + } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) { + _vm->_dialogs->show(20105); + } else if (_action.isAction(VERB_LOOK, NOUN_ISLAND_IN_DISTANCE)) { + _vm->_dialogs->show(20106); + } else if (_action.isAction(VERB_LOOK, NOUN_WEATHER_STATION)) { + _vm->_dialogs->show(20107); + } else if (_action.isAction(VERB_LOOK, NOUN_PATH)) { + _vm->_dialogs->show(20108); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_SOUTH)) { + _vm->_dialogs->show(20110); + } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + if (_globals[kMeteorologistEverSeen]) + _vm->_dialogs->show(20112); + else + _vm->_dialogs->show(20109); + } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) { + _vm->_dialogs->show(20113); + } else + return; + } else { + _vm->_dialogs->show(20111); + } + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene202::Scene202(MADSEngine *vm) : Scene2xx(vm) { + _activeMsgFl = false; + _ladderTopFl = false; + _waitingMeteoFl = false; + _ladderHotspotId = -1; + _meteoClock1 = 0; + _meteoClock2 = 0; + _toStationFl = false; + _toTeleportFl = false; + _lastRoute = 0; + _stationCounter = 0; + _meteoFrame = 0; + _startTime = 0; + _meteorologistSpecial = false; +} + +void Scene202::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_activeMsgFl); + s.syncAsByte(_ladderTopFl); + s.syncAsByte(_waitingMeteoFl); + s.syncAsByte(_toStationFl); + s.syncAsByte(_toTeleportFl); + + s.syncAsSint32LE(_ladderHotspotId); + s.syncAsSint32LE(_lastRoute); + s.syncAsSint32LE(_stationCounter); + s.syncAsSint32LE(_meteoFrame); + + s.syncAsUint32LE(_meteoClock1); + s.syncAsUint32LE(_meteoClock2); + s.syncAsUint32LE(_startTime); + + s.syncAsByte(_meteorologistSpecial); +} + +void Scene202::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_LADDER); + _scene->addActiveVocab(VERB_CLIMB_DOWN); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_BONE); + _scene->addActiveVocab(NOUN_SKULL); + _scene->addActiveVocab(NOUN_BROKEN_LADDER); +} + +void Scene202::enter() { + _game._player._beenVisible = true; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('l', -1)); + if (_globals[kSexOfRex] != SEX_MALE) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXBD_2"); + } else { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*RXMBD_2"); + } + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(149, 113)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + int idx = _scene->_dynamicHotspots.add(NOUN_SKULL, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(153, 97), FACING_SOUTH); + + if (!(_globals[kBone202Status] & 1)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(130, 108)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(132, 97), FACING_SOUTH); + } + + if (!(_globals[kBone202Status] & 2)) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(166, 110)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); + idx = _scene->_dynamicHotspots.add(NOUN_BONE, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(165, 99), FACING_SOUTH); + } + + if (_globals[kBone202Status]) + _scene->changeVariant(_globals[kBone202Status]); + + if (_scene->_priorSceneId == 201) { + _game._player._playerPos = Common::Point(190, 91); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(178, 152); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kLadderBroken]) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6); + _scene->_hotspots.activate(NOUN_LADDER, false); + idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH); + } + + _game.loadQuoteSet(0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x61, 0); + _activeMsgFl = false; + + if (_scene->_priorSceneId == -2) { + if (_waitingMeteoFl) { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _game._player._visible = false; + } + } else { + _waitingMeteoFl = false; + _ladderTopFl = false; + } + + _meteoClock1 = _meteoClock2 = _scene->_frameStartTime; + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BINOCULARS); + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _ladderTopFl = (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER); + + if (_ladderTopFl) { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82)); + _game._player._playerPos = Common::Point(246, 124); + _game._player._facing = FACING_NORTH; + _globals[kTeleporterUnderstood] = true; + } else { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _game._player._playerPos = Common::Point(171, 122); + _game._player._facing = FACING_NORTH; + } + + _scene->loadAnimation(formAnimName('M', -1), 71); + _scene->_activeAnimation->setCurrentFrame(200); + } else { + if (_ladderTopFl) { + _game._player._visible = false; + _scene->_sequences.startCycle(_globals._sequenceIndexes[9], true, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _game._player._playerPos = Common::Point(246, 124); + _game._player._facing = FACING_NORTH; + } + } + + _meteorologistSpecial = false; +} + +void Scene202::setRandomKernelMessage() { + int vocabId = _vm->getRandomNumber(92, 96); + _scene->_kernelMessages.reset(); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 70, 120, _game.getQuote(vocabId)); + _activeMsgFl = true; +} + +void Scene202::step() { + if (!_activeMsgFl && (_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH) && (_vm->getRandomNumber(999) == 0)) { + _scene->_kernelMessages.reset(); + _activeMsgFl = false; + if (_vm->getRandomNumber(4) == 0) + setRandomKernelMessage(); + } + + if (_game._trigger == 70) + _activeMsgFl = false; + + if (_game._trigger == 71) { + _vm->_sound->command(3); + _vm->_sound->command(9); + + _meteoClock1 = _scene->_frameStartTime + 15 * 60; + + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) { + Common::Point msgPos; + int msgFlag; + if (!_ladderTopFl) { + msgPos = Common::Point(0, 0); + msgFlag = 2; + } else { + msgPos = Common::Point(248, 15); + msgFlag = 0; + } + int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(102)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + + if (_globals[kMeteorologistWatch] == METEOROLOGIST_GROUND) { + _action._activeAction._verbId = VERB_LOOK; + _action._activeAction._objectNameId = NOUN_BINOCULARS; + _action._activeAction._indirectObjectId = NOUN_STRANGE_DEVICE; + _game._triggerSetupMode = SEQUENCE_TRIGGER_PARSER; + _scene->_sequences.addTimer(2 * 60, 2); + _meteorologistSpecial = true; + } else if (_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) { + _scene->_sequences.addTimer(2 * 60, 90); + } + } + + _globals[kMeteorologistWatch] = METEOROLOGIST_NORMAL; + } + + switch (_game._trigger) { + case 90: + _vm->_sound->command(41); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + break; + case 91: + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addTimer(60, 92); + break; + case 92: { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 93); + _scene->_kernelMessages.reset(); + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, -65), 0x1110, 32, 0, 60, _game.getQuote(98)); + _scene->_kernelMessages.setSeqIndex(msgIndex, _globals._sequenceIndexes[11]); + } + break; + case 93: { + _globals[kLadderBroken] = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_hotspots.activate(NOUN_LADDER, false); + int idx = _scene->_dynamicHotspots.add(NOUN_BROKEN_LADDER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(246, 124), FACING_NORTH); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[11], _globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[11]); + _game._player._stepEnabled = true; + _game._player._visible = true; + _ladderTopFl = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(99)); + } + break; + default: + break; + } + + if (!_scene->_activeAnimation && (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) && (_meteoClock2 <= _scene->_frameStartTime) && (_meteoClock1 <= _scene->_frameStartTime)) { + int randVal = _vm->getRandomNumber(1, 500); + int threshold = 1; + if (_ladderTopFl) + threshold += 25; + if (!_globals[kMeteorologistEverSeen]) + threshold += 25; + if (threshold >= randVal) { + _vm->_sound->command(17); + _scene->loadAnimation(formAnimName('M', -1), 71); + _toStationFl = true; + _toTeleportFl = false; + _globals[kMeteorologistEverSeen] = true; + _lastRoute = 0; + _stationCounter = 0; + _meteoClock2 = _scene->_frameStartTime + 2; + } + } + + if (!_scene->_activeAnimation) + return; + + if (_waitingMeteoFl) { + if (_scene->_activeAnimation->getCurrentFrame() >= 200) { + if ((_globals[kMeteorologistWatch] == METEOROLOGIST_TOWER) || _globals[kLadderBroken]) { + _scene->_nextSceneId = 213; + } else { + _vm->_dialogs->show(20201); + _scene->_reloadSceneFlag = true; + } + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 160) && (_meteoFrame != _scene->_activeAnimation->getCurrentFrame())) { + Common::Point msgPos; + int msgFlag; + if (!_ladderTopFl) { + msgPos = Common::Point(0, 0); + msgFlag = 2; + } else { + msgPos = Common::Point(248, 15); + msgFlag = 0; + } + int msgIndex = _scene->_kernelMessages.add(msgPos, 0x1110, msgFlag | 32, 0, 120, _game.getQuote(101)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + } + + if (_meteoClock2 + 120 * 60 <= _scene->_frameStartTime) { + _toTeleportFl = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == _meteoFrame) { + return; + } + + _meteoFrame = _scene->_activeAnimation->getCurrentFrame(); + int randVal = _vm->getRandomNumber(1, 1000); + int frameStep = -1; + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 42: + case 77: + case 96: + _stationCounter = 0; + frameStep = subStep1(randVal); + break; + case 51: + case 74: + _toStationFl = false; + frameStep = subStep2(randVal); + break; + case 27: + case 119: + case 159: + frameStep = subStep3(randVal); + break; + case 176: + frameStep = subStep4(randVal); + break; + case 59: + _lastRoute = 3; + ++_stationCounter; + if (randVal <= 800) + frameStep = 55; + break; + case 89: + _lastRoute = 1; + if (randVal <= 700) + frameStep = 83; + break; + case 137: + _lastRoute = 2; + if (randVal <= 700) + frameStep = 126; + break; + } + + if (frameStep >= 0 && frameStep != _scene->_activeAnimation->getCurrentFrame() + 1) { + _scene->_activeAnimation->setCurrentFrame(frameStep); + _meteoFrame = frameStep; + } +} + +int Scene202::subStep1(int randVal) { + if ((randVal <= 100) || _toStationFl) + return 42; + + if ((randVal <= 200) || _toTeleportFl) + return 96; + + if ((randVal <= 300) && (_lastRoute != 1)) + return 77; + + return 76; +} + +int Scene202::subStep2(int randVal) { + if ((randVal <= 150) && (_stationCounter < 5)) + return 51; + + if ((randVal <= 300) || _toTeleportFl) + return 74; + + if (randVal <= 400) + return 64; + + return 44; +} + +int Scene202::subStep3(int randVal) { + if ((randVal <= 100) || _toStationFl) + return 27; + + if ((randVal <= 200) || _toTeleportFl) + return 159; + + if ((randVal <= 300) && (_lastRoute != 2)) + return 119; + + return 110; +} + +int Scene202::subStep4(int randVal) { + if ((randVal <= 100) || _toTeleportFl) + return 176; + + if (randVal <= 200) + return 19; + + return 166; +} + +void Scene202::preActions() { + Player &player = _vm->_game->_player; + + if (player._needToWalk) + _scene->_kernelMessages.reset(); + + if (_ladderTopFl && (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER) || player._needToWalk)) { + if (_game._trigger == 0) { + _vm->_sound->command(29); + player._readyToWalk = false; + player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[8] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else if (_game._trigger == 1) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]); + _scene->_dynamicHotspots.remove(_ladderHotspotId); + player._visible = true; + player._readyToWalk = true; + player._stepEnabled = true; + _ladderTopFl = false; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS) && (_action._activeAction._indirectObjectId > 0)) { + if (!player._readyToWalk || _ladderTopFl) + player._needToWalk = false; + else + player._needToWalk = true; + + if (!_ladderTopFl) + player.walk(Common::Point(171, 122), FACING_NORTH); + } +} + +void Scene202::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(20219); + return; + } + + if (_action.isAction(VERB_CLIMB_DOWN, NOUN_LADDER)) { + _action._inProgress = false; + return; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _scene->_nextSceneId = 203; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) { + if (_globals[kMeteorologistStatus] != METEOROLOGIST_GONE) { + if (_scene->_activeAnimation) + _globals[kMeteorologistStatus] = METEOROLOGIST_PRESENT; + else + _globals[kMeteorologistStatus] = METEOROLOGIST_ABSENT; + } + _scene->_nextSceneId = 201; + } else if (_action.isAction(VERB_TAKE, NOUN_BONE) && (_action._savedFields._mainObjectSource == 4)) { + switch (_game._trigger) { + case 0: + if (_game._objects.isInInventory(OBJ_BONES)) { + _vm->_dialogs->show(20221); + } else { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + case 1: + if (_game._player._playerPos == Common::Point(132, 97)) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals[kBone202Status] |= BONE_202_LEFT_GONE; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals[kBone202Status] |= BONE_202_RIGHT_GONE; + } + break; + case 2: + if (_game._objects.isInInventory(OBJ_BONE)) { + _game._objects.removeFromInventory(OBJ_BONE, NOWHERE); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->showItem(OBJ_BONES, 20218); + } else { + _game._objects.addToInventory(OBJ_BONE); + _vm->_dialogs->showItem(OBJ_BONE, 20218); + } + _scene->changeVariant(_globals[kBone202Status]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + default: + break; + } + + _action._inProgress = false; + } else if (_action.isAction(VERB_CLIMB_UP, NOUN_LADDER) && !_globals[kLadderBroken]) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(29); + _meteoClock1 = _scene->_frameStartTime; + _game._player._visible = false; + _game._player._stepEnabled = false; + + _ladderHotspotId = _scene->_dynamicHotspots.add(NOUN_LADDER, 78, -1, Common::Rect(241, 68, 241 + 12, 68 + 54)); + _scene->_dynamicHotspots.setPosition(_ladderHotspotId, Common::Point(246, 124), FACING_NORTH); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], _globals._sequenceIndexes[9]); + _ladderTopFl = true; + _game._player._stepEnabled = true; + int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(97)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + default: + _action._inProgress = false; + return; + } + } else if ((_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_FIELD_TO_NORTH) || (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_STRANGE_DEVICE))) && (_globals[kSexOfRex] == SEX_MALE)) { + if (!_ladderTopFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible= false; + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + if (_scene->_activeAnimation) { + _waitingMeteoFl = true; + _globals[kMeteorologistWatch] = METEOROLOGIST_GROUND; + } else { + _scene->_sequences.addTimer(120, 2); + } + break; + case 2: + if (!_scene->_activeAnimation && !_meteorologistSpecial) { + _vm->_dialogs->show(20222); + } + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(172, 123)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[10]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + default: + _action._inProgress = false; + return; + } + } else { + switch (_game._trigger) { + case 0: + _toTeleportFl = true; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + case 1: + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[10], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 1); + if (_scene->_activeAnimation) { + if (_scene->_activeAnimation->getCurrentFrame() > 200) { + _scene->_sequences.addTimer(120, 2); + } else { + _waitingMeteoFl = true; + _globals[kMeteorologistWatch] = METEOROLOGIST_GONE; + if ((_scene->_activeAnimation->getCurrentFrame() >= 44) && (_scene->_activeAnimation->getCurrentFrame() <= 75)) { + _scene->_kernelMessages.reset(); + int msgIndex = _scene->_kernelMessages.add(Common::Point(248, 15), 0x1110, 32, 0, 60, _game.getQuote(100)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, false); + } else { + _action._inProgress = false; + return; + } + } + } else { + _scene->_sequences.addTimer(120, 2); + } + break; + case 2: + if (!_scene->_activeAnimation) + _vm->_dialogs->show(20222); + _meteorologistSpecial = false; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + case 3: + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], true, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(247, 82)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 1); + _game._player._stepEnabled = true; + break; + default: + _action._inProgress = false; + return; + } + } + } else if (_action.isAction(VERB_WALK_INSIDE, NOUN_HUT)) { + setRandomKernelMessage(); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) { + _vm->_dialogs->show(20202); + } else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT)) { + _vm->_dialogs->show(20203); + } else if (_action.isAction(VERB_LOOK, NOUN_GRASS)) { + _vm->_dialogs->show(20204); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) { + if ((_globals[kMeteorologistStatus] == METEOROLOGIST_ABSENT) || (_globals[kMeteorologistStatus] == METEOROLOGIST_GONE)) + _vm->_dialogs->show(20205); + else if (_globals[kMeteorologistStatus] == METEOROLOGIST_PRESENT) + _vm->_dialogs->show(20220); + } else if (_action.isAction(VERB_LOOK, NOUN_WATCH_TOWER)) { + _vm->_dialogs->show(20206); + } else if (_action.isAction(VERB_LOOK, NOUN_TALL_GRASS)) { + _vm->_dialogs->show(20207); + } else if (_action.isAction(VERB_LOOK, NOUN_TREES)) { + _vm->_dialogs->show(20208); + } else if (_action.isAction(VERB_LOOK, NOUN_TREE)) { + _vm->_dialogs->show(20209); + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20210); + } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) { + if ((_game._player._playerPos == Common::Point(77, 105)) && (_game._player._facing == FACING_NORTH)) + _vm->_dialogs->show(20212); + else + _vm->_dialogs->show(20211); + } else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + _vm->_dialogs->show(20213); + } else if (_action.isAction(VERB_LOOK, NOUN_OCEAN_IN_DISTANCE)) { + _vm->_dialogs->show(20214); + } else if (_action.isAction(VERB_LOOK, NOUN_SKULL)) { + _vm->_dialogs->show(20215); + } else if (_action.isAction(VERB_TAKE, NOUN_SKULL)) { + _vm->_dialogs->show(20216); + } else if (_action.isAction(VERB_LOOK, NOUN_BONES) && _action._commandSource == 4) { + _vm->_dialogs->show(20217); + } else { + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene203::Scene203(MADSEngine *vm) : Scene2xx(vm) { + _rhotundaEat2Fl = false; + _rhotundaEatFl = false; +} + +void Scene203::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_rhotundaEat2Fl); + s.syncAsByte(_rhotundaEatFl); +} + +void Scene203::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(477); +} + +void Scene203::enter() { + if (_scene->_priorSceneId == 202) { + _game._player._playerPos = Common::Point(187, 99); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 209) { + _game._player._playerPos = Common::Point(308, 117); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(155, 152); + _game._player._facing = FACING_NORTH; + } + + _rhotundaEatFl = false; + _rhotundaEat2Fl = false; + + if ((_globals[kRhotundaStatus] == 0) && (!_scene->_roomChanged)) { + _rhotundaEatFl = true; + _game._player.walk(Common::Point(158, 135), FACING_SOUTH); + int idx = _scene->_dynamicHotspots.add(131, 396, 0, Common::Rect(0, 0, 320, 156)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(155, 152), FACING_SOUTH); + _scene->_dynamicHotspots.setCursor(idx, CURSOR_GO_DOWN); + } + + if (!_rhotundaEatFl) { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', -1)); + if (_vm->getRandomNumber(1, 3) == 2) { + _globals._spriteIndexes[15] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 9, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(477, 209, _globals._spriteIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + _vm->_sound->command(14); + } + } + + _game.loadQuoteSet(0x67, 0x68, 0x69, 0x6A, 0x5A, 0); + + if (_rhotundaEatFl) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(_vm->getRandomNumber(103, 106))); + } + + sceneEntrySound(); +} + +void Scene203::step() { + if (!_rhotundaEatFl) + return; + + if ((_game._trigger == 0) && _rhotundaEat2Fl) + return; + + if ((_game._player._playerPos != Common::Point(158, 136)) || (_game._player._facing != FACING_SOUTH)) + return; + + _rhotundaEat2Fl = true; + + if (_game._trigger == 0) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _vm->_events->setCursor2(CURSOR_WAIT); + _scene->loadAnimation(Resources::formatName(203, 'a', -1, EXT_AA, ""), 81); + } else if (_game._trigger == 81) { + _scene->_nextSceneId = 208; + _scene->_reloadSceneFlag = true; + } +} + +void Scene203::preActions() { + if (_rhotundaEatFl && !_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _game._player.walk(Common::Point(158, 136), FACING_SOUTH); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALKTO, NOUN_OPEN_AREA_TO_EAST)) + _game._player._walkOffScreenSceneId = 209; +} + +void Scene203::actions() { + if (_action._savedFields._lookFlag) { + _vm->_dialogs->show(20307); + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) { + _scene->_nextSceneId = 208; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_NORTH)) { + _scene->_nextSceneId = 202; + } else if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20301); + } else if (_action.isAction(VERB_LOOK, NOUN_CLIFF_FACE)) { + _vm->_dialogs->show(20302); + } else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + _vm->_dialogs->show(20303); + } else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) { + _vm->_dialogs->show(20304); + } else if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20305); + } else if (_action.isAction(VERB_LOOK, NOUN_BOULDERS)) { + _vm->_dialogs->show(20305); + } else + return; + + _action._inProgress = false; +} + +/*****************************************************************************/ + +void Scene205::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_CHICKEN); + _scene->addActiveVocab(NOUN_PIRANHA); +} + +Scene205::Scene205(MADSEngine *vm) : Scene2xx(vm) { + _lastFishTime = 0; + _chickenTime = 0; + _beingKicked = false; + _kernelMessage = -1; +} + +void Scene205::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsUint32LE(_lastFishTime); + s.syncAsUint32LE(_chickenTime); + s.syncAsByte(_beingKicked); + s.syncAsSint16LE(_kernelMessage); +} + +void Scene205::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('p', -1)); + + if (_globals[kSexOfRex] == SEX_MALE) + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 0, 3); + int idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + idx = _scene->_dynamicHotspots.add(73, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(162, 120), FACING_NORTHEAST); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 11); + + if (!_game._visitedScenes._sceneRevisited) { + _lastFishTime = _scene->_frameStartTime; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH); + } + + if (_game._objects[12]._roomNumber == 205) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + } else { + _scene->_hotspots.activate(450, false); + } + + _beingKicked = false; + _game.loadQuoteSet(0x6B, 0x70, 0x71, 0x72, 0x5A, 0x74, 0x75, 0x76, 0x77, 0x78, 0x73, 0x79, 0x7A, 0x7B, 0x7C, + 0x7D, 0x7E, 0x7F, 0x80, 0xAC, 0xAD, 0xAE, 0x6C, 0x6D, 0x6E, 0x6F, 0x2, 0); + _dialog1.setup(0x2A, 0x5A, 0x78, 0x74, 0x75, 0x76, 0x77, 0); + + if (!_game._visitedScenes._sceneRevisited) + _dialog1.set(0x5A, 0x74, 0x75, 0x77, 0); + + _vm->_palette->setEntry(250, 63, 50, 20); + _vm->_palette->setEntry(251, 50, 40, 15); + _vm->_palette->setEntry(252, 63, 63, 40); + _vm->_palette->setEntry(253, 50, 50, 30); + + _chickenTime = _vm->_game->_scene._frameStartTime; + + if (_globals[kSexOfRex] == SEX_FEMALE) + _scene->_kernelMessages.initRandomMessages(3, + Common::Rect(195, 99, 264, 134), 13, 2, 0xFDFC, 60, + 108, 108, 109, 109, 110, 110, 111, 108, 0); + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(99, 152); + + if (_globals[kSexOfRex] != SEX_MALE) { + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->_resetFlag = false; + } else { + _beingKicked = true; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 6, 73); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 11, 74); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + sceneEntrySound(); +} + +void Scene205::step() { + if (_globals[kSexOfRex] == SEX_FEMALE) { + _scene->_kernelMessages.randomServer(); + + if (_vm->_game->_scene._frameStartTime >= _chickenTime) { + int chanceMinor = _scene->_kernelMessages.checkRandom() + 1; + if (_scene->_kernelMessages.generateRandom(100, chanceMinor)) + _vm->_sound->command(28); + + _chickenTime = _vm->_game->_scene._frameStartTime + 2; + } + } + + if (_vm->_game->_scene._frameStartTime - _lastFishTime > 1300) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle( + _globals._spriteIndexes[6], false, 5, 1, 0, 0); + int idx = _scene->_dynamicHotspots.add(269, 13, _globals._sequenceIndexes[6], + Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(49, 86), FACING_NORTH); + _lastFishTime = _vm->_game->_scene._frameStartTime; + } + + if (_game._trigger == 73) + _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 0, 60, _game.getQuote(112)); + + if (_game._trigger == 74) { + _vm->_sound->command(26); + _scene->_kernelMessages.add(Common::Point(106, 90), 0x1110, 32, 0, 60, _game.getQuote(113)); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 2); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], -2, -2); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 68), 0xFBFA, 32, 72, 180, _game.getQuote(114)); + } + + if (_game._trigger == 72) + _scene->_nextSceneId = 211; +} + +void Scene205::handleWomanSpeech(int quote) { + _kernelMessage = _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 9999999, _game.getQuote(quote)); +} + +void Scene205::actions() { + if (_game._screenObjects._inputMode == 1) { + if (_kernelMessage >= 0) + _scene->_kernelMessages.remove(_kernelMessage); + _kernelMessage = -1; + + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(_action._activeAction._verbId)); + } else { + if ((_game._trigger > 1) || (_action._activeAction._verbId != 0x76)) + _game._player._stepEnabled = true; + + switch (_action._activeAction._verbId) { + case 0x5A: + handleWomanSpeech(0x7A); + _dialog1.write(0x78, true); + _dialog1.write(0x5A, false); + break; + + case 0x74: + handleWomanSpeech(0x7C); + _dialog1.write(0x74, false); + _dialog1.write(0x76, true); + break; + + case 0x75: + case 0x78: + handleWomanSpeech(0x7B); + _dialog1.write(_action._activeAction._verbId, false); + _vm->_dialogs->show(20501); + break; + + case 0x76: + if (_game._trigger == 1) { + handleWomanSpeech(0x7D); + _scene->_sequences.addTimer(120, 2); + } else if (_game._trigger == 2) { + handleWomanSpeech(0x7E); + _dialog1.write(0x76, false); + _globals[kChickenPermitted] = true; + } + break; + + case 0x77: + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 0, 0, 120, _game.getQuote(0x7F)); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } + + if (_action._activeAction._verbId != 0x77) + _dialog1.start(); + } + } else if (_action._lookFlag) + _vm->_dialogs->show(20502); + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_OPPOSITE_BANK)) + _vm->_dialogs->show(20518); + else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN)) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 18, 1, 120, _game.getQuote(0x73)); + } else if (_game._trigger == 1) { + _game._player._stepEnabled = true; + handleWomanSpeech (0x79); + _dialog1.write(0x5A, true); + _dialog1.write(0x75, true); + _dialog1.start(); + } + } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + int rndVal = _vm->getRandomNumber(0xAC, 0xAE); + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 1, 120, _game.getQuote(rndVal)); + } else if (_game._trigger == 1) + _game._player._stepEnabled = true; + } else if (_action.isAction(VERB_WALKTO, NOUN_OPPOSITE_BANK)) { + if (_game._trigger == 0) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _game._player.removePlayerSprites(); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _vm->_palette->refreshSceneColors(); + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1); + _vm->_sound->command(27); + } else if (_game._trigger == 1) { + if (_scene->_activeAnimation != nullptr) + _scene->_activeAnimation->resetSpriteSetsCount(); + + _vm->_dialogs->show(20516); + _scene->_reloadSceneFlag = true; + } + } else { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_SOUTH)) + _scene->_nextSceneId = 210; + + if (_action.isAction(VERB_WALKTO, NOUN_FIRE_PIT) || _action.isAction(VERB_WALKTO, NOUN_CHICKEN_ON_SPIT)) { + if (_game._objects.isInRoom(OBJ_CHICKEN)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x6B)); + } + } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && _globals[kChickenPermitted] && _game._objects.isInRoom(OBJ_CHICKEN)) { + _game._objects.addToInventory(OBJ_CHICKEN); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_hotspots.activate(NOUN_CHICKEN_ON_SPIT, false); + _vm->_dialogs->showItem(OBJ_CHICKEN, 812); + } else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN_ON_SPIT) && (!_globals[kChickenPermitted])) + _scene->_kernelMessages.add(Common::Point(186, 27), 0xFBFA, 32, 0, 120, _game.getQuote(0x80)); + else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN)) + _vm->_dialogs->show(20503); + else if (_action.isAction(VERB_LOOK, NOUN_HUT)) + _vm->_dialogs->show(20504); + else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(20505); + else if (_action.isAction(VERB_TAKE, NOUN_CHICKEN) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(20506); + else if (_action.isAction(VERB_LOOK, NOUN_CHICKEN_ON_SPIT)) + _vm->_dialogs->show(20507); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_PIT)) + _vm->_dialogs->show(20508); + else if (_action.isAction(VERB_TAKE, NOUN_FIRE_PIT)) + _vm->_dialogs->show(20509); + else if (_action.isAction(VERB_LOOK, NOUN_STREAM)) + _vm->_dialogs->show(20510); + else if (_action.isAction(VERB_LOOK, NOUN_OPPOSITE_BANK)) + _vm->_dialogs->show(20511); + else if (_game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId)) + && ( _action.isAction(VERB_GIVE, NOUN_STREAM) || _action.isAction(VERB_THROW, NOUN_STREAM) + || _action.isAction(VERB_GIVE, NOUN_PIRANHA) || _action.isAction(VERB_THROW, NOUN_PIRANHA))) + _vm->_dialogs->show(20512); + else if (_action.isAction(VERB_LOOK, NOUN_PIRANHA)) + _vm->_dialogs->show(20513); + else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT_BUSH)) + _vm->_dialogs->show(20514); + else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT_BUSH)) + _vm->_dialogs->show(20515); + else if (_action.isAction(VERB_TAKE, NOUN_NATIVE_WOMAN)) + _vm->_dialogs->show(20517); + else + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene207::Scene207(MADSEngine *vm) : Scene2xx(vm) { + _vultureFl = false; + _spiderFl = false; + _eyeFl = false; + _spiderHotspotId = -1; + _vultureHotspotId = -1; + _spiderTime = 0; + _vultureTime = 0; +} + +void Scene207::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_vultureFl); + s.syncAsByte(_spiderFl); + s.syncAsByte(_eyeFl); + + s.syncAsSint32LE(_spiderHotspotId); + s.syncAsSint32LE(_vultureHotspotId); + s.syncAsSint32LE(_spiderTime); + s.syncAsSint32LE(_vultureTime); +} + +void Scene207::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_VULTURE); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_SPIDER); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene207::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('h', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 7); + + int var2; + if (!_game._visitedScenes._sceneRevisited) { + var2 = 1; + } else { + var2 = _vm->getRandomNumber(4) + 1; + } + + if (var2 > 2) + _vultureFl = false; + else + _vultureFl = true; + + _spiderFl = (var2 & 1); + + if (_vultureFl) { + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 30, 0, 0, 400); + _vultureTime = _game._player._priorTimer; + _vultureHotspotId = _scene->_dynamicHotspots.add(389, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_vultureHotspotId, Common::Point(254, 94), FACING_WEST); + } + + if (_spiderFl) { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -1); + _spiderTime = _game._player._priorTimer; + _spiderHotspotId = _scene->_dynamicHotspots.add(333, 13, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_spiderHotspotId, Common::Point(59, 132), FACING_SOUTH); + } + + _eyeFl = false; + if (_scene->_priorSceneId == 211) { + _game._player._playerPos = Common::Point(13, 105); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 214) { + _game._player._playerPos = Common::Point(164, 117); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(305, 131); + } + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 22); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 70); +} + +void Scene207::moveVulture() { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _vm->_sound->command(43); + _vultureFl = false; + _vultureTime = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_vultureHotspotId); +} + +void Scene207::moveSpider() { + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _spiderFl = false; + _spiderTime = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_spiderHotspotId); +} + +void Scene207::step() { + if (!_vultureFl) + moveVulture(); + + if (_spiderFl) + moveSpider(); + + if (_game._trigger == 70) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 23, 34); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + } + + if (_game._trigger == 71) + _eyeFl = false; + + if (_eyeFl) + return; + + if ((_game._player._playerPos.x >= 124) && (_game._player._playerPos.x <= 201)) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _eyeFl = true; + } +} + +void Scene207::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) + _game._player._walkOffScreenSceneId = 211; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_FIELD_TO_EAST)) + _game._player._walkOffScreenSceneId = 208; + + if (_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) { + if (_action.isObject(NOUN_VULTURE)) { + _vultureTime = -9999; + } else if (_action.isObject(NOUN_SPIDER)) { + _spiderTime = -9999; + } + } +} + +void Scene207::actions() { + if (_action._savedFields._lookFlag) + _vm->_dialogs->show(20711); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 214; + else { + if ((_game._player._playerPos.x > 150) && (_game._player._playerPos.x < 189) && + (_game._player._playerPos.y > 111) && (_game._player._playerPos.y < 130)) { + if ((_game._player._playerPos.x <= 162) || (_game._player._playerPos.x >= 181) || + (_game._player._playerPos.y <= 115) || (_game._player._playerPos.y >= 126)) { + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 2, 0, 0); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + } + } else if (_eyeFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _eyeFl = false; + } + + if (_action.isAction(VERB_LOOK, NOUN_DENSE_FOREST)) + _vm->_dialogs->show(20701); + else if (_action.isAction(VERB_LOOK, NOUN_HEDGE)) + _vm->_dialogs->show(20702); + else if (_action.isAction(VERB_LOOK, NOUN_SKULL_AND_CROSSBONES)) + _vm->_dialogs->show(20703); + else if (_action.isAction(VERB_LOOK, NOUN_CAULDRON)) + _vm->_dialogs->show(20704); + else if (_action.isAction(VERB_LOOK, NOUN_WITCHDOCTOR_HUT)) + _vm->_dialogs->show(20705); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST)) + _vm->_dialogs->show(20706); + else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS)) + _vm->_dialogs->show(20707); + else if (_action.isAction(VERB_LOOK, NOUN_ALOE_PLANT)) + _vm->_dialogs->show(20708); + else if (_action.isAction(VERB_LOOK, NOUN_LAWN)) + _vm->_dialogs->show(20709); + else if (_action.isAction(VERB_LOOK, NOUN_VULTURE)) + _vm->_dialogs->show(20710); + else if (_action.isAction(VERB_TAKE, NOUN_SKULL_AND_CROSSBONES)) + _vm->_dialogs->show(20712); + else if (_action.isAction(VERB_TAKE, NOUN_ALOE_PLANT)) + _vm->_dialogs->show(20713); + else if (_action.isAction(VERB_LOOK, NOUN_SPIDER)) + _vm->_dialogs->show(20714); + else if (_action.isAction(VERB_TAKE, NOUN_SPIDER)) + _vm->_dialogs->show(20715); + else + return; + } + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene208::Scene208(MADSEngine *vm) : Scene2xx(vm) { + _rhotundaTurnFl = false; + _boundingFl = false; + _rhotundaTime = 0; +} + +void Scene208::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_rhotundaTurnFl); + s.syncAsByte(_boundingFl); + s.syncAsSint32LE(_rhotundaTime); +} + +void Scene208::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_HUGE_LEGS); + _scene->addActiveVocab(NOUN_LEAF_COVERED_PIT); + _scene->addActiveVocab(NOUN_PILE_OF_LEAVES); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene208::updateTrap() { + if (_globals[kRhotundaStatus] == 1) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 0, 0, 24); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + int idx = _scene->_dynamicHotspots.add(NOUN_HUGE_LEGS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH); + _scene->_hotspots.activate(414, false); + return; + } + + switch (_globals[kLeavesStatus]) { + case 0: { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 15); + int idx = _scene->_dynamicHotspots.add(NOUN_PILE_OF_LEAVES, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(60, 152), FACING_NORTH); + } + break; + case 2: { + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_hotspots.activate(NOUN_DEEP_PIT, false); + int idx = _scene->_dynamicHotspots.add(NOUN_LEAF_COVERED_PIT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(100, 146), FACING_NORTH); + _scene->_dynamicHotspots[idx]._articleNumber = PREP_ON; + } + break; + } +} + +void Scene208::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8"); + + updateTrap(); + + _rhotundaTurnFl = false; + _boundingFl = false; + _scene->_kernelMessages._talkFont = _vm->_font->getFont(FONT_INTERFACE); + _scene->_textSpacing = 0; + + if (_scene->_priorSceneId == 207) { + _game._player._playerPos = Common::Point(8, 122); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 203) { + _game._player._playerPos = Common::Point(142, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 209) { + _game._player._playerPos = Common::Point(307, 123); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(162, 149); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x81, 0x46, 0); + + if ((_scene->_priorSceneId == 207) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) { + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(129)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + + _vm->_palette->setEntry(16, 0, 0, 63); + _vm->_palette->setEntry(17, 0, 0, 45); + sceneEntrySound(); +} + +void Scene208::step() { + if (_boundingFl && (_rhotundaTime <= _scene->_activeAnimation->getCurrentFrame())) { + _rhotundaTime = _scene->_activeAnimation->getCurrentFrame(); + + if (_rhotundaTime == 125) + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + } + + if (!_rhotundaTurnFl) + return; + + if ((_game._player._playerPos != Common::Point(20, 148)) || (_game._player._facing != FACING_EAST)) + return; + + if ((_game._trigger == 0) && _boundingFl) + return; + + _boundingFl = true; + + switch (_game._trigger) { + case 0: + _scene->loadAnimation(formAnimName('A', -1), 81); + _rhotundaTime = 0; + break; + case 81: + _scene->_sequences.remove(_globals._spriteIndexes[15]); + _globals[kRhotundaStatus] = 1; + updateTrap(); + _scene->_sequences.addTimer(90, 82); + break; + case 82: + _game._player._stepEnabled = true; + break; + } +} + +void Scene208::preActions() { + Player &player = _vm->_game->_player; + + if (_action.isAction(VERB_LOOK) && player._readyToWalk) + player._needToWalk = true; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_GRASSLAND_TO_EAST)) + player._walkOffScreenSceneId = 209; + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_OPEN_AREA_TO_WEST)) + player._walkOffScreenSceneId = 207; +} + +void Scene208::subAction(int mode) { + + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + + int abortVal; + if ((mode == 1) || (mode == 2)) + abortVal = 1; + else + abortVal = 2; + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + } + break; + case 1: { + int oldVal = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 3, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _vm->_sound->command(20); + } + break; + + case 2: { + switch (mode) { + case 1: + _game._objects.addToInventory(OBJ_BIG_LEAVES); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals[kLeavesStatus] = 1; + break; + + case 2: + _game._objects.setRoom(OBJ_BIG_LEAVES, 1); + _globals[kLeavesStatus] = 2; + updateTrap(); + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _game._objects.removeFromInventory(OBJ_TWINKIFRUIT, 1); + _vm->_sound->command(34); + break; + + case 4: + _game._objects.removeFromInventory(OBJ_BURGER, 1); + _vm->_sound->command(33); + break; + + case 5: + _game._objects.removeFromInventory(OBJ_DEAD_FISH, 1); + _vm->_sound->command(33); + break; + + default: + break; + } + + int oldVal = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldVal); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene208::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LOWLANDS_TO_NORTH)) { + if (_globals[kRhotundaStatus]) + _scene->_nextSceneId = 203; + else if (_game._trigger == 0) { + _game._player._stepEnabled = false; + int msgIndex = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, _game.getQuote(70)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } else if (_game._trigger == 1) + _scene->_nextSceneId = 203; + } else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_SOUTH)) + _scene->_nextSceneId = 212; + else if (_action.isAction(VERB_TAKE, NOUN_PILE_OF_LEAVES) && (!_globals[kLeavesStatus] || _game._trigger)) { + subAction(1); + if (_game._player._stepEnabled) + _vm->_dialogs->showItem(OBJ_BIG_LEAVES, 0x326, 0); + } else if (_action.isAction(VERB_PUT, NOUN_BIG_LEAVES, NOUN_DEEP_PIT) && (_globals[kLeavesStatus] == 1 || _game._trigger)) + subAction(2); + else if (_action.isAction(VERB_PUT, NOUN_TWINKIFRUIT, NOUN_LEAF_COVERED_PIT)) { + subAction(3); + if (_game._player._stepEnabled) { + _game._player._stepEnabled = false; + _rhotundaTurnFl = true; + _game._player.walk(Common::Point(20, 148), FACING_EAST); + } + } else if (_action.isAction(VERB_PUT, NOUN_BURGER, NOUN_LEAF_COVERED_PIT)) { + subAction(4); + if (_game._player._stepEnabled) + _vm->_dialogs->show(20812); + } else if (_action.isAction(VERB_PUT, NOUN_DEAD_FISH, NOUN_LEAF_COVERED_PIT)) { + subAction(5); + if (_game._player._stepEnabled) + _vm->_dialogs->show(20812); + } else if (_action.isAction(VERB_LOOK, NOUN_CUMULOUS_CLOUD)) + _vm->_dialogs->show(20801); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_AREA_TO_WEST)) + _vm->_dialogs->show(20802); + else if (_action.isAction(VERB_LOOK, NOUN_THORNY_BUSH)) + _vm->_dialogs->show(20803); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(20804); + else if (_action.isAction(VERB_LOOK, NOUN_SMALL_CACTUS)) + _vm->_dialogs->show(20805); + else if (_action.isAction(VERB_TAKE, NOUN_SMALL_CACTUS)) + _vm->_dialogs->show(20806); + else if (_action.isAction(VERB_LOOK, NOUN_GRASSLAND_TO_EAST)) + _vm->_dialogs->show(20807); + else if (_action.isAction(VERB_LOOK, NOUN_DEEP_PIT)) + _vm->_dialogs->show(20808); + else if (_action.isAction(VERB_LOOK, NOUN_PILE_OF_LEAVES)) + _vm->_dialogs->show(20809); + else if (_action.isAction(VERB_LOOK, NOUN_LEAF_COVERED_PIT)) { + if (_game._difficulty == DIFFICULTY_EASY) + _vm->_dialogs->show(20810); + else + _vm->_dialogs->show(20811); + } else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(20813); + else if (_action.isAction(VERB_TAKE, NOUN_LEAF_COVERED_PIT)) + _vm->_dialogs->show(20814); + else if (_action.isAction(VERB_LOOK, NOUN_HUGE_LEGS)) + _vm->_dialogs->show(20815); + else if (_action.isAction(VERB_TAKE, NOUN_HUGE_LEGS) || _action.isAction(VERB_PULL, NOUN_HUGE_LEGS)) + _vm->_dialogs->show(20816); + else if (_action._savedFields._lookFlag && (_globals[kRhotundaStatus] == 1)) + _vm->_dialogs->show(20819); + else if (_action._savedFields._lookFlag && (_globals[kLeavesStatus] == 2)) + _vm->_dialogs->show(20818); + else if (_action._savedFields._lookFlag) + _vm->_dialogs->show(20817); + else + return; + + _action._inProgress = false; +} + +/*****************************************************************************/ + +Scene209::Scene209(MADSEngine *vm) : Scene2xx(vm) { + _dodgeFl = false; + _forceDodgeFl = false; + _pitchFl = false; + _fallFl = false; + _forceFallFl = false; + _playingAnimFl = false; + _shouldFallFl = false; + _shouldDodgeFl = false; + _monkeyPosition = 0; + _counter = 0; + _pauseMode = 0; + _binocularsDroppedFl = false; + _startShootingInTimerFl = false; + _dialogAbortVal = 0; + _playingDialogFl = false; + _shootMissedLastFl = false; + _removeMonkeyFl = false; + _shootReadyFl = false; + _pauseCounterThreshold = 0; + _pauseCounter = 0; +} + +void Scene209::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_dodgeFl); + s.syncAsByte(_forceDodgeFl); + s.syncAsByte(_shouldDodgeFl); + s.syncAsByte(_pitchFl); + s.syncAsByte(_fallFl); + s.syncAsByte(_forceFallFl); + s.syncAsByte(_shouldFallFl); + s.syncAsByte(_playingAnimFl); + s.syncAsByte(_playingDialogFl); + + s.syncAsSint32LE(_pauseMode); + s.syncAsSint32LE(_pauseCounterThreshold); + s.syncAsSint32LE(_pauseCounter); + + s.syncAsByte(_removeMonkeyFl); + + s.syncAsSint32LE(_monkeyPosition); + + s.syncAsByte(_shootReadyFl); + s.syncAsByte(_startShootingInTimerFl); + s.syncAsByte(_shootMissedLastFl); + s.syncAsByte(_binocularsDroppedFl); + + s.syncAsSint32LE(_dialogAbortVal); + s.syncAsSint32LE(_counter); +} + +void Scene209::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PLANT_STALK); +} + +void Scene209::handlePause() { + switch (_game._trigger) { + case 124: + if (++_pauseCounter <= _pauseCounterThreshold) + _scene->_sequences.addTimer(60, 124); + else + _pauseMode = 0; + break; + } +} + +void Scene209::initPauseCounterThreshold() { + switch (_game._trigger) { + case 226: + _scene->_sequences.addTimer(1, 124); + _pauseCounterThreshold = _vm->getRandomNumber(7,12); + _pauseMode = 2; + _pauseCounter = 0; + break; + } +} + +void Scene209::handlePeek() { + switch (_game._trigger) { + case 133: + _vm->_sound->command(18); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 134); + break; + + case 134: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 135); + } + break; + + case 135: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(10, 136); + break; + + case 136: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 137); + break; + + case 137: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 138); + break; + + case 138: + _pauseMode = 1; + _scene->_hotspots.activate(227, false); + _playingAnimFl = false; + break; + } +} + +void Scene209::handleVerticalMove() { + switch (_game._trigger) { + case 140: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 8, 0, 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 141); + break; + + case 141: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 142); + } + break; + + case 142: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 143); + break; + + case 143: + _pauseMode = 1; + _playingAnimFl = false; + _scene->_hotspots.activate(227, false); + break; + } +} + +void Scene209::handleLookStay() { + switch (_game._trigger) { + case 145: + _vm->_sound->command(18); + _monkeyPosition = 2; + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 51, 52); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 146); + break; + + case 146: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 147); + } + break; + + case 147: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(8, 148); + break; + + case 148: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + + if (!_dodgeFl) { + _scene->_sequences.addTimer(90, 149); + } else { + _scene->_sequences.addTimer(1, 149); + _shouldDodgeFl = true; + } + break; + + case 149: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleLookRight() { + switch (_game._trigger) { + case 151: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 152); + break; + + case 152: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 153); + } + break; + + case 153: + _playingAnimFl = false; + if (_dodgeFl) + _shouldDodgeFl = true; + break; + } +} + +void Scene209::handleBlink() { + switch (_game._trigger) { + case 155: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 156); + break; + + case 156: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(10, 157); + break; + + case 157: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(50, 158); + break; + + case 158: + _playingAnimFl = false; + if (_dodgeFl) + _shouldDodgeFl = true; + break; + } +} + +void Scene209::handleGetBinoculars() { + switch (_game._trigger) { + case 161: + _vm->_sound->command(18); + _monkeyPosition = 3; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 24); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 20, 165); + if (!_fallFl && !_dodgeFl) { + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 162); + } else { + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + } + break; + + case 162: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + } + break; + + case 163: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(8, 164); + } + break; + + case 164: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + + case 165: + _vm->_sound->command(18); + break; + } +} + +void Scene209::handleBinocularBlink() { + switch (_game._trigger) { + case 167: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 168); + } + break; + + case 168: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(30, 169); + } + break; + + case 169: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + } +} + +void Scene209::handleBinocularScan() { + switch (_game._trigger) { + case 171: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 43, 45); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 172); + } + break; + + case 172: { + int oldIdx = _globals._sequenceIndexes[3]; + int randAction = _vm->getRandomNumber(1,2); + switch (randAction) { + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + break; + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 4, 0, 0); + break; + } + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 173); + } + break; + + case 173: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 174); + } + break; + + case 174: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 23, 24); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(60, 175); + } + break; + + case 175: + _playingAnimFl = false; + if (_fallFl) + _shouldFallFl = true; + break; + } +} + +void Scene209::handleJumpInTree() { + switch (_game._trigger) { + case 178: { + int oldIdx = 0; + _monkeyPosition = 1; + if (_removeMonkeyFl) + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + else + oldIdx = _globals._sequenceIndexes[3]; + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 46, 49); + if (!_removeMonkeyFl) + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 179); + } + break; + + case 179: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 53, 61); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 180); + } + break; + + case 180: + _removeMonkeyFl = true; + _pauseMode = 1; + _playingAnimFl = false; + _scene->_hotspots.activate(227, false); + break; + } +} + +void Scene209::handleTongue() { + switch (_game._trigger) { + case 182: { + int oldIdx = _globals._sequenceIndexes[3]; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 30); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 183); + } + break; + + case 183: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 31, 33); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 184); + } + break; + + case 184: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 36, 37); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 185); + } + break; + + case 185: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 20, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 38, 39); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 186); + } + break; + + case 186: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 40, 41); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 178); + _removeMonkeyFl = false; + } + break; + } +} + +void Scene209::handleStandFromPeek() { + switch (_game._trigger) { + case 189: + _monkeyPosition = 4; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 50); + _scene->_sequences.addTimer(8, 190); + break; + + case 190: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.addTimer(8, 191); + break; + + case 191: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 192); + break; + + case 192: { + _vm->_sound->command(18); + int oldIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addTimer(8, 193); + } + break; + + case 193: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(5, 194); + break; + + case 194: + _playingAnimFl = false; + _counter = 0; + break; + } +} + +void Scene209::handleStandBlink() { + switch (_game._trigger) { + case 246: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(10, 247); + break; + + case 247: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 23); + _scene->_sequences.addTimer(8, 248); + break; + + case 248: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.addTimer(10, 249); + break; + + case 249: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleJumpAndHide() { + switch (_game._trigger) { + case 196: + _vm->_sound->command(18); + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 16); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 197); + break; + + case 197: + _pauseMode = 1; + _scene->_hotspots.activate(227, false); + _playingAnimFl = false; + break; + } +} + +void Scene209::handleMonkeyEating() { + switch (_game._trigger) { + case 199: + _vm->_sound->command(18); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 200); + break; + + case 200: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 10, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 15, 16); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 201); + } + break; + + case 201: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(20, 202); + } + break; + + case 202: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 19); + _scene->_sequences.addTimer(20, 203); + break; + + case 203: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 17); + _scene->_sequences.addTimer(20, 204); + break; + + case 204: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 18, 19); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 205); + break; + + case 205: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 20, 21); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 206); + } + break; + + case 206: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 22, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + if (!_dodgeFl && !_fallFl) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 207); + else + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209); + } + break; + + case 207: { + _vm->_sound->command(18); + int msgIndex = _scene->_kernelMessages.add(Common::Point(180, 25), 0xFDFC, 0, 0, 90, _game.getQuote(130)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 26, 27); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 208); + } + break; + + case 208: { + _scene->_kernelMessages.add(Common::Point(180, 39), 0xFDFC, 0, 0, 90, _game.getQuote(131)); + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 28, 29); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 209); + } + break; + + case 209: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(1, 210); + } + break; + + case 210: + _playingAnimFl = false; + break; + } +} + +void Scene209::handleMonkeyFall() { + switch (_game._trigger) { + case 219: { + _vm->_sound->command(25); + _scene->_sprites.remove(_globals._spriteIndexes[7]); + _scene->_sprites.remove(_globals._spriteIndexes[6]); + _scene->_sprites.remove(_globals._spriteIndexes[5]); + _scene->_sprites.remove(_globals._spriteIndexes[4]); + + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('m', 4)); + _scene->_kernelMessages.add(Common::Point(180, 26), 0xFDFC, 0, 0, 90, _game.getQuote(151)); + _scene->_sequences.addTimer(40, 100); + _scene->_hotspots.activate(227, false); + int oldIdx = _globals._sequenceIndexes[3]; + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 35); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 220); + } + break; + + case 220: { + _vm->_sound->command(18); + _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 90, _game.getQuote(159)); + _scene->_hotspots.activate(227, false); + int oldIdx = _globals._sequenceIndexes[3]; + _monkeyPosition = 1; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 36, 42); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 221); + } + break; + + case 221: { + _game._objects.setRoom(OBJ_BINOCULARS, 209); + _binocularsDroppedFl = true; + int oldIdx = _globals._sequenceIndexes[8]; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], oldIdx); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 43, 72); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 222); + int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH); + } + break; + + case 222: { + _scene->_kernelMessages.add(Common::Point(182, 109), 0xFDFC, 0, 0, 70, _game.getQuote(160)); + int oldIdx = _globals._sequenceIndexes[8]; + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 73, 78); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[8], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 223); + } + break; + + case 223: + _scene->loadAnimation(Resources::formatName(209, 'e', -1, EXT_AA, ""), 224); + _vm->_sound->command(38); + break; + + case 224: + _playingAnimFl = false; + _fallFl = false; + _counter = 0; + _pauseMode = 0; + _vm->_dialogs->show(20910); + _game._player._stepEnabled = true; + break; + } +} + +void Scene209::handleMonkey1() { + switch (_game._trigger) { + case 212: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 13); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 213); + break; + + case 213: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 214); + } + break; + + case 214: { + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 23, 26); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 215); + int msgIndex = _scene->_kernelMessages.add(Common::Point(170, 21), 0xFDFC, 0, 0, 90, _game.getQuote(156)); + _scene->_kernelMessages.setQuoted(msgIndex, 3, true); + } + break; + + case 215: { + _vm->_sound->command(18); + _scene->loadAnimation(Resources::formatName(209, 'a', -1, EXT_AA, ""), 251); + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 27, 35); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 216); + } + break; + + case 216: { + int oldIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 22); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(25, 217); + } + break; + + case 217: + _pitchFl = false; + _counter = 0; + _pauseMode = 0; + _scene->_sequences.addTimer(1, 196); + break; + } +} + +void Scene209::handleMonkey2() { + switch (_game._trigger) { + case 251: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(137)); + _vm->_sound->command(22); + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 11, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133)); + _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 252); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = false; + break; + + case 252: { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(132)); + int oldIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[12], Common::Point(111, 133)); + _scene->_sequences.setScale(_globals._sequenceIndexes[12], 79); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], oldIdx); + _scene->_sequences.addTimer(120, 253); + } + break; + + case 253: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + } +} + +void Scene209::handleDodge() { + switch (_game._trigger) { + case 241: + _scene->_hotspots.activate(227, true); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.addTimer(6, 242); + break; + + case 242: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.addTimer(25, 243); + _vm->_sound->command(24); + break; + + case 243: + _vm->_sound->command(18); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _playingAnimFl = false; + _pauseMode = 0; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 90, _game.getQuote(155)); + if (!_shootMissedLastFl) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(135)); + _shootMissedLastFl = true; + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(136)); + } + break; + } +} + +void Scene209::enter() { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('m', 3)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('m', 6)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('m', 8)); + + _game.loadQuoteSet(0x82, 0x83, 0x84, 0x9C, 0x97, 0x95, 0x99, 0x9E, 0x98, 0x9B, 0xA0, 0x96, 0x9F, + 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91, 0x92, 0x93, 0x94, 0x89, 0x85, 0x8A, 0x86, 0x87, 0x88, 0); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + + if (_game._objects.isInRoom(OBJ_PLANT_STALK)) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(271, 13, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(263, 129), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 13); + } + + if (_scene->_priorSceneId == 208) { + _game._player._playerPos = Common::Point(11, 121); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(28, 121); + _game._player._facing = FACING_SOUTH; + } + + if (_game._objects.isInRoom(OBJ_BINOCULARS)) { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[9], Common::Point(201, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(39, 13, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(200, 133), FACING_NORTH); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_POISON_DARTS); + _game._objects.addToInventory(OBJ_BLOWGUN); + _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS; + } + + _pitchFl = false; + _fallFl = false; + _dodgeFl = false; + _playingAnimFl = false; + _monkeyPosition = 1; + _counter = 0; + _pauseMode = 0; + _forceFallFl = false; + _shouldFallFl = false; + _forceDodgeFl = false; + _binocularsDroppedFl = false; + _shouldDodgeFl = false; + _startShootingInTimerFl = false; + _dialogAbortVal = 5; + _playingDialogFl = false; + _shootMissedLastFl = false; + _removeMonkeyFl = true; + _shootReadyFl = false; + + _scene->_hotspots.activate(227, false); + + sceneEntrySound(); +} + +void Scene209::step() { + if (!_playingAnimFl && !_pitchFl && !_fallFl && !_dodgeFl && (_pauseMode == 0) && (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS)) { + int randAction = _vm->getRandomNumber(1,50); + switch (randAction) { + case 1: + if ((_monkeyPosition == 1) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 133); + _playingAnimFl = true; + _scene->_hotspots.activate(227, true); + ++_counter; + } + break; + + case 2: + if ((_monkeyPosition == 1) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 140); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + ++_counter; + } + break; + + case 3: + if (_monkeyPosition == 1) { + _scene->_sequences.addTimer(1, 145); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + _counter = 0; + } + break; + + case 4: + if ((_monkeyPosition == 2) && (_counter < 2)) { + _scene->_sequences.addTimer(1, 151); + _scene->_hotspots.activate(227, true); + ++_counter; + _playingAnimFl = true; + } + break; + + case 5: + if (_monkeyPosition == 2) { + _scene->_sequences.addTimer(1, 161); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + case 6: + if (_monkeyPosition == 2) { + _scene->_sequences.addTimer(1, 189); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + case 7: + if (_monkeyPosition == 3) { + _scene->_hotspots.activate(227, true); + _scene->_sequences.addTimer(1, 167); + _playingAnimFl = true; + } + break; + + case 8: + if (_monkeyPosition == 3) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + _scene->_hotspots.activate(227, true); + _counter = 0; + } + break; + + case 9: + if ((_monkeyPosition == 3) && (_game._player._playerPos.x<120)) { + _scene->_sequences.addTimer(1, 182); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + case 10: + if (_monkeyPosition == 4) { + _scene->_sequences.addTimer(1, 196); + _scene->_hotspots.activate(227, true); + _playingAnimFl = true; + _counter = 0; + } + break; + + case 11: + if ((_monkeyPosition == 4) && (_counter < 3)) { + _scene->_sequences.addTimer(1, 199); + _scene->_hotspots.activate(227, true); + ++_counter; + _playingAnimFl = true; + } + break; + + case 30: + if (_monkeyPosition == 4) { + _scene->_sequences.addTimer(1, 246); + _scene->_hotspots.activate(227, true); + _counter = 0; + _playingAnimFl = true; + } + break; + + default: + if ((randAction >= 12) && (randAction <= 20) && (_monkeyPosition == 2) && (_counter < 5)) { + _scene->_sequences.addTimer(1, 155); + ++_counter; + _playingAnimFl = true; + } + + if ((randAction >= 21) && (randAction <= 29) && (_monkeyPosition == 3) && (_counter < 3)) { + _scene->_sequences.addTimer(1, 171); + _playingAnimFl = true; + ++_counter; + } + break; + } + } + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1)) + _scene->_sequences.addTimer(1, 226); + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 2)) + handlePause(); + + if (!_dodgeFl && !_pitchFl && !_fallFl && (_pauseMode == 1)) + initPauseCounterThreshold(); + + handlePeek(); + handleVerticalMove(); + handleLookStay(); + handleLookRight(); + handleBlink(); + handleGetBinoculars(); + handleStandFromPeek(); + handleDodge(); + handleBinocularBlink(); + handleBinocularScan(); + handleJumpInTree(); + handleTongue(); + handleMonkeyFall(); + handleJumpAndHide(); + handleMonkeyEating(); + handleMonkey1(); + handleStandBlink(); + handleMonkey2(); + + if ((_monkeyPosition == 1) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 161); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _fallFl) { + _scene->_sequences.addTimer(1, 196); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _fallFl && _forceFallFl) { + _scene->_sequences.addTimer(1, 219); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 1) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 189); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 212); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _pitchFl) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 1) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 145); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 4) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 196); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 3) && !_playingAnimFl && _dodgeFl) { + _scene->_sequences.addTimer(1, 178); + _playingAnimFl = true; + } + + if ((_monkeyPosition == 2) && !_playingAnimFl && _dodgeFl && _forceDodgeFl) { + _scene->_sequences.addTimer(1, 241); + _playingAnimFl = true; + } + + if (_dodgeFl || _fallFl) { /* if want to dodge or fall */ + if (!_playingAnimFl && (_monkeyPosition == 2)) + _shouldDodgeFl = true; + + if (!_playingAnimFl && (_monkeyPosition == 3)) + _shouldFallFl = true; + + switch (_game._trigger) { + case 228: + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 229); + break; + + case 229: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(35, 230); + } + break; + + case 230: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 231); + break; + + case 231: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, 10); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 232); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1); + _game._player._visible = false; + } + break; + + case 232: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(2, 233); + _scene->_kernelMessages.reset(); + if (_dodgeFl && (_monkeyPosition != 1) && (_monkeyPosition != 2)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138)); + if (_fallFl && (_monkeyPosition != 3)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 34463, _game.getQuote(138)); + } + break; + + case 233: + _shootReadyFl = true; + break; + + case 234: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_kernelMessages.reset(); + if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 7, 16, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 12, 239); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235); + } else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 11, 12); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 235); + _vm->_sound->command(23); + } + break; + + case 235: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 13); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(12, 236); + _forceFallFl = true; + _forceDodgeFl = true; + } + break; + + case 236: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 14, 16); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(116, 131)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 237); + break; + + case 237: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(1, 238); + break; + + case 238: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + if (_dodgeFl) + _game._player._stepEnabled = true; + + _startShootingInTimerFl = false; + + if (_fallFl) { + _globals[kMonkeyStatus] = MONKEY_IS_GONE; + _game._objects.setRoom(OBJ_POISON_DARTS, NOWHERE); + } + _dodgeFl = false; + _fallFl = false; + _forceFallFl = false; + _forceDodgeFl = false; + _shouldFallFl = false; + _shouldDodgeFl = false; + break; + + case 239: + _vm->_sound->command(23); + break; + } + } + + if (_game._trigger == 100) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(134)); + + if (_shootReadyFl && (_shouldFallFl || _shouldDodgeFl)) { + _scene->_sequences.addTimer(4, 234); + _shootReadyFl = false; + } +} + +void Scene209::preActions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_FIELD_TO_WEST)) + _game._player._walkOffScreenSceneId = 208; + + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY) + && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) { + _game._player._prepareWalkPos = Common::Point(111, 129); + _game._player._prepareWalkFacing = FACING_NORTHEAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_action.isAction(VERB_LOOK, NOUN_MONKEY) || _action.isAction(VERB_TALKTO, NOUN_MONKEY)) { + _game._player._prepareWalkPos = Common::Point(111, 129); + _game._player._prepareWalkFacing = FACING_NORTHEAST; + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + } +} + +void Scene209::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(20912); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ROCKY_AREA_TO_NORTH)) { + _scene->_nextSceneId = 203; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TALKTO, NOUN_MONKEY) && !_pitchFl && !_playingDialogFl) { + _scene->_sequences.addTimer(1, _dialogAbortVal); + _playingDialogFl = true; + _game._player._stepEnabled = false; + _action._inProgress = false; + return; + } + + switch (_game._trigger) { + case 130: + _game._player._stepEnabled = true; + _playingDialogFl = false; + _action._inProgress = false; + return; + + case 5: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 180, _game.getQuote(139)); + _action._inProgress = false; + return; + + case 6: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 7; + _action._inProgress = false; + return; + + case 7: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 8, 180, _game.getQuote(140)); + _action._inProgress = false; + return; + + case 8: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(149)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 9; + _action._inProgress = false; + return; + + case 9: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(141)); + _scene->_sequences.addTimer(200, 10); + _action._inProgress = false; + return; + + case 10: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 11, 180, _game.getQuote(142)); + _action._inProgress = false; + return; + + case 11: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(152)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 12; + _action._inProgress = false; + return; + + case 12: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 130, _game.getQuote(143)); + _scene->_sequences.addTimer(150, 13); + _action._inProgress = false; + return; + + case 13: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 14, 180, _game.getQuote(145)); + _action._inProgress = false; + return; + + case 14: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 0, 60, _game.getQuote(151)); + _scene->_sequences.addTimer(60, 130); + _dialogAbortVal = 15; + _action._inProgress = false; + return; + + case 15: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 16, 180, _game.getQuote(146)); + _action._inProgress = false; + return; + + case 16: + _scene->_kernelMessages.add(Common::Point(180, 21), 0xFDFC, 0, 17, 60, _game.getQuote(154)); + _action._inProgress = false; + return; + + case 17: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 130, 60, _game.getQuote(147)); + _dialogAbortVal = 18; + _action._inProgress = false; + return; + + case 18: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(148)); + _pitchFl = true; + _playingDialogFl = false; + _dialogAbortVal = 5; + _action._inProgress = false; + return; + } + + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if ((_action.isAction(VERB_SHOOT) || _action.isAction(VERB_HOSE_DOWN)) && _action.isTarget(NOUN_MONKEY) + && _action.isObject(NOUN_BLOWGUN) && _game._objects.isInInventory(OBJ_BLOWGUN) && _game._objects.isInInventory(OBJ_POISON_DARTS)) { + if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 231); + _startShootingInTimerFl = true; + _game._player._stepEnabled = false; + _dodgeFl = true; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_MONKEY) && !_startShootingInTimerFl) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 228); + _game._player._stepEnabled = false; + _fallFl = true; + _startShootingInTimerFl = true; + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_MONKEY)) { + _pitchFl = true; + _game._player._stepEnabled = false; + _vm->_dialogs->show(20914); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_TAKE, NOUN_PLANT_STALK) && (_game._trigger || _game._objects.isInRoom(OBJ_PLANT_STALK))) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[11] = _scene->_sprites.addSprites("*RXMBD_2"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[11] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[11], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[11]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_PLANT_STALK); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.addTimer(4, 3); + _vm->_dialogs->showItem(OBJ_PLANT_STALK, 0x328); + break; + + case 3: + _scene->_sprites.remove(_globals._spriteIndexes[11]); + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_BINOCULARS) && (_game._trigger || _game._objects.isInRoom(OBJ_BINOCULARS))) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[10] = _scene->_sprites.addSprites("*RXMBD_8"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 3, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[10]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _game._objects.addToInventory(OBJ_BINOCULARS); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _binocularsDroppedFl = false; + _scene->_sequences.addTimer(4, 3); + break; + + case 3: + _vm->_dialogs->showItem (OBJ_BINOCULARS, 0x51AF); + _scene->_sprites.remove(_globals._spriteIndexes[10]); + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_SKY)) { + _vm->_dialogs->show(20901); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_BAMBOO_LIKE_PLANT)) { + _vm->_dialogs->show(20902); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINSIDE)) { + _vm->_dialogs->show(20903); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_GRASSY_FIELD)) { + _vm->_dialogs->show(20904); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_WEST)) { + _vm->_dialogs->show(20905); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_ROCKY_AREA_TO_NORTH)) { + _vm->_dialogs->show(20906); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PLANT_STALK) && (_action._savedFields._mainObjectSource == 4)) { + _vm->_dialogs->show(20907); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_MONKEY) || _action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_MONKEY)) { + _vm->_dialogs->show(20909); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TREES)) { + _vm->_dialogs->show(20913); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_THROW, NOUN_MONKEY) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + if (!_action.isObject(NOUN_POISON_DARTS)) { + _vm->_dialogs->show(20915); + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_THROW, NOUN_POISON_DARTS, NOUN_MONKEY)) { + _vm->_dialogs->show(20916); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + if (_globals[kMonkeyStatus] == MONKEY_HAS_BINOCULARS) { + if (_monkeyPosition == 1) + _vm->_dialogs->show(20917); + else + _vm->_dialogs->show(20918); + } else { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + _vm->_dialogs->show(20917); + else + _vm->_dialogs->show(20919); + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_MELON_MUSH)) { + _vm->_dialogs->show(20920); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_MELON_MUSH)) { + _vm->_dialogs->show(20921); + _action._inProgress = false; + return; + } +} + +/*****************************************************************************/ + +Scene210::Scene210(MADSEngine *vm) : Scene2xx(vm) { + _curDialogNode = -1; + _nextHandsPlace = 0; + _twinkleAnimationType = 0; + _twinklesCurrentFrame = 0; + _shouldTalk = false; + _shouldFaceRex = false; + _shouldMoveHead = false; + _stopWalking = false; + _twinklesTalking = false; + _twinklesTalk2 = false; + _doorway = 0; + _subQuote2 = ""; +} + +void Scene210::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsSint32LE(_curDialogNode); + s.syncAsSint32LE(_nextHandsPlace); + s.syncAsSint32LE(_twinkleAnimationType); + s.syncAsSint32LE(_twinklesCurrentFrame); + + s.syncAsByte(_shouldTalk); + s.syncAsByte(_shouldFaceRex); + s.syncAsByte(_shouldMoveHead); + s.syncAsByte(_stopWalking); + s.syncAsByte(_twinklesTalking); + s.syncAsByte(_twinklesTalk2); + + s.syncAsSint32LE(_doorway); + + s.syncString(_subQuote2); +} + +void Scene210::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DOORWAY); + _scene->addActiveVocab(VERB_WALK_THROUGH); +} + +void Scene210::handleConversations() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_scene->_kernelMessages._talkFont->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1); + _scene->_sequences.addTimer(60, 50); + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); + } + } else if (_game._trigger == 50) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 240, _subQuote2); + _scene->_sequences.addTimer(180, 1); + } else { + if (_game._trigger == 1) + _scene->_kernelMessages.reset(); + + switch (_curDialogNode) { + case 1: + handleConversation1(); + break; + + case 2: + handleConversation2(); + break; + + case 3: + handleConversation3(); + break; + + case 5: + handleConversation5(); + break; + + case 6: + handleConversation6(); + break; + + case 7: + handleConversation7(); + break; + + case 8: + handleConversation8(); + break; + } + } +} + +void Scene210::handleConversation1() { + switch (_action._activeAction._verbId) { + case 180: + setDialogNode(2); + break; + + case 181: + setDialogNode(6); + break; + + case 182: + setDialogNode(4); + break; + + case 183: + setDialogNode(9); + break; + + case 184: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation2() { + switch (_action._activeAction._verbId) { + case 187: + setDialogNode(3); + break; + + case 188: + setDialogNode(4); + break; + + case 189: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation3() { + switch (_action._activeAction._verbId) { + case 193: + setDialogNode(6); + break; + + case 194: + setDialogNode(5); + break; + + case 195: + setDialogNode(4); + break; + + case 196: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation5() { + switch (_action._activeAction._verbId) { + case 204: + setDialogNode(6); + break; + + case 205: + case 206: + setDialogNode(4); + break; + + case 207: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation6() { + switch (_action._activeAction._verbId) { + case 211: + setDialogNode(7); + break; + + case 212: + setDialogNode(4); + break; + + case 213: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation7() { + switch (_action._activeAction._verbId) { + case 216: + case 217: + case 219: + setDialogNode(4); + break; + + case 218: + setDialogNode(8); + break; + + case 220: + setDialogNode(0); + break; + } +} + +void Scene210::handleConversation8() { + switch (_action._activeAction._verbId) { + case 223: + case 224: + setDialogNode(4); + break; + + case 225: + case 226: + setDialogNode(9); + break; + + case 227: + setDialogNode(0); + break; + } +} + +void Scene210::setDialogNode(int node) { + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _shouldFaceRex = false; + _shouldTalk = false; + _game._player._stepEnabled = true; + _curDialogNode = 0; + break; + + case 2: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xB9, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + _nextHandsPlace = 0; + handleTwinklesSpeech(186, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _nextHandsPlace = 0; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(2); + break; + } + break; + + case 3: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 0; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xBE, -2, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + case 2: + _nextHandsPlace = 2; + handleTwinklesSpeech(191, -1, 0); + _scene->_sequences.addTimer(180, 3); + break; + case 3: + _nextHandsPlace = 0; + handleTwinklesSpeech(192, 0, 0); + _scene->_sequences.addTimer(180, 4); + break; + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(3); + break; + } + break; + + case 4: + if (_game._trigger == 1) { + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + + int quote; + if (_game._storyMode == STORYMODE_NAUGHTY) + quote = _vm->getRandomNumber(199, 201); + else + quote = _vm->getRandomNumber(197, 198); + + if (_twinklesTalking) { + handleTwinklesSpeech(quote, 0, 360); + _scene->_sequences.addTimer(120, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + } else { + _scene->_userInterface.setup(kInputBuildingSentences); + _shouldFaceRex = false; + _shouldTalk = false; + _game._player._stepEnabled = true; + } + break; + + case 5: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xCA, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + _nextHandsPlace = 1; + handleTwinklesSpeech(0xCB, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _nextHandsPlace = 2; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(5); + break; + } + break; + + case 6: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 1; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xD0, -2, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xD1, -1, 0); + _scene->_sequences.addTimer(180, 3); + break; + + case 3: + _nextHandsPlace = 1; + handleTwinklesSpeech(0xD2, 0, 0); + _scene->_sequences.addTimer(180, 4); + break; + + default: + _nextHandsPlace = 0; + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(6); + break; + } + break; + + case 7: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xD6, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xD7, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(7); + break; + } + break; + + case 8: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 2; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + handleTwinklesSpeech(0xDD, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xDE, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + default: + _shouldTalk = false; + _game._player._stepEnabled = true; + newNode(8); + break; + } + break; + + + case 9: + switch (_game._trigger) { + case 1: + _nextHandsPlace = 0; + _shouldTalk = true; + _game._player._stepEnabled = false; + if (_twinklesTalking) { + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + handleTwinklesSpeech(0xE4, -1, 0); + _scene->_sequences.addTimer(180, 2); + } else { + _scene->_sequences.addTimer(6, 1); + } + break; + + case 2: + handleTwinklesSpeech(0xE5, 0, 0); + _scene->_sequences.addTimer(180, 3); + break; + + case 3: + _twinkleAnimationType = 2; + _globals[kCurtainOpen] = true; + _game._player._visible = false; + _vm->_palette->lock(); + _scene->_kernelMessages.reset(); + _scene->freeAnimation(); + _scene->_activeAnimation = nullptr; + _scene->resetScene(); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _game.loadQuoteSet(0xE6, 0xE9, 0xEA, 0xE7, 0xE8, 0); + _scene->loadAnimation(formAnimName('B', -1), 4); + break; + + case 4: { + _globals._spriteIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._spriteIndexes[8], 1); + + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 20), 0x1110, 32, 5, 180, _game.getQuote(231)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 5: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 40), 0xFDFC, 32, 6, 180, _game.getQuote(233)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 6: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 60), 0x1110, 32, 7, 180, _game.getQuote(232)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 7: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(160, 80), 0xFDFC, 32, 8, 180, _game.getQuote(234)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 8: + _globals[kTwinklesStatus] = TWINKLES_GONE; + _scene->_nextSceneId = 216; + break; + } + break; + } +} + +void Scene210::handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay) { + _scene->_kernelMessages.add(Common::Point(10, 70 + (shiftX * 14)), 0xFDFC, 0, 0, (delay == 0) ? 9999999 : delay, _game.getQuote(quoteId)); +} + +void Scene210::newNode(int node) { + _curDialogNode = node; + + switch (_curDialogNode) { + case 1: + _conv1.start(); + break; + + case 2: + _conv2.start(); + break; + + case 3: + _conv3.start(); + break; + + case 5: + _conv5.start(); + break; + + case 6: + _conv6.start(); + break; + + case 7: + _conv7.start(); + break; + + case 8: + _conv8.start(); + break; + + default: + break; + } +} + +void Scene210::restoreDialogNode(int node, int msgId, int posY) { + int curQuoteId = msgId; + int curY = 1 - posY; + for (int count = 0; count < posY; count++) { + handleTwinklesSpeech(curQuoteId, curY, 0); + curY++; + curQuoteId++; + } + + newNode(node); +} + +void Scene210::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kCurtainOpen] = 0; + + if (_scene->_priorSceneId == 205) + _game._player._playerPos = Common::Point(277, 56); + else if (_scene->_priorSceneId == 215) { + _game._player._playerPos = Common::Point(168, 128); + _game._player._facing = FACING_SOUTH; + _globals[kCurtainOpen] = true; + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(308, 132); + + if (!_globals[kCurtainOpen]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + } else { + int idx = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36)); + _doorway = _scene->_dynamicHotspots.setPosition(idx, Common::Point(168, 127), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP); + } + + _game.loadQuoteSet(0x5A, 0x73, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB8, 0xB7, + 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, + 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, + 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0); + + _conv1.setup(0x2E, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _conv1.set(0x2E, 0xB4, 0xB5, 0xB6, 0xB8, 0); + + if (_game._widepipeCtr >= 2) + _conv1.write(0xB7, true); + } + + bool sceneRevisited = _game._visitedScenes._sceneRevisited; + _conv2.setup(0x2F, 0xBC, 0xBB, 0xBD, sceneRevisited ? 0 : -1); + _conv3.setup(0x30, 0xC3, 0xC2, 0xC1, 0xC4, sceneRevisited ? 0 : -1); + _conv5.setup(0x31, 0xCD, 0xCC, 0xCE, 0xCF, sceneRevisited ? 0 : -1); + _conv6.setup(0x32, 0xD3, 0xD4, 0xD5, sceneRevisited ? 0 : -1); + _conv7.setup(0x33, 0xD8, 0xDA, 0xD9, 0xDB, 0xDC, sceneRevisited ? 0 : -1); + _conv8.setup(0x34, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, sceneRevisited ? 0 : -1); + + _twinkleAnimationType = 0; + _twinklesCurrentFrame = 0; + + if (_scene->_priorSceneId != -2) { + _shouldMoveHead = false; + _shouldFaceRex = false; + _shouldTalk = false; + _nextHandsPlace = 0; + _twinklesTalking = false; + _curDialogNode = 0; + _stopWalking = false; + _twinklesTalk2 = (_globals[kTwinklesApproached] > 0); + } + + if (_globals[kTwinklesStatus] == 0) { + _scene->loadAnimation(formAnimName('A', -1)); + _twinkleAnimationType = 1; + } else + _scene->_hotspots.activate(476, false); + + if (_curDialogNode) { + int quote = 0; + int number = 0; + + switch (_curDialogNode) { + case 1: + quote = 0xB3; + number = 1; + break; + case 2: + quote = 0xB9; + number = 2; + break; + case 3: + quote = 0xBE; + number = 3; + break; + case 5: + quote = 0xCA; + number = 2; + break; + case 6: + quote = 0xD0; + number = 3; + break; + case 7: + quote = 0xD6; + number = 2; + break; + case 8: + quote = 0xDD; + number = 2; + break; + } + + restoreDialogNode(_curDialogNode, quote, number); + if (_scene->_activeAnimation) + _scene->_activeAnimation->setCurrentFrame(131); + } + + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 5); + + sceneEntrySound(); +} + +void Scene210::step() { + if ((_twinkleAnimationType == 1) && _scene->_activeAnimation) { + if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) { + _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int reset_frame = -1; + int random = _vm->getRandomNumber(1, 1000); + + switch (_twinklesCurrentFrame) { + case 31: + case 58: + case 74: + case 108: + case 190: + if (_shouldFaceRex) + reset_frame = 108; + else if ((random <= 100) || _shouldMoveHead) + reset_frame = 74; + else if (random <= 300) + reset_frame = 58; + else if (random <= 500) + reset_frame = 31; + else + reset_frame = 0; + break; + + case 80: + case 90: + _twinklesTalking = false; + if (_shouldMoveHead) { + reset_frame = 90; + } else if (_twinklesCurrentFrame == 90) { + if ((random <= 400) || _shouldFaceRex) + reset_frame = 99; + else + reset_frame = 79; + } + break; + + case 98: + if (_shouldMoveHead) + reset_frame = 91; + break; + + case 99: + if ((random <= 400) && !_shouldFaceRex) + reset_frame = 79; + break; + + case 124: + case 136: + case 174: + case 143: + case 152: + if (_nextHandsPlace == 3) + reset_frame = 174; + else if (!_shouldFaceRex) + reset_frame = 174; + else if (_nextHandsPlace == 1) + reset_frame = 136; + else if (_nextHandsPlace == 2) + reset_frame = 152; + else if (_shouldTalk) + reset_frame = 124; + else + reset_frame = (random <= 200) ? 131 : 143; + break; + + case 131: + if (_shouldTalk) { + switch (_nextHandsPlace) { + case 1: + reset_frame = 136; + break; + case 2: + reset_frame = 152; + break; + default: + reset_frame = 124; + break; + } + } + break; + + case 138: + case 141: + if ((_nextHandsPlace == 0) || !_shouldFaceRex) + reset_frame = 141; + else if (_nextHandsPlace == 2) + reset_frame = 152; + else if (!_shouldTalk || (_twinklesCurrentFrame == 141)) + reset_frame = 137; + break; + + case 153: + case 169: + if ((_nextHandsPlace == 0) || !_shouldFaceRex) + reset_frame = 169; + else if (_nextHandsPlace == 1) + reset_frame = 136; + else if (_shouldTalk) + reset_frame = 153; + else + reset_frame = 162; + break; + + case 162: + if (_shouldTalk) { + switch (_nextHandsPlace) { + case 0: + reset_frame = 124; + break; + case 1: + reset_frame = 136; + break; + default: + reset_frame = 153; + break; + } + } + break; + } + + if (reset_frame >= 0) { + if (reset_frame != _scene->_activeAnimation->getCurrentFrame()) { + _scene->_activeAnimation->setCurrentFrame(reset_frame); + _twinklesCurrentFrame = reset_frame; + } + + if ((reset_frame == 90) || (reset_frame == 91) || (reset_frame == 124) || (reset_frame == 153) + || ((reset_frame == 137) && _shouldTalk)) { + _twinklesTalking = true; + } else { + _twinklesTalking = false; + } + } + } + } + + if ((_twinkleAnimationType == 2) && _scene->_activeAnimation) { + if (_twinklesCurrentFrame != _scene->_activeAnimation->getCurrentFrame()) { + _twinklesCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int reset_frame = -1; + + if (_twinklesCurrentFrame == 53) { + _scene->_kernelMessages.add(Common::Point(151, 61), 0xFDFC, 32, 70, 180, _game.getQuote(230)); + _shouldTalk = true; + } else if ((_twinklesCurrentFrame == 75) && _shouldTalk) + reset_frame = 60; + + if ((reset_frame >= 0) && (reset_frame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(reset_frame); + _twinklesCurrentFrame = reset_frame; + } + } + + if (_game._trigger == 70) + _shouldTalk = false; + } + + if ((_twinkleAnimationType == 1) && (_scene->_rails.getNext() > 0)) { + _game._player.walk(Common::Point(214, 150), FACING_NORTHWEST); + _scene->_rails.resetNext(); + _stopWalking = true; + } +} + +void Scene210::preActions() { + _stopWalking = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST)) + _game._player._walkOffScreenSceneId = 211; +} + +void Scene210::actions() { + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_HUT_TO_NORTH)) { + _vm->_dialogs->show(21017); + } else if (_game._screenObjects._inputMode == 1) { + handleConversations(); + } else if (_action.isAction(VERB_TALKTO, NOUN_NATIVE_WOMAN) || + ((_game._player._playerPos == Common::Point(214, 150)) && (_game._player._facing == FACING_NORTHWEST) && (_twinkleAnimationType == 1) && _stopWalking)) { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + int quote; + if (_globals[kTwinklesApproached] == 0) + quote = 90; + else if (_globals[kTwinklesApproached] == 1) + quote = 115; + else + quote = 171; + + _shouldFaceRex = true; + _nextHandsPlace = 0; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(quote, 1, 120); + } + break; + + case 1: + _shouldTalk = true; + if (!_twinklesTalking) { + _scene->_sequences.addTimer(6, 1); + } else { + if (_globals[kTwinklesApproached] == 0) { + handleTwinklesSpeech(0xAF, -1, 0); + handleTwinklesSpeech(0xB0, 0, 0); + } else if (_globals[kTwinklesApproached] == 1) { + handleTwinklesSpeech(0xB1, 0, 0); + } else { + int quote = _twinklesTalk2 ? 0xB3 : 0xB2; + _twinklesTalk2 = true; + handleTwinklesSpeech(quote, 0, 0); + } + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + _shouldMoveHead = false; + _shouldTalk = false; + + if (_globals[kTwinklesApproached] < 2) + _globals[kTwinklesApproached]++; + + _conv1.start(); + _curDialogNode = 1; + break; + } + } else if (_action.isAction(VERB_GIVE, NOUN_NATIVE_WOMAN) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + switch (_game._trigger) { + case 0: { + int quote = _vm->getRandomNumber(172, 174); + _shouldMoveHead = true; + _game._player._stepEnabled = false; + handleTwinklesSpeech(quote, 0, 120); + _scene->_sequences.addTimer(120, 1); + } + break; + + case 1: + _game._player._stepEnabled = true; + _shouldMoveHead = false; + break; + } + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTH) || _action.isAction(VERB_WALK_TOWARDS, NOUN_HUT_TO_NORTH)) { + _scene->_nextSceneId = 205; + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) { + _scene->_nextSceneId = 215; + } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_OPEN, NOUN_CURTAIN)) && !_globals[kCurtainOpen]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player._stepEnabled = true; + _globals[kCurtainOpen] = true; + _doorway = _scene->_dynamicHotspots.add(112, 395, -1, Common::Rect(163, 87, 163 + 19, 87 + 36)); + _scene->_dynamicHotspots.setPosition(_doorway, Common::Point(168, 127), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorway, CURSOR_GO_UP); + break; + } + } else if ((_action.isAction(VERB_PULL, NOUN_CURTAIN) || _action.isAction(VERB_CLOSE, NOUN_CURTAIN)) && _globals[kCurtainOpen]) { + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._player._stepEnabled = false; + _game._player._facing = FACING_NORTH; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 0, 0, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _game._player._stepEnabled = false; + break; + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addTimer(48, 2); + break; + case 2: + _scene->_dynamicHotspots.remove(_doorway); + _game._player._stepEnabled = true; + _globals[kCurtainOpen] = false; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_HUT)) { + if (_globals[kTwinklesStatus] == TWINKLES_GONE) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21003); + else + _vm->_dialogs->show(21002); + } else { + _vm->_dialogs->show(21001); + } + } else if (_action.isAction(VERB_LOOK, NOUN_BRA)) { + _vm->_dialogs->show(21004); + } else if (_action.isAction(VERB_LOOK, NOUN_HOTPANTS)) { + _vm->_dialogs->show(21005); + } else if (_action.isAction(VERB_TAKE, NOUN_HOTPANTS) || _action.isAction(VERB_TAKE, NOUN_BRA)) { + _vm->_dialogs->show(21006); + } else if (_action.isAction(VERB_LOOK, NOUN_STREAM)) { + _vm->_dialogs->show(21007); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN)) { + _vm->_dialogs->show(21008); + } else if (_action.isAction(VERB_LOOK, NOUN_VILLAGE_PATH)) { + _vm->_dialogs->show(21009); + } else if (_action.isAction(VERB_LOOK, NOUN_NATIVE_WOMAN)) { + _vm->_dialogs->show(21010); + } else if (_action.isAction(VERB_SHOOT, NOUN_NATIVE_WOMAN) || _action.isAction(VERB_HOSE_DOWN, NOUN_NATIVE_WOMAN)) { + _vm->_dialogs->show(21011); + } else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTH)) { + _vm->_dialogs->show(21012); + } else if (_action.isAction(VERB_LOOK, NOUN_CURTAIN)) { + _vm->_dialogs->show(21013); + } else if (_action.isAction(VERB_LOOK, NOUN_CLOTHESLINE)) { + _vm->_dialogs->show(21014); + } else if (_action.isAction(VERB_TAKE, NOUN_CLOTHESLINE)) { + _vm->_dialogs->show(21015); + } else if (_action.isAction(VERB_LOOK, NOUN_HUT_TO_NORTH)) { + _vm->_dialogs->show(21016); + } else { + // Not handled + return; + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene211::Scene211(MADSEngine *vm) : Scene2xx(vm) { + _ambushFl = false; + _wakeFl = false; + _monkeyFrame = 0; + _scrollY = 0; + _monkeyTime = 0; +} + +void Scene211::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsByte(_ambushFl); + s.syncAsByte(_wakeFl); + + s.syncAsSint32LE(_monkeyFrame); + s.syncAsSint32LE(_scrollY); + s.syncAsUint32LE(_monkeyTime); +} + +void Scene211::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_SLITHERING_SNAKE); +} + +void Scene211::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC002Z2"); + _wakeFl = false; + + if (_scene->_priorSceneId == 210) + _game._player._playerPos = Common::Point(25, 148); + else if (_scene->_priorSceneId == 205) { + _game._player._playerPos = Common::Point(49, 133); + _game._player._facing = FACING_WEST; + _wakeFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('A', -1), 100); + _scene->_activeAnimation->setCurrentFrame(169); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(310, 31); + _game._player._facing = FACING_SOUTHWEST; + } + + if (_vm->getRandomNumber(1, 8) == 1) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(202, 126)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _scene->_sequences.setMotion(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, -200, 0); + _scene->_dynamicHotspots.add(324, 13, _globals._sequenceIndexes[2], Common::Rect(1, 1, 1 + 41, 1 + 10)); + } + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BINOCULARS); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + _game.loadQuoteSet(0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 1, 0); + + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + _scene->_kernelMessages.initRandomMessages(2, + Common::Rect(0, 0, 54, 30), 13, 2, 0xFDFC, 60, + 151, 152, 153, 154, 0); + + _monkeyTime = _vm->_game->_scene._frameStartTime; + _scrollY = 30; + + _ambushFl = false; + _monkeyFrame = 0; + + sceneEntrySound(); +} + +void Scene211::step() { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) { + _scene->_kernelMessages.randomServer(); + + if (!_ambushFl && !_wakeFl && (_vm->_game->_scene._frameStartTime >= _monkeyTime)) { + int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1; + if (_scene->_kernelMessages.generateRandom(80, chanceMinor)) + _vm->_sound->command(18); + + _monkeyTime = _vm->_game->_scene._frameStartTime + 2; + } + + if ((_game._player._playerPos == Common::Point(52, 132)) && (_game._player._facing == FACING_WEST) && !_game._player._moving && + (_game._trigger || !_ambushFl)) { + switch (_game._trigger) { + case 0: + if (_game._objects.isInInventory(OBJ_BINOCULARS)) { + _ambushFl = true; + _monkeyFrame = 0; + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_kernelMessages.reset(); + _scene->loadAnimation(formAnimName('A', -1), 90); + _vm->_sound->command(19); + int count = (int)_game._objects._inventoryList.size(); + for (int idx = 0; idx < count; idx++) { + if ((_game._objects._inventoryList[idx] == OBJ_BINOCULARS) && (_scene->_userInterface._selectedInvIndex != idx)) + _scene->_userInterface.selectObject(idx); + } + } + break; + + case 90: + _vm->_sound->command(10); + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._playerPos = Common::Point(49, 133); + _ambushFl = false; + _globals[kMonkeyStatus] = MONKEY_HAS_BINOCULARS; + break; + } + } + } + + if (_ambushFl && (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame)) { + _monkeyFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_monkeyFrame) { + case 2: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(12, 4), 0xFDFC, 0, 0, 60, _game.getQuote(157)); + _scene->_kernelMessages.setQuoted(msgIndex, 2, true); + } + break; + + case 12: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(35, 20), 0xFDFC, 0, 0, 60, _game.getQuote(155)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + } + break; + + case 42: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(60, 45), 0xFDFC, 0, 0, 60, _game.getQuote(156)); + _scene->_kernelMessages.setQuoted(msgIndex, 6, true); + } + break; + + case 73: + _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 75, _game.getQuote(157)); + break; + + case 90: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(102, 95), 0xFDFC, 32, 0, 60, _game.getQuote(158)); + _scene->_kernelMessages.setQuoted(msgIndex, 6, true); + } + break; + + case 97: + _scene->_userInterface.selectObject(-1); + _game._objects.removeFromInventory(OBJ_BINOCULARS, 1); + break; + + case 177: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(161)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 181: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(162)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 188: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(163)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 200: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(164)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + } + } + + if (_wakeFl) { + if (_game._trigger == 100) { + _game._player._visible = true; + _game._player._stepEnabled = true; + _wakeFl = false; + } + + if (_scene->_activeAnimation->getCurrentFrame() > _monkeyFrame) { + _monkeyFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 177: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(165)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 181: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(166)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 188: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(167)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + + case 200: { + int msgIndex = _scene->_kernelMessages.add(Common::Point(63, _scrollY), 0x1110, 0, 0, 180, _game.getQuote(168)); + _scene->_kernelMessages.setQuoted(msgIndex, 4, true); + _scrollY += 14; + } + break; + } + } + } +} + +void Scene211::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_JUNGLE_PATH) && _game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) + && (_scene->_customDest.x <= 52) && (_scene->_customDest.y >= 132)) + _game._player.walk(Common::Point(52, 132), FACING_WEST); + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) { + if (_game._objects.isInInventory(OBJ_BINOCULARS) && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)) + _game._player.walk(Common::Point(52, 132), FACING_WEST); + else + _game._player._walkOffScreenSceneId = 210; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_NORTHEAST)) + _game._player._walkOffScreenSceneId = 207; +} + +void Scene211::actions() { + if (_action._lookFlag && (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY)) + _vm->_dialogs->show(21111); + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_PALM_TREE)) + _vm->_dialogs->show(21116); + else if (_action.isAction(VERB_LOOK, NOUN_BUSHY_FERN)) + _vm->_dialogs->show(21101); + else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE_PATH)) + _vm->_dialogs->show(21102); + else if (_action.isAction(VERB_LOOK, NOUN_PALM_TREE)) { + if (_globals[kMonkeyStatus] == MONKEY_AMBUSH_READY) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21103); + else + _vm->_dialogs->show(21104); + } else { + _vm->_dialogs->show(21105); + } + } else if (_action.isAction(VERB_LOOK, NOUN_THICK_UNDERGROWTH)) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(21106); + else + _vm->_dialogs->show(21107); + } else if (_action.isAction(VERB_LOOK, NOUN_JUNGLE)) + _vm->_dialogs->show(21108); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_NORTHEAST)) + _vm->_dialogs->show(21109); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_WEST)) + _vm->_dialogs->show(21110); + else if (_action.isAction(VERB_LOOK, NOUN_SLITHERING_SNAKE)) + _vm->_dialogs->show(21113); + else if (_action.isAction(VERB_TAKE, NOUN_SLITHERING_SNAKE)) + _vm->_dialogs->show(21114); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(21115); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene212::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BOUNCING_REPTILE); +} + +void Scene212::enter() { + // CHECKME: Some useless variables have been remove here + + if (_scene->_priorSceneId == 208) { + _game._player._playerPos = Common::Point(195, 85); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(67, 117); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); +} + +void Scene212::step() { +// CHECKME: Could we move the dino? +} + +void Scene212::preActions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_CAVE_ENTRANCE)) + _game._player._walkOffScreenSceneId = 111; +} + +void Scene212::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21209); + else if (_action.isAction(VERB_WALK_TOWARDS) && (_action.isObject(NOUN_FIELD_TO_NORTH) || _action.isObject(NOUN_MOUNTAINS))) + _scene->_nextSceneId = 208; + else if (_action.isAction(VERB_WALK_TOWARDS, NOUN_CAVE)) + _scene->_nextSceneId = 111; + else if (_action.isAction(VERB_LOOK, NOUN_GRASS)) + _vm->_dialogs->show(21201); + else if (_action.isAction(VERB_LOOK, NOUN_ROCKS)) + _vm->_dialogs->show(21202); + else if (_action.isAction(VERB_LOOK, NOUN_CAVE_ENTRANCE)) + _vm->_dialogs->show(21203); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(21204); + else if (_action.isAction(VERB_LOOK, NOUN_FIELD_TO_NORTH)) + _vm->_dialogs->show(21205); + else if (_action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(21206); + else if (_action.isAction(VERB_LOOK, NOUN_PLANTS)) + _vm->_dialogs->show(21207); + else if (_action.isAction(VERB_LOOK, NOUN_MOUNTAINS)) + _vm->_dialogs->show(21208); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene213::setup() { + _game._player._spritesPrefix = ""; + + // The original is calling Scene2xx::setAAName() + _game._aaName = Resources::formatAAName(2); +} + +void Scene213::enter() { + if (_globals[kMeteorologistWatch] != METEOROLOGIST_NORMAL) + _handSpriteId = _scene->_sprites.addSprites("*METHAND"); + else if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original is calling Scene2xx::sceneEntrySound() + if (_vm->_musicFlag) { + if (_globals[kMeteorologistWatch] == METEOROLOGIST_NORMAL) + _vm->_sound->command(1); + else + _vm->_sound->command(9); + } else { + _vm->_sound->command(2); + } +} + +void Scene213::step() { + teleporterStep(); +} + +void Scene213::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(21301); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) || _action.isAction (VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(21302); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(21303); + else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(21304); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(21305); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY) + || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY)) + _vm->_dialogs->show(21306); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene214::Scene214(MADSEngine *vm) : Scene2xx(vm) { + _devilTime = 0; + _devilRunningFl = false; +} + +void Scene214::synchronize(Common::Serializer &s) { + Scene2xx::synchronize(s); + + s.syncAsUint32LE(_devilTime); + s.syncAsByte(_devilRunningFl); +} + +void Scene214::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_CAPTIVE_CREATURE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene214::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_7"); + + _devilTime = _game._player._priorTimer; + _devilRunningFl = false; + + if (_game._objects.isInRoom(OBJ_POISON_DARTS)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(103, 86)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 11); + } else { + _scene->_hotspots.activate(NOUN_POISON_DARTS, false); + } + + if (_game._objects.isInRoom(OBJ_BLOWGUN)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(90, 87)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + } else { + _scene->_hotspots.activate(NOUN_BLOWGUN, false); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(191, 152); + + sceneEntrySound(); +} + +void Scene214::step() { + if ((_game._player._priorTimer - _devilTime > 800) && !_devilRunningFl) { + _devilRunningFl = true; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 6, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _scene->_dynamicHotspots.add(451, 13, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_devilRunningFl) { + switch (_game._trigger) { + case 71: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0); + _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + break; + + case 72: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.updateTimeout(oldIdx, _globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.add(451, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 9, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _devilTime = _game._player._priorTimer; + _devilRunningFl = false; + } + break; + } + } +} + +void Scene214::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21427); + else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT)) + _scene->_nextSceneId = 207; + else if (_action.isAction(VERB_TAKE, NOUN_POISON_DARTS) && (_game._trigger || _game._objects.isInRoom(OBJ_POISON_DARTS))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], true, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_POISON_DARTS); + _scene->_hotspots.activate(NOUN_POISON_DARTS, false); + break; + + case 2: + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_POISON_DARTS, 0x53A5); + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_BLOWGUN) && (_game._trigger || _game._objects.isInRoom(OBJ_BLOWGUN))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_BLOWGUN); + _scene->_hotspots.activate(NOUN_BLOWGUN, false); + break; + + case 2: + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_BLOWGUN, 0x329); + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(21401); + else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT_CAGE)) + _vm->_dialogs->show(21402); + else if (_action.isAction(VERB_LOOK, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21403); + else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21404); + else if (_action.isAction(VERB_LOOK, NOUN_TROPHY)) + _vm->_dialogs->show(21405); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BOWL)) { + if (_game._storyMode == STORYMODE_NAUGHTY) { + _vm->_dialogs->show(21406); + } else { + _vm->_dialogs->show(21407); + } + } else if (_action.isAction(VERB_LOOK, NOUN_SPECIMEN_JARS)) + _vm->_dialogs->show(21408); + else if (_action.isAction(VERB_TAKE, NOUN_LARGE_BOWL) || _action.isAction(VERB_TAKE, NOUN_SPECIMEN_JARS)) + _vm->_dialogs->show(21409); + else if (_action.isAction(VERB_LOOK, NOUN_SHRUNKEN_HEADS)) + _vm->_dialogs->show(21410); + else if (_action.isAction(VERB_TAKE, NOUN_SHRUNKEN_HEADS) || _action.isAction(VERB_TAKE, NOUN_LARGE_HEADS)) + _vm->_dialogs->show(21411); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_HEADS)) + _vm->_dialogs->show(21428); + else if (_action.isAction(VERB_LOOK, NOUN_POISON_DARTS) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(21412); + else if (_action.isAction(VERB_OPEN, NOUN_EXPERIMENT_CAGE)) + _vm->_dialogs->show(21414); + else if (_action.isAction(VERB_TALKTO, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21415); + else if (_action.isAction(VERB_GIVE, NOUN_TWINKIFRUIT, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21416); + else if (_action.isAction(VERB_SHOOT, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE) || _action.isAction(VERB_HOSE_DOWN, NOUN_BLOWGUN, NOUN_CAPTIVE_CREATURE)) + _vm->_dialogs->show(21417); + else if (_action.isAction(VERB_LOOK, NOUN_BIG_HEADS)) + _vm->_dialogs->show(21418); + else if (_action.isAction(VERB_TAKE, NOUN_BIG_HEADS)) + _vm->_dialogs->show(21419); + else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21420); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR_OF_HUT)) + _vm->_dialogs->show(21421); + else if (_action.isAction(VERB_LOOK, NOUN_BLOWGUN)) + _vm->_dialogs->show(21422); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) { + if (_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21423); + } else if (_game._objects.isInRoom(OBJ_POISON_DARTS) && !_game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21424); + } else if (!_game._objects.isInRoom(OBJ_POISON_DARTS) && _game._objects.isInRoom(OBJ_BLOWGUN)) { + _vm->_dialogs->show(21425); + } else { + _vm->_dialogs->show(21426); + } + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene215::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene215::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle (_globals._spriteIndexes[1], false, 7, 0, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(235, 83)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + else + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_9"); + + if (_scene->_priorSceneId == 216) { + _game._player._playerPos = Common::Point(140, 119); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.addTimer(120, 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(204, 152); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0xA9, 0xAA, 0); + sceneEntrySound(); +} + +void Scene215::step() { + if (_game._trigger == 70) { + _scene->_sequences.remove (_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + + if (_game._trigger == 71) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _game._player._stepEnabled = true; + } +} + +void Scene215::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(21509); + else if (_action.isAction(VERB_TAKE, NOUN_TWINKIFRUIT)) { + if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT) || _game._trigger) { + switch (_game._trigger) { + case 0: + if (_globals[kSexOfRex] == REX_MALE) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404); + } + break; + + case 1: + if (!_game._objects.isInInventory(OBJ_TWINKIFRUIT)) { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _vm->_dialogs->showItem(OBJ_TWINKIFRUIT, 0x5404); + } + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + break; + } + } else { + int idx = _vm->getRandomNumber(169, 170); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(idx)); + } + } else if (_action.isAction(VERB_WALK_OUTSIDE, NOUN_HUT)) + _scene->_nextSceneId = 210; + else if (_action.isAction(VERB_LOOK, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21501); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(21502); + else if (_action.isAction(VERB_LOOK, NOUN_WELCOME_MAT)) + _vm->_dialogs->show(21503); + else if (_action.isAction(VERB_LOOK, NOUN_LOVE_ALTAR)) + _vm->_dialogs->show(21504); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(21505); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(21506); + else if (_action.isAction(VERB_LOOK, NOUN_TWINKIFRUIT) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(21507); + else if (_action.isAction(VERB_TAKE, NOUN_BEAR_RUG)) + _vm->_dialogs->show(21510); + else if (_action.isAction(VERB_TAKE, NOUN_LOVE_ALTAR)) + _vm->_dialogs->show(21511); + else if (_action.isAction(VERB_LOOK, NOUN_BAG_OF_TWINKIFRUITS)) + _vm->_dialogs->show(21512); + else if (_action.isAction(VERB_TAKE, NOUN_BAG_OF_TWINKIFRUITS)) + _vm->_dialogs->show(21513); + else if (_action.isAction(VERB_TAKE, NOUN_WELCOME_MAT)) + _vm->_dialogs->show(21514); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene216::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene216::enter() { + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + _scene->loadAnimation(formAnimName('A', -1), 60); + + sceneEntrySound(); +} + +void Scene216::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 215; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes2.h b/engines/mads/nebular/nebular_scenes2.h new file mode 100644 index 0000000000..c860db9470 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes2.h @@ -0,0 +1,325 @@ +/* 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 MADS_NEBULAR_SCENES2_H +#define MADS_NEBULAR_SCENES2_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene2xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); +public: + Scene2xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene201 : public Scene2xx { +private: + bool _pterodactylFlag; + +public: + Scene201(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene202 : public Scene2xx { +private: + bool _activeMsgFl, _ladderTopFl, _waitingMeteoFl, _toStationFl, _toTeleportFl; + int _ladderHotspotId, _lastRoute, _stationCounter, _meteoFrame; + uint32 _meteoClock1, _meteoClock2, _startTime; + bool _meteorologistSpecial; + + int subStep1(int randVal); + int subStep2(int randVal); + int subStep3(int randVal); + int subStep4(int randVal); + +public: + Scene202(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); + + void setRandomKernelMessage(); +}; + +class Scene203 : public Scene2xx { +private: + bool _rhotundaEat2Fl, _rhotundaEatFl; + +public: + Scene203(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene205 : public Scene2xx { +private: + uint32 _lastFishTime, _chickenTime; + bool _beingKicked; + int _kernelMessage; + Conversation _dialog1; + + void handleWomanSpeech(int quoteId); + +public: + Scene205(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene207 : public Scene2xx { +private: + bool _vultureFl, _spiderFl, _eyeFl; + int _spiderHotspotId, _vultureHotspotId; + int32 _spiderTime, _vultureTime; + + void moveVulture(); + void moveSpider(); + +public: + Scene207(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene208 : public Scene2xx { +private: + bool _rhotundaTurnFl, _boundingFl; + int32 _rhotundaTime; + + void updateTrap(); + void subAction(int mode); + +public: + Scene208(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene209 : public Scene2xx { +private: + bool _dodgeFl, _forceDodgeFl, _shouldDodgeFl; + bool _pitchFl; + bool _fallFl, _forceFallFl, _shouldFallFl; + bool _playingAnimFl, _playingDialogFl; + int _pauseMode, _pauseCounterThreshold, _pauseCounter; + bool _removeMonkeyFl; + int _monkeyPosition; + bool _shootReadyFl, _startShootingInTimerFl, _shootMissedLastFl; + bool _binocularsDroppedFl; + int _dialogAbortVal; + int _counter; + + void handlePause(); + void initPauseCounterThreshold(); + void handlePeek(); + void handleVerticalMove(); + void handleLookStay(); + void handleLookRight(); + void handleBlink(); + void handleGetBinoculars(); + void handleStandFromPeek(); + void handleDodge(); + void handleBinocularBlink(); + void handleBinocularScan(); + void handleJumpInTree(); + void handleTongue(); + void handleMonkeyFall(); + void handleJumpAndHide(); + void handleMonkeyEating(); + void handleMonkey1(); + void handleStandBlink(); + void handleMonkey2(); + +public: + Scene209(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene210 : public Scene2xx { +private: + int _curDialogNode; + int _nextHandsPlace; + int _twinkleAnimationType; + int _twinklesCurrentFrame; + bool _shouldTalk, _shouldFaceRex, _shouldMoveHead; + bool _stopWalking; + bool _twinklesTalking; + bool _twinklesTalk2; + int _doorway; + Common::String _subQuote2; + Conversation _conv1, _conv2, _conv3; + Conversation _conv5, _conv6, _conv7, _conv8; + + void handleConversations(); + void handleConversation1(); + void handleConversation2(); + void handleConversation3(); + void handleConversation5(); + void handleConversation6(); + void handleConversation7(); + void handleConversation8(); + void setDialogNode(int node); + void handleTwinklesSpeech(int quoteId, int shiftX, uint32 delay); + void newNode(int node); + void restoreDialogNode(int node, int msgId, int posY); + +public: + Scene210(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene211 : public Scene2xx { +private: + bool _ambushFl, _wakeFl; + int _monkeyFrame, _scrollY; + uint32 _monkeyTime; + +public: + Scene211(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene212 : public Scene2xx { +public: + Scene212(MADSEngine *vm) : Scene2xx(vm) {} + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene213 : public SceneTeleporter { +public: + Scene213(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene214 : public Scene2xx { +private: + uint32 _devilTime; + bool _devilRunningFl; + +public: + Scene214(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene215 : public Scene2xx { +public: + Scene215(MADSEngine *vm) : Scene2xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene216 : public Scene2xx { +public: + Scene216(MADSEngine *vm) : Scene2xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES2_H */ diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp new file mode 100644 index 0000000000..a963484bd0 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes3.cpp @@ -0,0 +1,5818 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes3.h" + +namespace MADS { + +namespace Nebular { + +void Scene3xx::setAAName() { + _game._aaName = Resources::formatAAName(4); +} + +void Scene3xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + if ((_scene->_nextSceneId == 313) || (_scene->_nextSceneId == 366) + || ((_scene->_nextSceneId >= 301) && (_scene->_nextSceneId <= 303)) + || ((_scene->_nextSceneId == 304) && (_scene->_currentSceneId == 303)) + || ((_scene->_nextSceneId == 311) && (_scene->_currentSceneId == 304)) + || ((_scene->_nextSceneId >= 308) && (_scene->_nextSceneId <= 310)) + || ((_scene->_nextSceneId >= 319) && (_scene->_nextSceneId <= 322)) + || ((_scene->_nextSceneId >= 387) && (_scene->_nextSceneId <= 391))) { + _game._player._spritesPrefix = ""; + _game._player._spritesChanged = true; + } + + _game._player._scalingVelocity = true; + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene3xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 301: + case 302: + case 303: + case 304: + case 308: + case 309: + case 310: + _vm->_sound->command(11); + break; + + case 311: + if (_scene->_priorSceneId == 304) + _vm->_sound->command(11); + else + _vm->_sound->command(10); + break; + + case 313: + case 316: + case 320: + case 322: + case 357: + case 358: + case 359: + case 360: + case 361: + case 387: + case 388: + case 389: + case 390: + case 391: + case 399: + _vm->_sound->command(10); + break; + + case 318: + if ((_scene->_priorSceneId == 357) || (_scene->_priorSceneId == 407)) + _vm->_sound->command(10); + else if (_scene->_priorSceneId == 319) + _vm->_sound->command(16); + else + _vm->_sound->command(3); + + _vm->_sound->command(50); + break; + + case 319: + _vm->_sound->command(16); + break; + + case 321: + _vm->_sound->command(18); + break; + + default: + break; + } +} + +void Scene3xx::initForceField(ForceField *force, bool flag) { + force->_flag = flag; + force->_vertical = 0; + force->_horizontal = 0; + force->_timer = 0; + + for (int count = 0; count < 40; count++) + force->_seqId[count] = -1; + + if (force->_flag) + _vm->_sound->command(24); +} + +int Scene3xx::computeScale(int low, int high, int id) { + int diff = high - (low + 2); + int quotient = diff / 20; + int remainder = diff % 20; + int value = low + 2 + (quotient * id) + (remainder / (id + 1)); + + return (value); +} + +void Scene3xx::handleForceField(ForceField *force, int *sprites) { + if (_game._trigger >= 150) { + int id = _game._trigger - 150; + if (id < 40) { + if (id < 20) + force->_vertical--; + else + force->_horizontal--; + + force->_seqId[id] = -1; + } + return; + } + + if (!force->_flag || (_scene->_frameStartTime < force->_timer) || (force->_vertical + force->_horizontal >= 5)) + return; + + if (_vm->getRandomNumber(1, 1000) <= (200 + ((40 - (force->_vertical + force->_horizontal)) << 5))) { + int id = -1; + for (int i = 0; i < 100; i++) { + int randIdx = _vm->getRandomNumber(0, 39); + if (force->_seqId[randIdx] < 0) { + id = randIdx; + break; + } + } + + if (id < 0) { + for (int i = 0; i < 40; i++) { + if (force->_seqId[i] < 0) { + id = i; + break; + } + } + } + + int speedX, speedY; + int posX, posY; + int randVal = _vm->getRandomNumber(1, 100); + int spriteId; + bool mirror; + + if (id >= 20) { + spriteId = 2; + mirror = (randVal <= 50); + posX = mirror ? 315 : 5; + posY = computeScale(15, 119, id - 20); + speedX = 1000 * (mirror ? -1 : 1); + speedY = 0; + } else if (randVal <= 50) { + spriteId = 1; + mirror = false; + posX = computeScale(21, 258, id); + posY = 0; + speedX = 0; + speedY = 600; + } else { + spriteId = 0; + mirror = false; + posX = computeScale(21, 258, id); + posY = 155; + speedX = 0; + speedY = -600; + } + + if (id >= 0) { + force->_seqId[id] = _scene->_sequences.addSpriteCycle(sprites[spriteId], mirror, 2, 0, 0, 0); + _scene->_sequences.setDepth(force->_seqId[id], 8); + _scene->_sequences.setPosition(force->_seqId[id], Common::Point(posX, posY)); + _scene->_sequences.setMotion(force->_seqId[id], 2, speedX, speedY); + _scene->_sequences.addSubEntry(force->_seqId[id], SEQUENCE_TRIGGER_EXPIRE, 0, 150 + id); + if (spriteId == 2) + force->_horizontal++; + else + force->_vertical++; + } + } + + force->_timer = _scene->_frameStartTime + 4; +} + +/*------------------------------------------------------------------------*/ + +void Scene300s::preActions() { + _game._player._needToWalk = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene301::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene301::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + + _globals[kMeteorologistStatus] = METEOROLOGIST_GONE; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); +} + +void Scene301::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 302; +} + +/*------------------------------------------------------------------------*/ + +Scene302::Scene302(MADSEngine *vm) : Scene3xx(vm) { + _oldFrame = 0; +} + +void Scene302::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_oldFrame); +} + +void Scene302::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene302::enter() { + _game._player._stepEnabled = false; + _game._player._visible = false; + + _scene->loadAnimation(formAnimName('a', -1), 71); + sceneEntrySound(); +} + +void Scene302::step() { + if (_game._trigger == 71) + _scene->_nextSceneId = 303; + + if ((_scene->_activeAnimation != nullptr) && (_scene->_activeAnimation->getCurrentFrame() != _oldFrame)) { + _oldFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_oldFrame == 147) { + _game._objects.setRoom(OBJ_POISON_DARTS, 1); + _game._objects.setRoom(OBJ_BLOWGUN, 1); + _game._objects.setRoom(OBJ_REBREATHER, 1); + _game._objects.setRoom(OBJ_STUFFED_FISH, 1); + _game._objects.setRoom(OBJ_DEAD_FISH, 1); + _game._objects.setRoom(OBJ_BURGER, 1); + + int count = (int)_game._objects._inventoryList.size(); + for (int idx = 0; idx < count; idx++) { + if (_game._objects.isInInventory(idx)) + _game._objects.setRoom(idx, 50); + } + } + } +} + +/*------------------------------------------------------------------------*/ + +void Scene303::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene303::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 0, 50, 120); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 10, 0, 0, 0); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); +} + +void Scene303::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 304; +} + +/*------------------------------------------------------------------------*/ + +Scene304::Scene304(MADSEngine *vm) : Scene3xx(vm) { + _explosionSpriteId = -1; +} + +void Scene304::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_explosionSpriteId); +} + +void Scene304::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene304::enter() { + if (_scene->_priorSceneId == 303) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + } else { + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0)); + + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 150, 0, 3, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 2); + _vm->_palette->setEntry(252, 45, 63, 45); + _vm->_palette->setEntry(253, 20, 45, 20); + + if (_globals[kSexOfRex] == REX_MALE) + _game._player._playerPos = Common::Point(111, 117); + else + _game._player._playerPos = Common::Point(113, 116); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 11, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -1); + _scene->_sequences.addTimer(48, 70); + } + + sceneEntrySound(); + _game.loadQuoteSet(0xEB, 0xEC, 0); +} + +void Scene304::step() { + if (_game._trigger == 60) + _scene->_nextSceneId = 311; + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: { + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + if (_globals[kSexOfRex] == REX_MALE) + _explosionSpriteId = _globals._spriteIndexes[1]; + else + _explosionSpriteId = _globals._spriteIndexes[4]; + + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, -1, 4); + _scene->_sequences.setDepth(sprIdx, 1); + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + } + break; + + case 71: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xEB)); + _scene->_sequences.addTimer(1, 72); + break; + + case 72: { + _vm->_sound->command(43); + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, 5, -2); + _scene->_sequences.setDepth(sprIdx, 1); + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 73); + if (_game._storyMode == STORYMODE_NICE) + _scene->_sequences.addSubEntry(sprIdx, SEQUENCE_TRIGGER_SPRITE, 8, 78); + } + break; + + case 73: { + int sprIdx = _scene->_sequences.addSpriteCycle(_explosionSpriteId, false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(sprIdx, -2, -2); + _scene->_sequences.setDepth(sprIdx, 1); + } + break; + + case 74: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 75: + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + break; + + case 76: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 2); + _scene->_sequences.addTimer(48, 77); + break; + + case 77: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(211, 45), 0xFDFC, 32, 0, 180, _game.getQuote(0xEC)); + _scene->_sequences.addTimer(120, 78); + break; + + case 78: + _scene->_nextSceneId = 316; + break; + + default: + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +Scene307::Scene307(MADSEngine *vm) : Scene3xx(vm) { + _afterPeeingFl = false; + _duringPeeingFl = false; + _grateOpenedFl = false; + _activePrisonerFl = false; + + _animationMode = -1; + _prisonerMessageId = -1; + _fieldCollisionCounter = -1; + + _lastFrameTime = 0; + _guardTime = 0; + _prisonerTimer = 0; + + _subQuote2 = ""; + + _forceField.init(); +} + +void Scene307::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); + + s.syncAsByte(_afterPeeingFl); + s.syncAsByte(_duringPeeingFl); + s.syncAsByte(_grateOpenedFl); + s.syncAsByte(_activePrisonerFl); + + s.syncAsSint32LE(_animationMode); + s.syncAsSint32LE(_prisonerMessageId); + s.syncAsSint32LE(_fieldCollisionCounter); + + s.syncAsUint32LE(_lastFrameTime); + s.syncAsUint32LE(_guardTime); + s.syncAsUint32LE(_prisonerTimer); + + s.syncString(_subQuote2); +} + +void Scene307::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_AIR_VENT); + _scene->addActiveVocab(NOUN_CLIMB_INTO); +} + +void Scene307::handleRexDialog(int quote) { + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 240, subQuote1); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 180, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); +} + +void Scene307::handlePrisonerEncounter() { + switch (_action._activeAction._verbId) { + case 275: + setDialogNode(5); + break; + + case 277: + setDialogNode(4); + break; + + case 276: + setDialogNode(6); + break; + } +} + +void Scene307::handlePrisonerSpeech(int firstQuoteId, int number, long timeout) { + int height = number * 14; + int posY; + + if (height < 60) + posY = 65 - height; + else + posY = 78 - (height / 2); + + _scene->_kernelMessages.reset(); + _activePrisonerFl = true; + + int quoteId = firstQuoteId; + for (int count = 0; count < number; count++) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_kernelMessages.add(Common::Point(5, posY), 0xFDFC, 0, 81, timeout, _game.getQuote(quoteId)); + posY += 14; + quoteId++; + } +} + +void Scene307::setDialogNode(int node) { + switch (node) { + case 0: + handlePrisonerSpeech(0x153, 2, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 1: + _globals[kMetBuddyBeast] = true; + handlePrisonerSpeech(0x10F, 2, 9999999); + _dialog1.start(); + break; + + case 2: + _globals[kMetBuddyBeast] = true; + handlePrisonerSpeech(0x111, 2, 9999999); + _dialog1.start(); + break; + + case 4: + handlePrisonerSpeech(0x116, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 5: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x117, 2, 9999999); + _dialog2.start(); + break; + + case 6: + handlePrisonerSpeech(0x123, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 7: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x124, 10, 9999999); + _dialog2.write(0x11A, false); + _dialog2.write(0x11B, true); + _dialog2.write(0x120, true); + _dialog2.start(); + break; + + case 8: + handlePrisonerSpeech(0x12E, 6, 9999999); + _dialog2.write(0x11A, false); + _dialog2.write(0x11B, false); + _dialog2.write(0x11C, true); + _dialog2.write(0x11D, true); + _dialog2.write(0x11F, true); + _dialog2.start(); + break; + + case 9: + handlePrisonerSpeech(0x134, 4, 9999999); + _dialog2.write(0x11D, false); + _dialog2.start(); + break; + + case 10: + handlePrisonerSpeech(0x138, 6, 9999999); + _dialog2.write(0x11E, false); + _dialog2.start(); + break; + + case 11: + handlePrisonerSpeech(0x13E, 6, 9999999); + _dialog2.write(0x11F, false); + _dialog2.write(0x121, true); + _dialog2.start(); + break; + + case 12: + handlePrisonerSpeech(0x144, 4, 9999999); + _dialog2.write(0x11C, false); + _dialog2.start(); + break; + + case 13: + handlePrisonerSpeech(0x148, 7, 9999999); + _dialog2.write(0x120, false); + _dialog2.start(); + break; + + case 14: + handlePrisonerSpeech(0x14F, 3, 9999999); + _dialog2.write(0x121, false); + _dialog2.start(); + break; + + case 15: + handlePrisonerSpeech(0x152, 1, 120); + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + case 16: + _globals[kKnowsBuddyBeast] = true; + handlePrisonerSpeech(0x10C, 1, 9999999); + _dialog2.start(); + break; + + default: + break; + } +} + +void Scene307::handlePrisonerDialog() { + switch (_action._activeAction._verbId) { + case 0x11A: + setDialogNode(7); + break; + + case 0x11B: + setDialogNode(8); + break; + + case 0x11C: + setDialogNode(12); + break; + + case 0x11D: + setDialogNode(9); + break; + + case 0x11E: + setDialogNode(10); + break; + + case 0x11F: + setDialogNode(11); + break; + + case 0x120: + setDialogNode(13); + break; + + case 0x121: + setDialogNode(14); + break; + + case 0x122: + setDialogNode(15); + break; + } +} + +void Scene307::handleDialog() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + handleRexDialog(_action._activeAction._verbId); + } else { + _game._player._stepEnabled = true; + + if (!_globals[kKnowsBuddyBeast]) { + handlePrisonerEncounter(); + } else { + handlePrisonerDialog(); + } + } +} + +void Scene307::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + initForceField(&_forceField, true); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + + _animationMode = 0; + _fieldCollisionCounter = 0; + + _scene->changeVariant(1); + + _game.loadQuoteSet(0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0x10C, 0x104, 0x106, 0x107, 0x108, 0x105, + 0x109, 0x10A, 0x10B, 0x10D, 0x10E, 0x10F, 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, + 0x118, 0x119, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0x123, 0x124, 0x125, + 0x126, 0x127, 0x128, 0x129, 0x12A, 0x12B, 0x12C, 0x12D, 0x12E, 0x12F, 0x130, 0x131, 0x132, 0x133, + 0x134, 0x135, 0x136, 0x137, 0x138, 0x139, 0x13A, 0x13B, 0x13C, 0x13D, 0x13E, 0x13F, 0x140, 0x141, + 0x142, 0x143, 0x144, 0x145, 0x146, 0x147, 0x148, 0x149, 0x14A, 0x14B, 0x14C, 0x14D, 0x14E, 0x14F, + 0x150, 0x151, 0x152, 0x153, 0); + + _dialog1.setup(0x3F, 0x113, 0x114, 0x115, -1); + _dialog2.setup(0x40, 0x11A, 0x11B, 0x11C, 0x11D, 0x11E, 0x11F, 0x120, 0x121, 0x122, 0); + + if (!_game._visitedScenes._sceneRevisited) + _dialog2.set(0x11A, 0x122, 0); + else if (_scene->_priorSceneId == 318) + _dialog2.write(0x11E, true); + + + if (_scene->_priorSceneId == -2) { + if (_grateOpenedFl) + _vm->_sound->command(10); + else + _vm->_sound->command(3); + } else { + _afterPeeingFl = false; + _duringPeeingFl = false; + _guardTime = 0; + _grateOpenedFl = false; + _activePrisonerFl = false; + _prisonerTimer = 0; + _prisonerMessageId = 0x104; + + if (_scene->_priorSceneId == 308) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(156, 113); + _game._player._facing = FACING_NORTH; + _animationMode = 1; + _vm->_sound->command(11); + _scene->loadAnimation(formAnimName('a', -1), 60); + } else if (_scene->_priorSceneId == 387) { + _game._player._playerPos = Common::Point(129, 108); + _game._player._facing = FACING_NORTH; + _vm->_sound->command(3); + _grateOpenedFl = true; + } else { + _game._player._playerPos = Common::Point(159, 109); + _game._player._facing = FACING_SOUTH; + _vm->_sound->command(3); + } + } + + if (_grateOpenedFl) { + _scene->_hotspots.activate(17, false); + + int idx = _scene->_dynamicHotspots.add(17, VERB_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP); + + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + } + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + + sceneEntrySound(); + + if ((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == 387)) + _scene->_kernelMessages.addQuote(0xF3, 120, 0); +} + +void Scene307::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if ((_animationMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() == 126) { + _forceField._flag = false; + _vm->_sound->command(5); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 194) { + _forceField._flag = true; + _vm->_sound->command(24); + } + } + + if ((_animationMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() == 54) + _forceField._flag = false; + + if (_scene->_activeAnimation->getCurrentFrame() == 150) { + _game._player._visible = false; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + } + } + + if (_game._trigger == 60) { + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _animationMode = 0; + _vm->_sound->command(9); + } + + if ((_lastFrameTime != _scene->_frameStartTime) && !_duringPeeingFl) { + int32 elapsedTime = _lastFrameTime - _scene->_frameStartTime; + if ((elapsedTime > 0) && (elapsedTime <= 4)) { + _guardTime += elapsedTime; + _prisonerTimer += elapsedTime; + } else { + _guardTime++; + _prisonerTimer++; + } + _lastFrameTime = _scene->_frameStartTime; + + if ((_guardTime > 3000) && !_duringPeeingFl && (_scene->_activeAnimation == nullptr) + && (_game._screenObjects._inputMode != 1) && _globals[kMetBuddyBeast] && !_activePrisonerFl) { + if (!_game._objects.isInInventory(OBJ_SCALPEL) && !_grateOpenedFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(151, 119), FACING_SOUTHEAST); + _animationMode = 2; + _vm->_sound->command(11); + _scene->loadAnimation(formAnimName('b', -1), 70); + } + _guardTime = 0; + } else if ((_prisonerTimer > 300) && (_game._screenObjects._inputMode != 1) && (_scene->_activeAnimation == nullptr) && !_activePrisonerFl) { + if (!_globals[kMetBuddyBeast]) { + int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(_prisonerMessageId)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + _prisonerMessageId++; + if (_prisonerMessageId > 0x10A) + _prisonerMessageId = 0x104; + } else if (_globals[kKnowsBuddyBeast] && (_dialog2.read(0) > 1) && (_vm->getRandomNumber(1, 3) == 1)) { + int idx = _scene->_kernelMessages.add(Common::Point(5, 51), 0xFDFC, 0, 81, 120, _game.getQuote(267)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + _prisonerTimer = 0; + } + } + + if (_game._trigger == 70) + _scene->_nextSceneId = 318; + + if (_game._trigger == 81) { + _prisonerTimer = 0; + if (_activePrisonerFl && (_guardTime > 2600)) + _guardTime = 3000 - _vm->getRandomNumber(1, 800); + + _activePrisonerFl = false; + } +} + +void Scene307::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(30715); + else if (_game._screenObjects._inputMode == 1) + handleDialog(); + else if (_action.isAction(VERB_TALKTO, NOUN_CELL_WALL) || _action.isAction(VERB_TALKTO, NOUN_WALL) || _action.isAction(VERB_TALKTO, NOUN_TOILET)) { + int node, say; + if (_globals[kKnowsBuddyBeast]) { + say = 0x10E; + node = 16; + } else if (_globals[kMetBuddyBeast]) { + say = 0x10E; + node = 2; + } else { + say = 0x10D; + node = 1; + } + + switch (_game._trigger) { + case 0: + handleRexDialog(say); + break; + + case 1: + setDialogNode(node); + break; + } + } else if (_action.isAction(VERB_PRY, NOUN_SCALPEL, NOUN_AIR_VENT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(239)); + _scene->_sequences.addTimer(120, 1); + break; + + case 1: + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8"); + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 12, 6, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addTimer(48, 4); + } + break; + + case 4: + _vm->_sound->command(26); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _scene->_sequences.addTimer(90, 5); + break; + + case 5: + _vm->_sound->command(10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(241)); + _scene->_sequences.addTimer(120, 6); + break; + + case 6: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _grateOpenedFl = true; + _scene->_hotspots.activate(17, false); + int idx = _scene->_dynamicHotspots.add(17, NOUN_CLIMB_INTO, -1, Common::Rect(117, 67, 117 + 19, 67 + 13)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(129, 104), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_UP); + _game._objects.removeFromInventory(OBJ_SCALPEL, NOWHERE); + _scene->_kernelMessages.addQuote(0xF2, 120, 7); + } + break; + + case 7: + _scene->_sprites.remove(_globals._spriteIndexes[5]); + _game._player._stepEnabled = true; + break; + + default: + break; + } + }else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_grateOpenedFl) { + switch (_game._trigger) { + case 0: + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXCL_8"); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addTimer(48, 4); + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(129, 102)); + _scene->_sequences.addTimer(48, 6); + break; + + case 6: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_USE, NOUN_TOILET) && (_game._storyMode != STORYMODE_NAUGHTY)) + _vm->_dialogs->show(30723); + else if (_action.isAction(VERB_USE, NOUN_TOILET)) { + if (!_afterPeeingFl) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(25); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _duringPeeingFl = true; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _scene->_sequences.addTimer(48, 3); + break; + + case 3: { + _scene->_sprites.remove(_globals._spriteIndexes[3]); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 4, 120, _game.getQuote(237)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + break; + + case 4: + _game._player._stepEnabled = true; + _duringPeeingFl = false; + _afterPeeingFl = true; + break; + + default: + break; + } + } else { + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(85, 39), 0x1110, 0, 0, 180, _game.getQuote(238)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + } else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) { + if (!_grateOpenedFl) + _vm->_dialogs->show(30710); + else + _vm->_dialogs->show(30711); + } else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(30712); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(30713); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(30714); + else if (_action.isAction(VERB_SHARPEN, NOUN_SCALPEL)) + _vm->_dialogs->show(30716); + else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL)) + _vm->_dialogs->show(30717); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(30718); + else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR)) { + switch (_fieldCollisionCounter) { + case 0: + _vm->_dialogs->show(30719); + _fieldCollisionCounter = 1; + break; + + case 1: + _vm->_dialogs->show(30720); + _fieldCollisionCounter = 2; + break; + + case 2: + _vm->_dialogs->show(30721); + _fieldCollisionCounter = 3; + break; + + case 3: + _vm->_dialogs->show(30722); + break; + } + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene308::Scene308(MADSEngine *vm) : Scene3xx(vm) { + _forceField.init(); +} + +void Scene308::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); +} + + +void Scene308::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene308::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.addTimer(48, 70); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + sceneEntrySound(); + _game.loadQuoteSet(0xF4, 0xF5, 0xF6, 0); +} + +void Scene308::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 60) + _scene->_nextSceneId = 307; + + if (_game._trigger < 70) + return; + + switch (_game._trigger) { + case 70: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 18, 9, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(244)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + break; + + case 71: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(48, 72); + } + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(48, 74); + } + break; + + case 74: { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 20, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 6, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(245)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + } + break; + + case 75: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 23, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 10); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + } + break; + + case 76: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + _scene->_kernelMessages.reset(); + int idx = _scene->_kernelMessages.add(Common::Point(171, 21), 0xFDFC, 0, 0, 120, _game.getQuote(246)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + } + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene309::Scene309(MADSEngine *vm) : Scene3xx(vm) { + for (int i = 0; i < 3; i++) { + _characterSpriteIndexes[i] = -1; + _messagesIndexes[i] = -1; + } + + _lastFrame = -1; + _forceField.init(); +} + +void Scene309::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); + + for (int i = 0; i < 3; ++i) + s.syncAsSint32LE(_characterSpriteIndexes[i]); + for (int i = 0; i < 3; ++i) + s.syncAsSint32LE(_messagesIndexes[i]); + s.syncAsSint32LE(_lastFrame); +} + +void Scene309::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene309::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 15); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 3, 70); + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _vm->_palette->setEntry(16, 63, 63, 63); + _vm->_palette->setEntry(17, 45, 45, 45); + _vm->_palette->setEntry(250, 63, 20, 20); + _vm->_palette->setEntry(251, 45, 10, 10); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + + _characterSpriteIndexes[0] = _scene->_activeAnimation->_spriteListIndexes[2]; + _characterSpriteIndexes[1] = _scene->_activeAnimation->_spriteListIndexes[2]; + _characterSpriteIndexes[2] = _scene->_activeAnimation->_spriteListIndexes[1]; + + _messagesIndexes[0] = -1; + _messagesIndexes[1] = -1; + _messagesIndexes[2] = -1; + + sceneEntrySound(); + + _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x15C, 0x15D, 0x15E, 0); +} + +void Scene309::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 61) { + _messagesIndexes[0] = -1; + _messagesIndexes[1] = -1; + } + + if (_game._trigger == 62) + _messagesIndexes[2] = -1; + + if (_scene->_activeAnimation != nullptr) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_lastFrame == 39) { + _messagesIndexes[0] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 61, 210, _game.getQuote(348)); + _messagesIndexes[1] = _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 32, 0, 210, _game.getQuote(349)); + } + + if (_lastFrame == 97) + _messagesIndexes[2] = _scene->_kernelMessages.add(Common::Point(0, 0), 0xFBFA, 32, 62, 180, _game.getQuote(350)); + + for (int charIdx = 0; charIdx < 3; charIdx++) { + if (_messagesIndexes[charIdx] >= 0) { + bool match = false; + int j = -1; + for (j = _scene->_activeAnimation->_oldFrameEntry; j < _scene->_activeAnimation->_header._frameEntriesCount; j++) { + if (_scene->_activeAnimation->_frameEntries[j]._spriteSlot._spritesIndex == _characterSpriteIndexes[charIdx]) { + match = true; + break; + } + } + + if (match) { + SpriteSlotSubset *curSpriteSlot = &_scene->_activeAnimation->_frameEntries[j]._spriteSlot; + _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.x = curSpriteSlot->_position.x; + _scene->_kernelMessages._entries[_messagesIndexes[charIdx]]._position.y = curSpriteSlot->_position.y - (50 + (14 * ((charIdx == 0) ? 2 : 1))); + } + } + } + } + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: { + int idx = _scene->_dynamicHotspots.add(689, 690, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(142, 146), FACING_NORTHEAST); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } + break; + + case 71: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + int idx = _scene->_kernelMessages.add(Common::Point(85, 37), 0xFDFC, 0, 0, 120, _game.getQuote(248)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + } + break; + + case 72: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 8, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 8, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + break; + + case 73: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 12, 20); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + int idx = _scene->_kernelMessages.add(Common::Point(170, 49), 0xFDFC, 0, 0, 120, _game.getQuote(249)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + } + break; + + case 74: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 21, 23); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + } + break; + + case 75: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 6, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 24, 25); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + } + break; + + case 76: { + int _oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 26, 28); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], _oldIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 77); + } + break; + + case 77: { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 90, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 29, 30); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 11); + int idx = _scene->_kernelMessages.add(Common::Point(15, 46), 0xFDFC, 0, 0, 120, _game.getQuote(247)); + _scene->_kernelMessages.setQuoted(idx, 2, true); + _scene->_sequences.addTimer(120, 78); + } + break; + } + } + + if (_game._trigger == 60) + _scene->_nextSceneId = 308; +} + +/*------------------------------------------------------------------------*/ + +Scene310::Scene310(MADSEngine *vm) : Scene3xx(vm) { + _forceField.init(); +} + +void Scene310::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + _forceField.synchronize(s); +} + +void Scene310::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene310::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*SC003x0"); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites("*SC003x1"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*SC003x2"); + + initForceField(&_forceField, true); + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 70); + + sceneEntrySound(); +} + +void Scene310::step() { + handleForceField(&_forceField, &_globals._spriteIndexes[0]); + + if (_game._trigger == 70) + _scene->_nextSceneId = 309; +} + +/*------------------------------------------------------------------------*/ + +Scene311::Scene311(MADSEngine *vm) : Scene3xx(vm) { + _checkGuardFl = false; +} + +void Scene311::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_checkGuardFl); +} + +void Scene311::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); + + if (_scene->_currentSceneId == 304) + _game._player._spritesPrefix = ""; +} + +void Scene311::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _checkGuardFl = false; + _game.loadQuoteSet(0xFA, 0); + + if (_scene->_priorSceneId == 391) { + _globals[kSexOfRex] = REX_MALE; + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._facing = FACING_SOUTH; + _game._player._playerPos = Common::Point(166, 101); + _scene->_sequences.addTimer(120, 71); + } else if (_scene->_priorSceneId == 310) + _game._player._playerPos = Common::Point(302, 145); + else if (_scene->_priorSceneId == 320) { + _game._player._playerPos = Common::Point(129, 113); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 70); + } + + sceneEntrySound(); +} + +void Scene311::step() { + if (_game._trigger == 70) + _scene->_nextSceneId = 310; + + if (_game._trigger >= 71) { + switch (_game._trigger) { + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 72); + break; + + case 72: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 73); + break; + + case 73: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 74); + break; + + case 74: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 75: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 76); + } + break; + + case 76: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 77); + break; + + case 77: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 78); + break; + + case 78: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 79); + break; + + case 79: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } + + if (_game._player._moving && (_scene->_rails.getNext() > 0)) { + int x = _game._player._prepareWalkPos.x; + if (x < 75) + x = 75; + if (x > 207) + x = 207; + + _checkGuardFl = true; + _game._player.startWalking(Common::Point(x, 122), FACING_SOUTH); + _scene->_rails.resetNext(); + } +} + +void Scene311::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(31119); + else if (_checkGuardFl) { + _checkGuardFl = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(0xFA, 120, 0); + } else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) + _scene->_nextSceneId = 320; + else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int oldIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], oldIdx); + } + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(15, 4); + } + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(15, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(31110); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(31111); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE)) + _vm->_dialogs->show(31112); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS)) + _vm->_dialogs->show(31113); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS)) + _vm->_dialogs->show(31114); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT)) + _vm->_dialogs->show(31115); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHT)) + _vm->_dialogs->show(31116); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(31117); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(31118); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(31120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene313::setup() { + setPlayerSpritesPrefix(); + _game._player._spritesPrefix = "RM313A"; + setAAName(); +} + +void Scene313::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if ((_scene->_priorSceneId == 366) || (_scene->_priorSceneId == 316)) { + _game._player._playerPos = Common::Point(30, 80); + _game._player._facing = FACING_NORTH; + } else if ((_scene->_priorSceneId == 311) || (_scene->_priorSceneId == 361) || (_scene->_priorSceneId == 391)) { + _game._player._playerPos = Common::Point(90, 70); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 390) { + _game._player._playerPos = Common::Point(126, 70); + _game._player._facing = FACING_EAST; + } else if ((_scene->_priorSceneId == 389) || (_scene->_priorSceneId == 399)) { + _game._player._playerPos = Common::Point(163, 70); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 388) { + _game._player._playerPos = Common::Point(199, 70); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(234, 70); + _game._player._facing = FACING_WEST; + } + + if (_globals[kAfterHavoc]) { + for (uint16 i = 0; i < _scene->_paletteCycles.size(); i++) { + int palIdx = _scene->_paletteCycles[i]._firstColorIndex; + int size = _scene->_paletteCycles[i]._colorCount * 3; + memset(&_vm->_palette->_cyclingPalette[palIdx], 0, size); + memset(&_vm->_palette->_mainPalette[palIdx], 0, size); + } + } + + sceneEntrySound(); +} + +void Scene313::actions() { + if (_action.isAction(VERB_CRAWL_TO, NOUN_FOURTH_CELL)) + _scene->_nextSceneId = 387; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_THIRD_CELL)) + _scene->_nextSceneId = 388; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECOND_CELL)) { + if (_globals[kAfterHavoc]) + _scene->_nextSceneId = 399; + else + _scene->_nextSceneId = 389; + } else if (_action.isAction(VERB_CRAWL_TO, NOUN_FIRST_CELL)) + _scene->_nextSceneId = 390; + else if (_action.isAction(VERB_CRAWL_TO, NOUN_SECURITY_STATION)) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + _vm->_dialogs->show(31301); + } + _scene->_nextSceneId = 391; + } else if (_action.isAction(VERB_CRAWL_TO, NOUN_EQUIPMENT_ROOM)) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + _vm->_dialogs->show(31301); + } + _scene->_nextSceneId = 366; + } else if (!_action.isAction(VERB_CRAWL_DOWN, NOUN_AIR_SHAFT)) + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene316::setup() { + if (_scene->_currentSceneId == 366) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene316::handleRexInGrate() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 2, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } + break; + + case 3: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + } + break; + + case 4: { + int oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 10, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + break; + + case 5: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + + oldIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], oldIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 13, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 7: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], -1); + break; + + case 8: { + int oldIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], oldIdx); + _scene->_sequences.addTimer(15, 9); + } + break; + + case 9: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(48, 10); + break; + + case 10: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene316::handleRoxInGrate() { + int temp; + int temp1; + + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 2, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 3: + temp1 = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp1); + break; + + case 4: + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 10, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 5, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: + temp = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp); + + temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addTimer(20, 6); + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 13, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 17, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 7: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 16); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], -1); + break; + + case 8: + temp = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], temp); + _scene->_sequences.addTimer(20, 9); + break; + + case 9: + _scene->_sequences.setDone(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(48, 10); + break; + + case 10: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene316::enter() { + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCL_2"); + } else { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXCL_8"); + } + + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('v', 0)); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + + if (_scene->_priorSceneId == 366) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._playerPos = Common::Point(78, 87); + _game._player._facing = FACING_SOUTH; + _scene->_sequences.addTimer(48, 70); + } else if (_scene->_priorSceneId == 321) { + _game._player._playerPos = Common::Point(153, 102); + _game._player._facing = FACING_SOUTH; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(44); + int spriteIdx = (_globals[kSexOfRex] == REX_MALE) ? 1 : 2; + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[spriteIdx], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(291, 126); + + sceneEntrySound(); + _game.loadQuoteSet(0xFD, 0); +} + +void Scene316::step() { + if (_game._trigger == 60) { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 2, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 71: { + int synxIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx); + } + break; + + case 72: { + int synxIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 6, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], synxIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + break; + + case 73: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + break; + + case 74: { + int synxIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 12); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], synxIdx); + } + break; + + case 75: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } +} + +void Scene316::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) { + if (_globals[kAfterHavoc]) + _game._player._walkOffScreenSceneId = 354; + else + _game._player._walkOffScreenSceneId = 304; + } +} + +void Scene316::actions() { + if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_globals[kSexOfRex] == REX_FEMALE) + handleRoxInGrate(); + else + handleRexInGrate(); + } else if (_action.isAction(VERB_WALK_UP, NOUN_RAMP) || _action.isAction(VERB_WALK_ONTO, NOUN_PLATFORM)) { + switch (_game._trigger) { + case 0: + if (_globals[kCityFlooded]) { + _vm->_dialogs->show(31623); + } else { + _vm->_sound->command(45); + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + } + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 8, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_kernelMessages.reset(); + if (!_game._visitedScenes.exists(321)) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(253)); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addTimer(48, 4); + break; + + case 3: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -2, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addTimer(48, 4); + break; + + case 4: + _scene->_nextSceneId = 321; + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(31610); + else if (_action.isAction(VERB_LOOK, NOUN_STRANGE_DEVICE)) { + if (_game._visitedScenes.exists(321)) + _vm->_dialogs->show(31612); + else + _vm->_dialogs->show(31611); + } else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS)) + _vm->_dialogs->show(31613); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(31614); + else if (_action.isAction(VERB_LOOK, NOUN_PANEL)) + _vm->_dialogs->show(31615); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(31616); + else if (_action.isAction(VERB_LOOK, NOUN_RAMP)) + _vm->_dialogs->show(31617); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(31618); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) { + if (!_globals[kAfterHavoc]) { + if (_game._difficulty != DIFFICULTY_EASY) + _vm->_dialogs->show(31620); + else + _vm->_dialogs->show(31619); + } + } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(31621); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(31622); + else + return; + + _action._inProgress = false; +} + + +/*------------------------------------------------------------------------*/ + +Scene318::Scene318(MADSEngine *vm) : Scene3xx(vm) { + _dropTimer = 0; + + _lastFrame = -1; + _animMode = -1; + _internCounter = -1; + _counter = -1; + + _dialogFl = false; + _internTalkingFl = false; + _internWalkingFl = false; + _internVisibleFl = false; + _explosionFl = false; + + _lastFrameCounter = 0; + + _subQuote2 = ""; +} + +void Scene318::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_dropTimer); + + s.syncAsSint32LE(_lastFrame); + s.syncAsSint32LE(_animMode); + s.syncAsSint32LE(_internCounter); + s.syncAsSint32LE(_counter); + + s.syncAsByte(_dialogFl); + s.syncAsByte(_internTalkingFl); + s.syncAsByte(_internWalkingFl); + s.syncAsByte(_internVisibleFl); + s.syncAsByte(_explosionFl); + + s.syncAsUint32LE(_lastFrameCounter); + + s.syncString(_subQuote2); +} + +void Scene318::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene318::handleDialog() { + if (!_game._trigger) { + _game._player._stepEnabled = false; + handleRexDialogs(_action._activeAction._verbId); + } else if (_game._trigger == 2) { + int synxIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], synxIdx); + _vm->_sound->command(3); + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._stepEnabled = true; + } else { + if (_action._activeAction._verbId < 0x19C) + _dialog1.write(_action._activeAction._verbId, false); + + switch (_action._activeAction._verbId) { + case 0x191: + handleInternDialog(0x19E, 2, 9999999); + _dialog1.write(0x192, true); + break; + + case 0x192: + handleInternDialog(0x1A0, 5, 9999999); + _dialog1.write(0x193, true); + break; + + case 0x193: + handleInternDialog(0x1A5, 4, 9999999); + _dialog1.write(0x194, true); + break; + + case 0x194: + handleInternDialog(0x1A9, 6, 9999999); + _dialog1.write(0x195, true); + _dialog1.write(0x196, true); + _dialog1.write(0x19D, false); + break; + + case 0x195: + handleInternDialog(0x1AF, 7, 9999999); + if (!_dialog1.read(0x196)) + _dialog1.write(0x197, true); + break; + + case 0x196: + handleInternDialog(0x1B6, 5, 9999999); + if (!_dialog1.read(0x195)) + _dialog1.write(0x197, true); + break; + + case 0x197: + handleInternDialog(0x1BB, 5, 9999999); + break; + + case 0x198: + handleInternDialog(0x1C0, 5, 9999999); + _dialog1.write(0x19A, true); + break; + + case 0x199: + handleInternDialog(0x1C5, 3, 9999999); + break; + + case 0x19A: + handleInternDialog(0x1C8, 5, 9999999); + _dialog1.write(0x19B, true); + break; + + case 0x19B: + handleInternDialog(0x1CD, 3, 9999999); + break; + + case 0x19C: + case 0x19D: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + + _dialogFl = false; + handleInternDialog(0x1D0, 1, 120); + if (_dialog1.read(0) || (_action._activeAction._verbId == 0x19D)) { + _explosionFl = true; + _internCounter = 3420; + } + break; + } + + if (_action._activeAction._verbId < 0x19C) { + _dialog1.start(); + _game._player._stepEnabled = true; + } + + } +} + +void Scene318::handleRexDialogs(int quote) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(quote); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(138, 59), 0x1110, 32, 0, 240, subQuote1); + _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 180, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(138, 73), 0x1110, 32, 1, 120, curQuote); +} + +void Scene318::handleInternDialog(int quoteId, int quoteNum, uint32 timeout) { + int height = quoteNum * 14; + int posY; + if (height < 85) + posY = 87 - height; + else + posY = 2; + + int curQuoteId= quoteId; + + int maxWidth = 0; + for (int i = 0; i < quoteNum; i++) { + maxWidth = MAX(maxWidth, _vm->_font->getWidth(_game.getQuote(curQuoteId), -1)); + curQuoteId++; + } + + int posX = MIN(319 - maxWidth, 178 - (maxWidth >> 1)); + curQuoteId = quoteId; + + _scene->_kernelMessages.reset(); + _internTalkingFl = true; + + for (int i = 0; i < quoteNum; i++) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(180, 63); + _scene->_kernelMessages.add(Common::Point(posX, posY), 0xFDFC, 0, 0, timeout, _game.getQuote(curQuoteId)); + posY += 14; + curQuoteId++; + } +} + +void Scene318::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('k', -1)); + + if (_globals[kAfterHavoc]) { + _scene->loadAnimation(formAnimName('f', -1)); + _scene->_activeAnimation->_resetFlag = true; + } else if (!_globals[kHasSeenProfPyro]) { + _scene->_hotspots.activate(NOUN_PROFESSORS_GURNEY, false); + _scene->_hotspots.activate(NOUN_PROFESSOR, false); + _scene->_hotspots.activate(NOUN_TAPE_PLAYER, false); + } + + if (_game._objects.isInRoom(OBJ_SCALPEL)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 0, 0, 120); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 4); + _scene->_dynamicHotspots.add(NOUN_SCALPEL, VERB_TAKE, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + } + + if (_scene->_priorSceneId == 357) + _game._player._playerPos = Common::Point(15, 110); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(214, 152); + + _dialog1.setup(0x47, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19D, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog1.set(0x191, 0x198, 0x199, 0x19C, 0); + if (_game._widepipeCtr >= 2) + _dialog1.write(0x19D, true); + } + + if (_scene->_priorSceneId == 307) { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('a', -1), 60); + _animMode = 1; + } + + _lastFrame = 0; + _scene->_hotspots.activate(NOUN_INTERN, false); + + if (_scene->_priorSceneId != -2) { + _dialogFl = false; + _internWalkingFl = false; + _counter= 0; + _internCounter= 0; + _internVisibleFl = true; + _explosionFl = false; + } + + _game.loadQuoteSet(0x18C, 0x18D, 0x18E, 0x18F, 0x191, 0x192, 0x193, 0x194, 0x195, 0x196, + 0x197, 0x198, 0x199, 0x19A, 0x19B, 0x19C, 0x19E, 0x19E, 0x1A0, 0x1A1, 0x1A2, 0x1A3, + 0x1A4, 0x1A5, 0x1A6, 0x1A7, 0x1A8, 0x1A9, 0x1AA, 0x1AB, 0x1AC, 0x1AD, 0x1AE, 0x1AF, + 0x1B0, 0x1B1, 0x1B2, 0x1B3, 0x1B4, 0x1B5, 0x1B6, 0x1B7, 0x1B8, 0x1B9, 0x1BA, 0x1BB, + 0x1BC, 0x1BD, 0x1BE, 0x1BF, 0x1C0, 0x1C1, 0x1C2, 0x1C3, 0x1C4, 0x1C5, 0x1C6, 0x1C7, + 0x1C8, 0x1C9, 0x1CA, 0x1CB, 0x1CC, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, + 0x190, 0x19D, 0); + + if ((_scene->_priorSceneId== -2) || (((_scene->_priorSceneId == 318) || (_scene->_priorSceneId == -1)) && (!_globals[kAfterHavoc]))) { + if (!_globals[kAfterHavoc]) { + _game._player._visible = false; + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _animMode = 2; + + if (_game._visitedScenes.exists(319) || !_internVisibleFl) { + _internVisibleFl = false; + _dialogFl = false; + } else { + _scene->loadAnimation(formAnimName('b', -1), 61); + _scene->_hotspots.activate(NOUN_INTERN, true); + } + + if (_dialogFl) { + _dialog1.start(); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + } else + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + } + } + + if (_scene->_priorSceneId == 319) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _animMode = 4; + if (!_globals[kHasSeenProfPyro]) { + _scene->loadAnimation(formAnimName('d', -1), 64); + _globals[kHasSeenProfPyro] = true; + } else { + _scene->loadAnimation(formAnimName('e', -1), 64); + } + } + + _internTalkingFl = false; + _vm->_palette->setEntry(252, 63, 63, 10); + _vm->_palette->setEntry(253, 45, 45, 05); + + _dropTimer = _vm->_game->_scene._frameStartTime; + sceneEntrySound(); + + if (_dialogFl) + _vm->_sound->command(15); +} + +void Scene318::step() { + if ((_scene->_activeAnimation != nullptr) && (_animMode == 2)) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + switch (_lastFrame) { + case 20: + case 30: + case 40: + case 50: + case 60: + case 70: + case 80: + case 90: + case 100: + case 110: + case 120: + case 130: + case 140: + case 149: + if (_internWalkingFl) { + nextFrame = 149; + } else if (_internTalkingFl) { + nextFrame = 149; + } else if (_lastFrame == 149) { + nextFrame = 4; + } + break; + + case 151: + if (_internWalkingFl) + nextFrame = 183; + break; + + case 167: + case 184: + if (_internWalkingFl) { + nextFrame = 184; + } else if (!_internTalkingFl) { + nextFrame = 0; + } else if (_vm->getRandomNumber(1, 100) <= 50) { + nextFrame = 151; + } else { + nextFrame = 167; + } + + if (nextFrame == 184) { + handleInternDialog(0x1D1, 3, 240); + _scene->_hotspots.activate(NOUN_INTERN, false); + _internVisibleFl = false; + } + break; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _lastFrame = nextFrame; + } + } + } + + switch (_game._trigger) { + case 60: + _vm->_sound->command(3); + _animMode = 2; + _scene->_reloadSceneFlag = true; + break; + + case 61: + _counter = 0; + break; + + case 62: + _scene->_nextSceneId = 319; + break; + + case 63: + _internTalkingFl = false; + break; + + case 64: + _vm->_sound->command(3); + _scene->_nextSceneId = 307; + break; + } + + uint32 tmpFrame = _vm->_events->getFrameCounter(); + long diffFrame = tmpFrame - _lastFrameCounter; + _lastFrameCounter = tmpFrame; + + if ((_animMode == 2) && !_internVisibleFl && _game._player._stepEnabled) { + if ((diffFrame >= 0) && (diffFrame <= 4)) + _counter += diffFrame; + else + _counter++; + + int extraCounter = _game._objects.isInInventory(OBJ_SCALPEL) ? 900 : 0; + + if (_counter + extraCounter >= 1800) { + _scene->freeAnimation(); + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('c', -1), 62); + _animMode = 3; + } + } else if ((_animMode == 2) && _explosionFl && _internVisibleFl && !_dialogFl + && !_internWalkingFl && (_game._screenObjects._inputMode != 1)) { + if ((diffFrame >= 0) && (diffFrame <= 4)) + _internCounter += diffFrame; + else + _internCounter++; + + if (_internCounter >= 3600) { + _vm->_sound->command(59); + _vm->_screen._shakeCountdown = 20; + _internWalkingFl = true; + } + } + + if ((_vm->_game->_scene._frameStartTime - _dropTimer) > 600) { + _vm->_sound->command(51); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 14, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _dropTimer = _vm->_game->_scene._frameStartTime; + } +} + +void Scene318::preActions() { + if (_game._player._needToWalk) + _game._player._needToWalk = _game._player._visible; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 357; +} + +void Scene318::actions() { + if (_game._screenObjects._inputMode == 1) { + handleDialog(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TALKTO, NOUN_INTERN)) { + switch (_game._trigger) { + case 0: { + _dialogFl = true; + _vm->_sound->command(15); + _game._player._stepEnabled = false; + handleRexDialogs(_vm->getRandomNumber(0x18C, 0x18E)); + + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 80); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _game._player._stepEnabled = true; + handleInternDialog(0x18F, 1, 9999999); + _dialog1.start(); + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + } + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_SCALPEL) && (_game._objects.isInRoom(OBJ_SCALPEL) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 2, 0, 80); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_internVisibleFl) + handleInternDialog(0x190, 1, 120); + else { + _game._objects.addToInventory(OBJ_SCALPEL); + _vm->_dialogs->showItem(OBJ_SCALPEL, 0x7C5D); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + } + break; + + case 2: { + int oldIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(142, 121)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], oldIdx); + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + break; + } + _action._inProgress = false; + return; + } + + if (_game._player._visible) { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 407; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER)) { + if (_game._objects.isInRoom(OBJ_AUDIO_TAPE)) { + _vm->_dialogs->showItem(OBJ_AUDIO_TAPE, 0x7C5B); + _game._objects.addToInventory(OBJ_AUDIO_TAPE); + } else + _vm->_dialogs->show(31834); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER)) { + if (_game._objects.isInRoom(OBJ_AUDIO_TAPE)) + _vm->_dialogs->show(31833); + else + _vm->_dialogs->show(31834); + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_DOCTORS_OFFICE)) { + _vm->_dialogs->show(31831); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) { + _vm->_dialogs->show(31823); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) { + _vm->_dialogs->show(31825); + _action._inProgress = false; + return; + } + } else { // Not visible + if (_action.isAction(VERB_LOOK, NOUN_GURNEY)) { + _vm->_dialogs->show(31822); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_INSTRUMENT_TABLE)) { + _vm->_dialogs->show(31824); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(31810); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(31811); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(31812); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(31813); + else if (_action.isAction(VERB_LOOK, NOUN_FAUCET)) + _vm->_dialogs->show(31814); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(31815); + else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(31816); + else if (_action.isAction(VERB_LOOK, NOUN_LARGE_BLADE)) + _vm->_dialogs->show(31817); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(31818); + else if (_action.isAction(VERB_LOOK, NOUN_CABINETS)) + _vm->_dialogs->show(31819); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(31820); + else if (_action.isAction(VERB_LOOK, NOUN_SHELF)) + _vm->_dialogs->show(31821); + else if (_action.isAction(VERB_OPEN, NOUN_CABINETS)) + _vm->_dialogs->show(31829); + else if (_action.isAction(VERB_LOOK, NOUN_INTERN)) + _vm->_dialogs->show(31830); + else if (_action.isAction(VERB_LOOK, NOUN_PROFESSOR)) + _vm->_dialogs->show(31832); + else if (_action.isAction(VERB_LOOK, NOUN_PROFESSORS_GURNEY)) + _vm->_dialogs->show(31836); + else if (_action._lookFlag) { + if (_game._player._visible || _game._objects.isInInventory(OBJ_SCALPEL)) + _vm->_dialogs->show(31828); + else if (_internVisibleFl) + _vm->_dialogs->show(31826); + else + _vm->_dialogs->show(31827); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene319::Scene319(MADSEngine *vm) : Scene3xx(vm) { + _animMode = -1; + _animFrame = -1; + _nextAction1 = -1; + _nextAction2 = -1; + _slacheMode = -1; + _slacheTopic = -1; + _slachePosY = -1; + + _slacheTalkingFl = false; + _slacheReady = false; + _slacheInitFl = false; + + _subQuote2 = ""; +} + +void Scene319::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_animMode); + s.syncAsUint32LE(_animFrame); + s.syncAsUint32LE(_nextAction1); + s.syncAsUint32LE(_nextAction2); + s.syncAsUint32LE(_slacheMode); + s.syncAsUint32LE(_slacheTopic); + s.syncAsUint32LE(_slachePosY); + + s.syncAsByte(_slacheTalkingFl); + s.syncAsByte(_slacheReady); + s.syncAsByte(_slacheInitFl); + + s.syncString(_subQuote2); +} + +void Scene319::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene319::handleRexDialogues(int quote) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(quote); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1; + _game.splitQuote(curQuote, subQuote1, _subQuote2); + _scene->_kernelMessages.add(Common::Point(160, 106), 0x1110, 32, 0, 120, subQuote1); + _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, _subQuote2); + } else + _scene->_kernelMessages.add(Common::Point(160, 120), 0x1110, 32, 1, 120, curQuote); +} + +void Scene319::handleSlacheDialogs(int quoteId, int counter, uint32 timer) { + int curQuote = quoteId; + int posY = 5 + (_slachePosY * 14); + + for (int count = 0; count < counter; count++, curQuote++) { + _scene->_kernelMessages.add(Common::Point(8, posY), 0xFDFC, 0, 0, timer, _game.getQuote(curQuote)); + posY += 14; + } +} + +void Scene319::enter() { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('e', 0)); + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('k', -1)); + + if (!_game._objects.isInInventory(OBJ_SCALPEL)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + } + + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 300); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 67, 0, 0, 377); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 173, 0, 0, 233); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14); + + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + _dialog1.setup(0x43, 0x165, 0x166, 0x167, 0x168, 0x169, 0x16A, 0); + _dialog2.setup(0x44, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0); + _dialog3.setup(0x45, 0x17D, 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0); + + if (_scene->_priorSceneId != -2) { + _dialog1.set(0x165, 0x166, 0x167, 0x168, 0); + _dialog2.set(0x171, 0x172, 0x173, 0x174, 0); + _dialog3.set(0x17D, 0x17E, 0x17F, 0x180, 0); + } + + _game.loadQuoteSet(0x15F, 0x160, 0x161, 0x162, 0x163, 0x164, 0x16B, 0x16C, 0x16D, + 0x16E, 0x16F, 0x170, 0x177, 0x178, 0x178, 0x17A, 0x17B, 0x17C, 0x165, 0x166, + 0x167, 0x168, 0x169, 0x16A, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x17D, + 0x17E, 0x17F, 0x180, 0x181, 0x182, 0x183, 0x184, 0x185, 0x186, 0x187, 0x188, + 0x189, 0x18A, 0x18B, 0); + + _vm->_palette->setEntry(252, 63, 30, 2); + _vm->_palette->setEntry(253, 45, 15, 1); + + _slachePosY = 0; + _slacheInitFl = false; + _slacheTalkingFl = false; + _slacheReady = false; + _animFrame = 0; + + _scene->loadAnimation(formAnimName('b', 0)); + + if (_scene->_priorSceneId != -2) { + _animMode = 1; + _nextAction1 = 2; + _nextAction2 = 2; + _slacheMode = 1; + _slacheTopic = 1; + _slacheInitFl = true; + + if (_globals[kRexHasMetSlache]) { + handleSlacheDialogs(VERB_WALK_OUTSIDE, 2, 9999999); + _slachePosY = 3; + } else { + handleSlacheDialogs(0x186, 4, 9999999); + _slachePosY = 5; + } + } + + switch (_slacheTopic) { + case 1: + handleSlacheDialogs(0x15F, 2, 9999999); + _dialog1.start(); + break; + + case 2: + handleSlacheDialogs(0x16B, 2, 9999999); + _dialog2.start(); + break; + + case 3: + handleSlacheDialogs(0x177, 2, 9999999); + _dialog3.start(); + break; + + default: + break; + } + + _slachePosY = 0; + sceneEntrySound(); +} + +void Scene319::step() { + if (_scene->_activeAnimation == nullptr) + return; + + if (_animFrame != _scene->_activeAnimation->getCurrentFrame()) { + _animFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + if (_animMode == 1) { + switch (_animFrame) { + case 6: + _slacheTalkingFl = true; + break; + + case 29: + _slacheReady = true; + break; + + case 39: + if (_slacheInitFl) { + _slacheInitFl = false; + if (_nextAction1 == 2) + nextFrame = 0; + } else if (_nextAction1 == 2) + _nextAction1 = 1; + break; + + case 50: + case 60: + case 70: + case 85: + if (_nextAction1 == 2) + nextFrame = 0; + else if (_nextAction1 == 3) { + nextFrame = 85; + _slacheTalkingFl = true; + } else if (_animFrame == 85) { + if (!_game._player._stepEnabled) + _slacheTalkingFl = true; + nextFrame = 40; + } + break; + + case 115: + _slacheReady = true; + break; + + case 129: + if (_nextAction1 == 3) { + nextFrame = 115; + if (!_game._player._stepEnabled) + _slacheTalkingFl = true; + } + break; + + case 145: + nextFrame = 40; + break; + + default: + break; + } + + if ((_animFrame > 40) && (_animFrame < 85) && (nextFrame < 0)) { + switch (_nextAction1) { + case 4: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 2; + _scene->loadAnimation(formAnimName('b', 3), 70); + break; + + case 5: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 3; + _scene->loadAnimation(formAnimName('b', 4), 71); + break; + + case 6: + _animFrame = 0; + _scene->freeAnimation(); + _animMode = 4; + _scene->loadAnimation(formAnimName('b', 5), 72); + break; + + default: + break; + } + + if (!_animFrame) { + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + + for (int i = 0; i <= 1; i++) { + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 1, 7); + } + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + } + } + } + + if (_animMode == 2) { + if (_animFrame == 13) + _vm->_screen._shakeCountdown = 40; + + if (_animFrame == 16) + _vm->_screen._shakeCountdown = 1; + } + + if (_animMode == 3) { + if (_animFrame == 11) + _vm->_screen._shakeCountdown = 60; + + if (_animFrame == 18) + _vm->_screen._shakeCountdown = 1; + } + + if ((_animMode == 4) && (_animFrame == 16)) + _vm->_screen._shakeCountdown = 80; + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _animFrame = nextFrame; + } + } + + switch (_game._trigger) { + case 70: + case 71: + _animMode = 1; + _nextAction1 = _nextAction2; + _animFrame = 0; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('b', 0)); + if (_nextAction1 == 3) + _scene->_activeAnimation->setCurrentFrame(85); + else if (_nextAction1 == 1) + _scene->_activeAnimation->setCurrentFrame(40); + + _animFrame = _scene->_activeAnimation->getCurrentFrame(); + _slacheTalkingFl = true; + _vm->_screen._shakeCountdown = 1; + + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 8, 13); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[0], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + break; + + case 72: + _vm->_palette->setColorFlags(0xFF, 0, 0); + _vm->_palette->setColorValues(0, 0, 0); + _vm->_palette->fadeOut(_vm->_palette->_mainPalette, nullptr, 18, 228, + 248, 0, 1, 16); + _vm->_screen._shakeCountdown = 1; + _scene->_reloadSceneFlag = true; + break; + + case 73: + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[i], false, 8, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[i], 6, 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + break; + + case 74: + for (int i = 0; i <= 1; i++) { + int oldIdx = _globals._sequenceIndexes[i]; + _scene->_sequences.remove(_globals._sequenceIndexes[i]); + _globals._sequenceIndexes[i] = _scene->_sequences.startCycle(_globals._spriteIndexes[i], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[i], oldIdx); + } + break; + + default: + break; + } +} + +void Scene319::actions() { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + handleRexDialogues(_action._activeAction._verbId); + } else { + if ((_action._activeAction._verbId == 0x165) || (_action._activeAction._verbId == 0x166)) { + if (_game._trigger == 1) { + _nextAction1 = 3; + _slacheTalkingFl = false; + _slacheMode = 1; + _slacheTopic = 2; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + handleSlacheDialogs(0x16B, 2, 9999999); + _dialog2.start(); + _game._player._stepEnabled = true; + } + } + + if ((_action._activeAction._verbId == 0x171) || (_action._activeAction._verbId == 0x172)) { + if (_game._trigger == 1) { + _nextAction1 = 2; + _slacheTalkingFl = false; + _slacheMode = 1; + _slacheTopic = 3; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + handleSlacheDialogs(0x177, 2, 9999999); + _dialog3.start(); + _game._player._stepEnabled = true; + } + } + + if ((_action._activeAction._verbId == 0x17D) || (_action._activeAction._verbId == 0x17E)) { + if (_game._trigger == 1) { + _nextAction1 = 3; + _slacheTalkingFl = false; + _slacheReady = false; + _slacheMode = 1; + _slacheTopic = 1; + } + + if (!_slacheTalkingFl) { + _scene->_sequences.addTimer(4, 2); + } else { + if (_game._trigger == 2) + handleSlacheDialogs(0x184, 2, 180); + + if (!_slacheReady) { + _scene->_sequences.addTimer(120, 3); + } else { + _globals[kRexHasMetSlache] = true; + _scene->_nextSceneId = 318; + } + } + } + + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x174) || + (_action._activeAction._verbId == 0x180) || (_action._activeAction._verbId == 0x169) || + (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x181) || + (_action._activeAction._verbId == 0x16A) || (_action._activeAction._verbId == 0x176) || + (_action._activeAction._verbId == 0x182) || (_action._activeAction._verbId == 0x183) || + (_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) || + (_action._activeAction._verbId == 0x17F)) { + + bool addDialogLine = !((_action._activeAction._verbId == 0x167) || (_action._activeAction._verbId == 0x173) || + (_action._activeAction._verbId == 0x17F) || (_action._activeAction._verbId == 0x16A) || + (_action._activeAction._verbId == 0x176) || (_action._activeAction._verbId == 0x182) || + (_action._activeAction._verbId == 0x183)); + + int addVerbId = _action._activeAction._verbId + 1; + if ((addVerbId == 0x182) && (_game._storyMode != STORYMODE_NAUGHTY)) + addVerbId = 0x183; + + if (_slacheMode == 1) { + if (_game._trigger == 1) { + _nextAction2 = _nextAction1; + _nextAction1 = 4; + } + + if (_nextAction1 != _nextAction2) { + _scene->_sequences.addTimer(4, 2); + } else { + Conversation *curDialog; + int nextDocQuote; + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x167)) { + curDialog = &_dialog1; + nextDocQuote = 0x161; + } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x1753)) { + nextDocQuote = 0x16D; + curDialog = &_dialog2; + } else { + nextDocQuote = 0x179; + curDialog = &_dialog3; + } + + handleSlacheDialogs(nextDocQuote, 2, 9999999); + if (addDialogLine) { + curDialog->write(_action._activeAction._verbId, false); + curDialog->write(addVerbId, true); + } + + curDialog->start(); + _game._player._stepEnabled = true; + _slacheMode = 2; + } + } else if (_slacheMode == 2) { + if (_game._trigger == 1) { + _nextAction2 = _nextAction1; + _nextAction1 = 5; + } + + if (_nextAction1 != _nextAction2) { + _scene->_sequences.addTimer(4, 2); + } else { + Conversation *curDialog; + int nextDocQuote; + if ((_action._activeAction._verbId == 0x168) || (_action._activeAction._verbId == 0x169) || (_action._activeAction._verbId == 0x167)) { + curDialog = &_dialog1; + nextDocQuote = 0x163; + } else if ((_action._activeAction._verbId == 0x174) || (_action._activeAction._verbId == 0x175) || (_action._activeAction._verbId == 0x173)) { + nextDocQuote = 0x16F; + curDialog = &_dialog2; + } else { + nextDocQuote = 0x17B; + curDialog = &_dialog3; + } + + handleSlacheDialogs(nextDocQuote, 2, 9999999); + if (addDialogLine) { + curDialog->write(_action._activeAction._verbId, false); + curDialog->write(addVerbId, true); + } + + curDialog->start(); + _game._player._stepEnabled = true; + _slacheMode = 3; + } + } else { + _nextAction2 = _nextAction1; + _nextAction1 = 6; + } + } + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene320::Scene320(MADSEngine *vm) : Scene300s(vm) { + _blinkFl = false; + _flippedFl = false; + + _buttonId = -1; + _lastFrame = -1; + _leftItemId = -1; + _posX = -1; + _rightItemId = -1; +} + +void Scene320::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_blinkFl); + s.syncAsByte(_flippedFl); + + s.syncAsSint32LE(_buttonId); + s.syncAsSint32LE(_lastFrame); + s.syncAsSint32LE(_leftItemId); + s.syncAsSint32LE(_posX); + s.syncAsSint32LE(_rightItemId); +} + +void Scene320::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene320::setRightView(int view) { + if (_rightItemId < 8) _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + int spriteNum; + switch (view) { + case 0: + spriteNum = 16; + break; + + case 1: + spriteNum = 14; + break; + + case 2: + spriteNum = 17; + break; + + case 3: + spriteNum = 15; + break; + + default: + spriteNum = view + 6; + break; + } + + if (view != 8) { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[spriteNum], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 0); + } + + _globals[kRightView320] = _rightItemId = view; +} + +void Scene320::setLeftView(int view) { + if (_leftItemId < 10) + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + + if (view != 10) { + _globals._sequenceIndexes[0] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[view], false, 6, 0, 0, 18); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 0); + if (!_blinkFl) + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[0], 2, 2); + } + + _leftItemId = view; +} + +void Scene320::handleButtons() { + switch(_action._activeAction._objectNameId) { + case 0x2DD: + _buttonId = 5; + break; + + case 0x2DE: + _buttonId = 4; + break; + + case 0x2E0: + _buttonId = 6; + break; + + case 0x2E1: + _buttonId = 7; + break; + + case 0x2E2: + _buttonId = 8; + break; + + case 0x2E3: + _buttonId = 9; + break; + + case 0x2E4: + _buttonId = 10; + break; + + case 0x2E5: + _buttonId = 11; + break; + + case 0x2E6: + _buttonId = 12; + break; + + case 0x2E7: + _buttonId = 13; + break; + + case 0x2E8: + _buttonId = 0; + break; + + case 0x2E9: + _buttonId = 1; + break; + + case 0x2EA: + _buttonId = 2; + break; + + case 0x2EB: + _buttonId = 3; + break; + + default: + break; + } + + if (_buttonId <= 3) { + _posX = (8 * _buttonId) - 2; + _flippedFl = true; + } else if (_buttonId <= 5) { + _posX = (13 * _buttonId) - 14; + _flippedFl = true; + } else { + _posX = (8 * _buttonId) + 98; + _flippedFl = false; + } +} + +void Scene320::enter() { + _blinkFl = true; + _rightItemId = 8; + _leftItemId = 10; + _lastFrame = 0; + + for (int i = 0; i < 10; i++) + _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('M', i)); + + for (int i = 0; i < 8; i++) + _globals._spriteIndexes[10 + i] = _scene->_sprites.addSprites(formAnimName('N', i)); + + _globals._spriteIndexes[18] = _scene->_sprites.addSprites("*REXHAND"); + _game._player._visible = false; + + setRightView(_globals[kRightView320]); + setLeftView(0); + + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 10); + + sceneEntrySound(); +} + +void Scene320::step() { + if (_scene->_activeAnimation != nullptr) { + if (_lastFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lastFrame = _scene->_activeAnimation->getCurrentFrame(); + switch (_lastFrame) { + case 95: + _blinkFl = true; + setLeftView(9); + _vm->_sound->command(41); + break; + + case 139: + _blinkFl = false; + setLeftView(9); + break; + + case 191: + _scene->_kernelMessages.add(Common::Point(1, 1), 0xFDFC, 0, 0, 60, _game.getQuote(0xFE)); + break; + + case 417: + case 457: + _vm->_screen._shakeCountdown = 40; + _vm->_sound->command(59); + break; + + case 430: + _blinkFl = true; + setLeftView(4); + break; + + default: + break; + } + } + } + + if (_game._trigger == 70) { + _globals[kAfterHavoc] = true; + _globals[kTeleporterRoom + 1] = 351; + _scene->_nextSceneId = 361; + } +} + +void Scene320::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(32011); + else if ((_action.isAction(VERB_PRESS) || _action.isAction(VERB_PUSH)) && + (_action.isObject(NOUN_LEFT_1_KEY) || _action.isObject(NOUN_LEFT_2_KEY) || _action.isObject(NOUN_LEFT_3_KEY) || _action.isObject(NOUN_LEFT_4_KEY) || + _action.isObject(NOUN_GREEN_BUTTON) || _action.isObject(NOUN_RED_BUTTON) || _action.isObject(NOUN_RIGHT_1_KEY) || _action.isObject(NOUN_RIGHT_2_KEY) || + _action.isObject(NOUN_RIGHT_3_KEY) || _action.isObject(NOUN_RIGHT_4_KEY) || _action.isObject(NOUN_RIGHT_5_KEY) || _action.isObject(NOUN_RIGHT_6_KEY) || + _action.isObject(NOUN_RIGHT_7_KEY) || _action.isObject(NOUN_RIGHT_8_KEY) + )) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + handleButtons(); + _globals._sequenceIndexes[18] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[18], _flippedFl, 4, 2, 0, 0); + _scene->_sequences.setScale(_globals._sequenceIndexes[18], 60); + _scene->_sequences.setPosition(_globals._sequenceIndexes[18], Common::Point(_posX, 170)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_LOOP, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[18], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_buttonId >= 6) { + _vm->_sound->command(60); + setRightView(_buttonId - 6); + } + if (_buttonId == 4) { + _vm->_sound->command(38); + if (_leftItemId == 3) + setLeftView(0); + else + setLeftView(3); + } + if (_buttonId == 5) { + _vm->_sound->command(38); + if (_leftItemId == 1) + setLeftView(2); + else + setLeftView(1); + } + if (_buttonId <= 3) { + _vm->_sound->command(60); + setLeftView(_buttonId + 5); + } + break; + + case 2: + _game._player._stepEnabled = true; + if (_buttonId == 5) { + if (_leftItemId == 2) { + _game._player._stepEnabled = false; + setRightView(8); + setLeftView(10); + _scene->_kernelMessages.reset(); + _scene->resetScene(); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 2)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('m', 4)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('m', 9)); + _blinkFl = false; + setLeftView(2); + _game.loadQuoteSet(0xFE, 0); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->loadAnimation(formAnimName('a', -1), 70); + _vm->_sound->command(17); + } + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_LEAVE, NOUN_SECURITY_STATION)) + _scene->_nextSceneId = 311; + else if (_action.isAction(VERB_LOOK, NOUN_RIGHT_MONITOR)) + _vm->_dialogs->show(32001); + else if (_action.isAction(VERB_LOOK, NOUN_LEFT_MONITOR)) + _vm->_dialogs->show(32002); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(32003); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_STATION)) + _vm->_dialogs->show(32004); + else if (_action.isAction(VERB_LOOK, NOUN_MUG)) + _vm->_dialogs->show(32005); + else if (_action.isAction(VERB_LOOK, NOUN_DOUGHNUT)) + _vm->_dialogs->show(32006); + else if (_action.isAction(VERB_LOOK, NOUN_MAGAZINE)) + _vm->_dialogs->show(32006); + else if (_action.isAction(VERB_LOOK, NOUN_PAPER_FOOTBALL)) + _vm->_dialogs->show(32008); + else if (_action.isAction(VERB_LOOK, NOUN_NEWSPAPER)) + _vm->_dialogs->show(32009); + else if (_action.isAction(VERB_LOOK, NOUN_CLIPBOARD)) + _vm->_dialogs->show(32010); + else if (_action.isAction(VERB_TAKE, NOUN_MUG)) + _vm->_dialogs->show(32012); + else if (_action.isAction(VERB_TAKE, NOUN_CLIPBOARD)) + _vm->_dialogs->show(32013); + else if (_action.isAction(VERB_TAKE, NOUN_DOUGHNUT) || _action.isAction(VERB_EAT, NOUN_DOUGHNUT)) + _vm->_dialogs->show(32014); + else if (_action.isAction(VERB_TAKE, NOUN_PAPER_FOOTBALL)) + _vm->_dialogs->show(32015); + else if (_action.isAction(VERB_TAKE, NOUN_MAGAZINE)) + _vm->_dialogs->show(32016); + else if (_action.isAction(VERB_TAKE, NOUN_NEWSPAPER)) + _vm->_dialogs->show(32017); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene321::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene321::enter() { + _game._player._visible = false; + _game._player._stepEnabled = false; + + _scene->_userInterface.emptyConversationList(); + _scene->_userInterface.setup(kInputConversation); + + int suffixNum; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals[kSexOfRex] = REX_MALE; + suffixNum = 1; + } else { + _globals[kSexOfRex] = REX_FEMALE; + suffixNum = _game._visitedScenes._sceneRevisited ? 2 : 0; + } + + _scene->loadAnimation(formAnimName('g', suffixNum), 60); + sceneEntrySound(); +} + +void Scene321::step() { + if (_scene->_activeAnimation != nullptr) { + if ((_scene->_activeAnimation->getCurrentFrame() >= 260) && (_globals[kSexOfRex] == REX_MALE) && (_game._storyMode >= STORYMODE_NICE)) + _scene->_nextSceneId = 316; + } + + if (_game._trigger == 60) + _scene->_nextSceneId = 316; +} + +/*------------------------------------------------------------------------*/ + +void Scene322::setup() { + _game._player._spritesPrefix = ""; + // The original is calling scene3xx_setAAName() + _game._aaName = Resources::formatAAName(4); +} + +void Scene322::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original is using scene3xx_sceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(10); +} + +void Scene322::step() { + teleporterStep(); +} + +void Scene322::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(32214); + _action._inProgress = false; + return; + } + + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(32210); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(32211); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(32212); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(32213); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(32214); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene351::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene351::enter() { + _globals[kAfterHavoc] = -1; + _globals[kTeleporterRoom + 1] = 351; + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXRD_7"); + + if (_game._objects.isInRoom(OBJ_CREDIT_CHIP)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4); + } else + _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false); + + if (_scene->_priorSceneId == 352) + _game._player._playerPos = Common::Point(148, 152); + else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(207, 81); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + char sepChar = 'a'; + if (_globals[kSexOfRex] != REX_MALE) + sepChar = 'b'; + + int suffixNum = -1; + int trigger = 0; + + switch (_globals[kTeleporterCommand]) { + case 1: + suffixNum = 0; + trigger = 60; + _globals[kTeleporterCommand] = true; + break; + + case 2: + suffixNum = 1; + trigger = 61; + break; + + case 3: + case 4: + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._turnToFacing = FACING_SOUTH; + suffixNum = -1; + break; + + default: + break; + } + + _globals[kTeleporterCommand] = 0; + + if (suffixNum >= 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger); + } + + sceneEntrySound(); +} + +void Scene351::step() { + if (_game._trigger == 60) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._turnToFacing = FACING_SOUTH; + } + + if (_game._trigger == 61) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } +} + +void Scene351::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35121); + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) + _scene->_nextSceneId = 322; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 352; + else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_hotspots.activate(NOUN_CREDIT_CHIP, false); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 0x32F); + break; + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _vm->_dialogs->show(35110); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35111); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(35112); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) { + if (_game._objects[0xF]._roomNumber == 351) + _vm->_dialogs->show(35114); + else + _vm->_dialogs->show(35113); + } else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT)) + _vm->_dialogs->show(35115); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(35116); + else if (_action.isAction(VERB_LOOK, NOUN_MACHINE)) + _vm->_dialogs->show(35117); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(35118); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(35119); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35120); + else if (_action.isAction(VERB_LOOK, NOUN_POLE)) + _vm->_dialogs->show(35122); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene352::Scene352(MADSEngine *vm) : Scene3xx(vm) { + _vaultOpenFl = false; + _mustPutArmDownFl = false; + _leaveRoomFl = false; + + _tapePlayerHotspotIdx = -1; + _hotspot1Idx = -1; + _hotspot2Idx = -1; + _lampHostpotIdx = -1; + _commonSequenceIdx = -1; + _commonSpriteIndex = -1; +} + +void Scene352::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsByte(_vaultOpenFl); + s.syncAsByte(_mustPutArmDownFl); + s.syncAsByte(_leaveRoomFl); + + s.syncAsSint32LE(_tapePlayerHotspotIdx); + s.syncAsSint32LE(_hotspot1Idx); + s.syncAsSint32LE(_hotspot2Idx); + s.syncAsSint32LE(_lampHostpotIdx); + s.syncAsSint32LE(_commonSequenceIdx); + s.syncAsSint32LE(_commonSpriteIndex); +} + +void Scene352::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_YOUR_STUFF); + _scene->addActiveVocab(NOUN_OTHER_STUFF); + _scene->addActiveVocab(NOUN_LAMP); +} + +void Scene352::putArmDown(bool corridorExit, bool doorwayExit) { + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0xFF)); + _scene->_sequences.addTimer(48, 1); + break; + + case 1: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 2: { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST); + _scene->changeVariant(0); + } + break; + + case 3: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x100)); + _game._objects.setRoom(OBJ_GUARDS_ARM, _scene->_currentSceneId); + _game._player._visible = true; + if (corridorExit) + _scene->_sequences.addTimer(48, 6); + else if (doorwayExit) + _scene->_sequences.addTimer(48, 4); + else { + _mustPutArmDownFl = false; + _game._player._stepEnabled = true; + } + break; + + case 4: + _game._player.walk(Common::Point(116, 107), FACING_NORTH); + _game._player._stepEnabled = true; + _mustPutArmDownFl = false; + _scene->_sequences.addTimer(180, 5); + _leaveRoomFl = true; + break; + + case 5: + if (_leaveRoomFl) + _scene->_nextSceneId = 351; + + break; + + case 6: + _game._player.walk(Common::Point(171, 152), FACING_SOUTH); + _game._player._stepEnabled = true; + _mustPutArmDownFl = false; + _scene->_sequences.addTimer(180, 7); + _leaveRoomFl = true; + break; + + case 7: + if (_leaveRoomFl) + _scene->_nextSceneId = 353; + + break; + + default: + break; + } +} + +void Scene352::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM302x0"); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites("*RM302x2"); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RM302x3"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', -1)); + + + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXRC_6"); + _globals._spriteIndexes[15] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('a', 2)); + } else { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRD_7"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXRC_6"); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('a', 0)); + } + + _leaveRoomFl = false; + + if (_game._objects.isInRoom(OBJ_TAPE_PLAYER)) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 5); + int idx = _scene->_dynamicHotspots.add(NOUN_TAPE_PLAYER, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _tapePlayerHotspotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(84, 145), FACING_WEST); + } + + _vaultOpenFl = false; + + if (_scene->_priorSceneId != -2) { + _mustPutArmDownFl = false; + if (!_game._visitedScenes._sceneRevisited) + _globals[kHaveYourStuff] = false; + } + + if (_game._objects.isInRoom(OBJ_GUARDS_ARM)) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_GUARDS_ARM, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(230, 117), FACING_NORTHWEST); + } else + _mustPutArmDownFl = true; + + if (_scene->_priorSceneId == 353) + _game._player._playerPos = Common::Point(171, 155); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(116, 107); + + sceneEntrySound(); + + _game.loadQuoteSet(0xFF, 0x100, 0x101, 0x102, 0x103, 0); +} + +void Scene352::preActions() { + _leaveRoomFl = false; + + if (_action.isAction(VERB_OPEN, NOUN_VAULT)) + _game._player.walk(Common::Point(266, 111), FACING_NORTHEAST); + + if (_vaultOpenFl && !_action.isObject(NOUN_VAULT) && !_action.isObject(NOUN_LAMP) && !_action.isObject(NOUN_OTHER_STUFF) && !_action.isObject(NOUN_YOUR_STUFF)) { + if (_globals[kHaveYourStuff]) { + _commonSpriteIndex = _globals._spriteIndexes[13]; + _commonSequenceIdx = _globals._sequenceIndexes[13]; + } else { + _commonSpriteIndex = _globals._spriteIndexes[1]; + _commonSequenceIdx = _globals._sequenceIndexes[1]; + } + + switch (_game._trigger) { + case 0: + if (_game._player._needToWalk) { + _game._player._stepEnabled = false; + _scene->_sequences.remove(_commonSequenceIdx); + _vm->_sound->command(20); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + } + break; + + case 1: + if (!_globals[kHaveYourStuff]) + _scene->_dynamicHotspots.remove(_hotspot2Idx); + + _scene->_dynamicHotspots.remove(_hotspot1Idx); + _scene->_dynamicHotspots.remove(_lampHostpotIdx); + _vaultOpenFl = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + + if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_SCANNER)) { + if (_globals[kSexOfRex] == REX_MALE) + _game._player.walk(Common::Point(269, 111), FACING_NORTHEAST); + else + _game._player.walk(Common::Point(271, 111), FACING_NORTHEAST); + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_FLOOR)) { + if (_game._objects.isInInventory(OBJ_GUARDS_ARM)) + _game._player.walk(Common::Point(230, 117), FACING_NORTHWEST); + } +} + +void Scene352::actions() { + if (_action._lookFlag) { + _vm->_dialogs->show(35225); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_OPEN, NOUN_VAULT)) { + if (!_vaultOpenFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) + _commonSpriteIndex = _globals._spriteIndexes[9]; + else + _commonSpriteIndex = _globals._spriteIndexes[8]; + + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.updateTimeout(_commonSequenceIdx, -1); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + _vm->_sound->command(21); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], FACING_NORTH); + int oldIdx = _commonSequenceIdx; + _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); + _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _vm->_sound->command(22); + _scene->_sequences.remove(_commonSequenceIdx); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 3); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _commonSequenceIdx); + _game._player._visible = true; + _scene->_sequences.addTimer(60, 4); + break; + + case 4: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x101)); + _game._player._stepEnabled = true; + break; + } + } + _action._inProgress = false; + return; + } + + if (_game._objects.isInInventory(OBJ_GUARDS_ARM)) { + _mustPutArmDownFl = true; + } + + bool exit_corridor = false; + bool exit_doorway = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) { + exit_corridor = true; + } + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) { + exit_doorway = true; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) || _action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY) || _action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_FLOOR)) { + if (_mustPutArmDownFl) + putArmDown(exit_corridor, exit_doorway); + else if (exit_corridor) + _scene->_nextSceneId = 353; + else + _scene->_nextSceneId = 351; + + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_GUARDS_ARM)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_GUARDS_ARM)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_GUARDS_ARM); + _scene->changeVariant(1); + break; + + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_GUARDS_ARM, 0x899C); + break; + } + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_PUT, NOUN_GUARDS_ARM, NOUN_SCANNER)) { + if (!_vaultOpenFl) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_FEMALE) + _commonSpriteIndex = _globals._spriteIndexes[11]; + else + _commonSpriteIndex = _globals._spriteIndexes[10]; + + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.updateTimeout(_commonSequenceIdx, -1); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + _vm->_sound->command(21); + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 7, 2, 20, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + int oldIdx = _commonSequenceIdx; + _commonSequenceIdx = _scene->_sequences.startCycle(_commonSpriteIndex, false, -2); + _scene->_sequences.updateTimeout(_commonSequenceIdx, oldIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _vm->_sound->command(23); + _scene->_sequences.remove(_commonSequenceIdx); + _commonSequenceIdx = _scene->_sequences.startReverseCycle(_commonSpriteIndex, false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, 1, 4); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + + case 3: + _scene->_sequences.updateTimeout(-1, _commonSequenceIdx); + _game._player._visible = true; + if (_globals[kHaveYourStuff]) + _commonSpriteIndex = _globals._spriteIndexes[13]; + else + _commonSpriteIndex = _globals._spriteIndexes[1]; + + _vm->_sound->command(20); + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + _scene->_sequences.addSubEntry(_commonSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _commonSequenceIdx = _scene->_sequences.addSpriteCycle(_commonSpriteIndex, false, 6, 0, 0, 0); + _scene->_sequences.setAnimRange(_commonSequenceIdx, -2, -2); + _scene->_sequences.setDepth(_commonSequenceIdx, 15); + _scene->_sequences.addTimer(60, 5); + break; + + case 5: { + _vaultOpenFl = true; + int idx; + if (!_globals[kHaveYourStuff]) { + idx = _scene->_dynamicHotspots.add(NOUN_YOUR_STUFF, VERB_WALKTO, -1, Common::Rect(282, 87, 282 + 13, 87 + 7)); + _hotspot2Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(280, 111), FACING_NORTHEAST); + _globals._sequenceIndexes[1] = _commonSequenceIdx; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x102)); + } else { + _globals._sequenceIndexes[13] = _commonSequenceIdx; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x103)); + } + + idx = _scene->_dynamicHotspots.add(NOUN_OTHER_STUFF, VERB_WALKTO, -1, Common::Rect(282, 48, 282 + 36, 48 + 27)); + _hotspot1Idx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST); + idx = _scene->_dynamicHotspots.add(NOUN_LAMP, VERB_WALKTO, -1, Common::Rect(296, 76, 296 + 11, 76 + 17)); + _lampHostpotIdx = _scene->_dynamicHotspots.setPosition(idx, Common::Point(287, 115), FACING_NORTHEAST); + _game._player._stepEnabled = true; + } + break; + } + } + } else if (_action.isAction(VERB_TAKE, NOUN_YOUR_STUFF)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[14] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[14], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[14], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[14]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[14], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[15] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[15], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[15], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[15]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[15], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_dynamicHotspots.remove(_hotspot2Idx); + _globals[kHaveYourStuff] = true; + + for (uint16 i = 0; i < _game._objects.size(); i++) { + if (_game._objects[i]._roomNumber == 50) + _game._objects.addToInventory(i); + } + + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 15); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[14]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[15]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TAPE_PLAYER) && !_game._objects.isInInventory(OBJ_TAPE_PLAYER)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[7]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->_dynamicHotspots.remove(_tapePlayerHotspotIdx); + break; + + case 2: + _game._objects.addToInventory(OBJ_TAPE_PLAYER); + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[7]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_TAPE_PLAYER, 0x899B); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) + _vm->_dialogs->show(35210); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) { + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(35211); + else + _vm->_dialogs->show(35212); + } else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(35213); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(35214); + else if (_action.isAction(VERB_LOOK, NOUN_TAPE_PLAYER) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(35215); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35216); + else if (_action.isAction(VERB_LOOK, NOUN_GUARDS_ARM) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(35217); + else if (_action.isAction(VERB_LOOK, NOUN_IRONING_BOARD)) + _vm->_dialogs->show(35218); + else if (_action.isAction(VERB_LOOK, NOUN_CLOCK)) + _vm->_dialogs->show(35219); + else if (_action.isAction(VERB_LOOK, NOUN_GAUGE)) + _vm->_dialogs->show(35220); + else if (_action.isAction(VERB_LOOK, NOUN_VAULT)) { + if (!_vaultOpenFl) + _vm->_dialogs->show(35221); + } else if (_action.isAction(VERB_LOOK, NOUN_YOUR_STUFF)) + _vm->_dialogs->show(35222); + else if (_action.isAction(VERB_LOOK, NOUN_OTHER_STUFF)) + _vm->_dialogs->show(35223); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35224); + else if (_action.isAction(VERB_TAKE, NOUN_OTHER_STUFF)) + _vm->_dialogs->show(35226); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(35229); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) + _vm->_dialogs->show(35230); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(35231); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(35232); + else if (_action.isAction(VERB_LOOK, NOUN_PROJECTOR)) + _vm->_dialogs->show(35233); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(35234); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_MONITOR)) + _vm->_dialogs->show(35235); + else + return; +} + +/*------------------------------------------------------------------------*/ + +void Scene353::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene353::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(303, 'B', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 5, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if (_scene->_priorSceneId == 352) + _game._player._playerPos = Common::Point(144, 95); + else + _game._player._playerPos = Common::Point(139, 155); + + sceneEntrySound(); +} + +void Scene353::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35315); + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 352; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 354; + else if (_action.isAction(VERB_LOOK, NOUN_ROCK_CHUNK)) + _vm->_dialogs->show(35310); + else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(35311); + else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_BEAM)) + _vm->_dialogs->show(35312); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(35313); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35314); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(35316); + else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) + _vm->_dialogs->show(35317); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35318); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene354::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene354::enter() { + _globals[kAfterHavoc] = true; + _globals[kTeleporterRoom + 1] = 351; + + if (_scene->_priorSceneId == 361) + _game._player._playerPos = Common::Point(231, 110); + else if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(106, 152); + _game._player._facing = FACING_NORTH; + } else if (_scene->_priorSceneId == 316) + _game._player._playerPos = Common::Point(71, 107); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(167, 57); + + sceneEntrySound(); +} + +void Scene354::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _game._player._walkOffScreenSceneId = 401; +} + +void Scene354::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35414); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.startWalking(Common::Point(208, 0), FACING_NORTHEAST); + _game._player._walkOffScreenSceneId = 353; + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _scene->_nextSceneId = 361; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _scene->_nextSceneId = 316; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 401; + else if (_action.isAction(VERB_LOOK, NOUN_CONTROLS)) + _vm->_dialogs->show(35410); + else if (_action.isAction(VERB_LOOK, NOUN_SIGNAL)) + _vm->_dialogs->show(35411); + else if (_action.isAction(VERB_LOOK, NOUN_CATWALK)) + _vm->_dialogs->show(35412); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_DUCT)) + _vm->_dialogs->show(35413); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(35415); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(35416); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35417); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35418); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(35419); + else if (_action.isAction(VERB_LOOK, NOUN_GUARD)) + _vm->_dialogs->show(35420); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene357::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene357::enter() { + _globals[kAfterHavoc] = true; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 318) + _game._player._playerPos = Common::Point(298, 142); + else if (_scene->_priorSceneId == 313) + _game._player._playerPos = Common::Point(127, 101); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(15, 148); + + sceneEntrySound(); +} + +void Scene357::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 318; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 358; +} + +void Scene357::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35715); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35710); + else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) + _vm->_dialogs->show(35711); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35712); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35713); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35714); + else if (_action.isAction(VERB_LOOK, NOUN_CELL_WALL)) + _vm->_dialogs->show(35716); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(35717); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35718); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(35719); + else if (_action.isAction(VERB_TAKE, NOUN_DEBRIS)) + _vm->_dialogs->show(35720); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35721); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35722); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35723); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene358::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene358::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 357) + _game._player._playerPos = Common::Point(305, 142); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(12, 141); + + sceneEntrySound(); +} + +void Scene358::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 357; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 359; +} + +void Scene358::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(35815); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35810); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35811); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35812); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35813); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35814); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(35816); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(35817); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene359::Scene359(MADSEngine *vm) : Scene3xx(vm) { + _cardHotspotId = -1; +} + +void Scene359::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsSint32LE(_cardHotspotId); +} + +void Scene359::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene359::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2"); + else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXBD_2"); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + + if (_game._objects.isInRoom(OBJ_SECURITY_CARD)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _cardHotspotId = _scene->_dynamicHotspots.add(NOUN_SECURITY_CARD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_cardHotspotId, Common::Point(107, 107), FACING_SOUTH); + } + + if (_scene->_priorSceneId == 358) + _game._player._playerPos = Common::Point(301, 141); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(15, 148); + + sceneEntrySound(); +} + +void Scene359::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 358; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 360; +} + +void Scene359::actions() { + if (_action._lookFlag) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35914); + else + _vm->_dialogs->show(35915); + } else if (_action.isAction(VERB_TAKE, NOUN_SECURITY_CARD)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_SECURITY_CARD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_dialogs->show(35920); + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], true, 7, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(106, 110)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 6, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_cardHotspotId); + _vm->_sound->command(57); + _game._objects.addToInventory(OBJ_SECURITY_CARD); + _vm->_dialogs->showItem(OBJ_SECURITY_CARD, 0x330); + _scene->changeVariant(1); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_BLOODY_CELL_WALL)) + _vm->_dialogs->show(35910); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(35911); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(35912); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(35913); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(35916); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(35917); + else if (_action.isAction(VERB_LOOK, NOUN_LIMB)) + _vm->_dialogs->show(35918); + else if (_action.isAction(VERB_TAKE, NOUN_LIMB)) + _vm->_dialogs->show(35919); + else if (_action.isAction(VERB_LOOK, NOUN_SECURITY_CARD) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(35921); + else if (_action.isAction(VERB_LOOK, NOUN_BLOOD_STAIN)) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35922); + else + _vm->_dialogs->show(35923); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL_BOARD)) + _vm->_dialogs->show(35924); + else if (_action.isAction(VERB_TAKE, NOUN_WALL_BOARD)) + _vm->_dialogs->show(35925); + else if (_action.isAction(VERB_LOOK, NOUN_RIP_IN_FLOOR)) + _vm->_dialogs->show(35926); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR)) + _vm->_dialogs->show(35927); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(35928); + else + _vm->_dialogs->show(35929); + } else if (_action.isAction(VERB_OPEN, NOUN_AIR_VENT) || _action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36016); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene360::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene360::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(127, 78)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 359) + _game._player._playerPos = Common::Point(304, 143); + else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(13, 141); + + sceneEntrySound(); +} + +void Scene360::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 359; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 361; +} + +void Scene360::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(36015); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(36010); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(36011); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(36012); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(36013); + else if (_action.isAction(VERB_LOOK, NOUN_TOILET)) + _vm->_dialogs->show(36014); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36016); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR)) + _vm->_dialogs->show(36017); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(36018); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene361::setup() { + if (_scene->_currentSceneId == 391) + _globals[kSexOfRex] = REX_MALE; + + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene361::handleRexAction() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 50, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 3, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int seqIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], seqIdx); + } + break; + + case 2: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 4, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(15, 4); + } + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 12, 14); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + break; + + case 5: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(15, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[2]); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene361::handleRoxAction() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 18, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: { + int tmpIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], tmpIdx); + } + break; + + case 2: { + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + } + break; + + case 3: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 9, 10); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } + break; + + case 4: { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 11, 15); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + break; + + case 5: { + int tmpIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 16); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(167, 100)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], tmpIdx); + _scene->_sequences.addTimer(48, 6); + } + break; + + case 6: + _scene->_sequences.setDone(_globals._sequenceIndexes[4]); + + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addTimer(48, 7); + break; + + case 7: + _scene->_nextSceneId = 313; + break; + + default: + break; + } +} + +void Scene361::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(Resources::formatName(307, 'X', 0, EXT_SS, "")); + + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXCL_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCL_2"); + } else + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*ROXCL_8"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + if (_scene->_priorSceneId == 391) { + _globals[kSexOfRex] = REX_MALE; + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._player._facing = FACING_SOUTH; + _game._player._playerPos = Common::Point(166, 101); + _scene->_sequences.addTimer(120, 70); + } else if (_scene->_priorSceneId == 360) + _game._player._playerPos = Common::Point(302, 145); + else if (_scene->_priorSceneId == 320) { + _game._player._playerPos = Common::Point(129, 113); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(13, 145); + + _game.loadQuoteSet(0xFB, 0xFC, 0); + + if (_scene->_priorSceneId == 320) + _scene->_kernelMessages.setQuoted(_scene->_kernelMessages.addQuote(0xFB, 0, 0x78), 4, true); + + sceneEntrySound(); +} + +void Scene361::step() { + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 71); + break; + + case 71: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 72); + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 3); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 73); + break; + + case 73: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 74); + break; + + case 74: { + int seqIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 6); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], seqIdx); + _scene->_sequences.addTimer(15, 75); + } + break; + + case 75: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 76); + break; + + case 76: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 8); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 77); + break; + + case 77: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(165, 76)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 15); + + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 9); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 78); + break; + + case 78: + _scene->_sequences.setDone(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 10, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 79); + break; + + case 79: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._stepEnabled = true; + _game._player._visible = true; + break; + + default: + break; + } + } +} + +void Scene361::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 360; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 354; +} + +void Scene361::actions() { + if (_action._lookFlag) + _vm->_dialogs->show(36119); + else if (_action.isAction(VERB_SIT_AT, NOUN_DESK)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.addQuote(0xFC, 120, 0); + } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_AIR_VENT)) { + if (_globals[kSexOfRex] == REX_FEMALE) + handleRoxAction(); + else + handleRexAction(); + } else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(36110); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(36111); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTING_FIXTURE) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTING_FIXTURE)) + _vm->_dialogs->show(36112); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHTS) || _action.isAction(VERB_STARE_AT, NOUN_LIGHTS)) + _vm->_dialogs->show(36113); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHTS)) + _vm->_dialogs->show(36114); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT_BULB) || _action.isAction(VERB_STARE_AT, NOUN_LIGHT_BULB)) + _vm->_dialogs->show(36115); + else if (_action.isAction(VERB_TAKE, NOUN_LIGHT_BULB)) + _vm->_dialogs->show(36116); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(36117); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(36118); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_VENT)) + _vm->_dialogs->show(36120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene366::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene366::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene366::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 302; + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_game._visitedScenes.exists(316)) + _vm->_dialogs->show(36612); + else + _vm->_dialogs->show(36613); + _scene->_nextSceneId = 316; + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_game._visitedScenes.exists(321)) + _vm->_dialogs->show(36611); + else + _vm->_dialogs->show(36610); + } else { + return; + } + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene387::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene387::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + + sceneEntrySound(); +} + +void Scene387::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) + _vm->_dialogs->show(38710); + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(38711); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene388::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene388::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if (_globals[kAfterHavoc]) + _scene->_hotspots.activate(NOUN_SAUROPOD, false); + else { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + } + + _game._player._visible = false; + _vm->_palette->setEntry(252, 63, 30, 20); + _vm->_palette->setEntry(253, 45, 15, 12); + _game.loadQuoteSet(0x154, 0x155, 0x156, 0x157, 0x158, 0); + + sceneEntrySound(); +} + +void Scene388::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_TALKTO, NOUN_SAUROPOD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(0x154)); + break; + + case 1: + _scene->_kernelMessages.add(Common::Point(82, 38), 0xFDFC, 0, 0, 300, _game.getQuote(0x156)); + _scene->_kernelMessages.add(Common::Point(82, 52), 0xFDFC, 0, 0, 300, _game.getQuote(0x157)); + _scene->_kernelMessages.add(Common::Point(82, 66), 0xFDFC, 0, 2, 300, _game.getQuote(0x158)); + break; + + case 2: + _game._player._stepEnabled = true; + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 0, 120, _game.getQuote(0x155)); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38811); + else + _vm->_dialogs->show(38810); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(38812); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene389::Scene389(MADSEngine *vm) : Scene300s(vm) { + _monsterTime = 0; + _circularQuoteId = -1; +} + +void Scene389::synchronize(Common::Serializer &s) { + Scene3xx::synchronize(s); + + s.syncAsUint32LE(_monsterTime); + s.syncAsSint32LE(_circularQuoteId); +} + +void Scene389::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene389::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _monsterTime = 0; + _circularQuoteId = 0x159; + + if (_globals[kAfterHavoc]) + _scene->_hotspots.activate(NOUN_MONSTER, false); + else { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0], false, 6, 0, 0, 0); + _scene->_kernelMessages.initRandomMessages(1, + Common::Rect(88, 19, 177, 77), 13, 2, 0xFDFC, 60, + 247, 248, 249, 0); + } + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _game._player._visible = false; + _game.loadQuoteSet(0xF7, 0xF8, 0xF9, 0x159, 0x15A, 0x15B, 0); + + sceneEntrySound(); +} + +void Scene389::step() { + _scene->_kernelMessages.randomServer(); + if (_scene->_frameStartTime >= _monsterTime) { + int chanceMinor = _scene->_kernelMessages.checkRandom() * 4 + 1; + _scene->_kernelMessages.generateRandom(20, chanceMinor); + _monsterTime = _scene->_frameStartTime + 2; + } +} + +void Scene389::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_TALKTO, NOUN_MONSTER)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(160, 136), 0x1110, 32, 1, 120, _game.getQuote(_circularQuoteId)); + _circularQuoteId++; + if (_circularQuoteId > 0x15B) + _circularQuoteId = 0x159; + + break; + + case 1: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(38911); + else + _vm->_dialogs->show(38912); + } else + _vm->_dialogs->show(38910); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38914); + else + _vm->_dialogs->show(38913); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene390::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene390::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + + sceneEntrySound(); +} + +void Scene390::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) + _vm->_dialogs->show(39010); + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) + _vm->_dialogs->show(39011); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene391::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene391::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene391::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kKickedIn391Grate]) + _vm->_dialogs->show(39113); + else { + _vm->_dialogs->show(39112); + _globals[kKickedIn391Grate] = true; + } + + if (_globals[kAfterHavoc]) + _scene->_nextSceneId = 361; + else + _scene->_nextSceneId = 311; + } else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(39111); + else + _vm->_dialogs->show(39110); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene399::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene399::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + sceneEntrySound(); +} + +void Scene399::actions() { + if (_action.isAction(VERB_RETURN_TO, NOUN_AIR_SHAFT)) + _scene->_nextSceneId = 313; + else if (_action.isAction(VERB_LOOK_THROUGH, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) { + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_SECURITY_CARD]._roomNumber == 359)) + _vm->_dialogs->show(38911); + else + _vm->_dialogs->show(38912); + } else + _vm->_dialogs->show(38910); + } else if (_action.isAction(VERB_OPEN, NOUN_GRATE)) { + if (_globals[kAfterHavoc]) + _vm->_dialogs->show(38914); + else + _vm->_dialogs->show(38913); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes3.h b/engines/mads/nebular/nebular_scenes3.h new file mode 100644 index 0000000000..9efd38e9a4 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes3.h @@ -0,0 +1,548 @@ +/* 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 MADS_NEBULAR_SCENES3_H +#define MADS_NEBULAR_SCENES3_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +typedef struct { + bool _flag; + int _vertical; + int _horizontal; + int _seqId[40]; + uint32 _timer; + + void init() { + _flag = false; + _vertical = _horizontal = -1; + _timer = 0; + for (int i = 0; i < 40; ++i) + _seqId[i] = -1; + } + + void synchronize(Common::Serializer &s) { + s.syncAsByte(_flag); + s.syncAsSint32LE(_vertical); + s.syncAsSint32LE(_horizontal); + for (int i = 0; i < 40; ++i) + s.syncAsSint32LE(_seqId[i]); + s.syncAsUint32LE(_timer); + }; +} ForceField; + +class Scene3xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + + void initForceField(ForceField *force, bool flag); + void handleForceField(ForceField *force, int *sprites); + int computeScale(int low, int high, int id); + +public: + Scene3xx(MADSEngine *vm) : NebularScene(vm) {} + + virtual void actions() {} +}; + +class Scene300s : public Scene3xx { +public: + Scene300s(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void preActions(); +}; + +class Scene301 : public Scene3xx { +public: + Scene301(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene302 : public Scene3xx { +private: + int _oldFrame; + +public: + Scene302(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene303 : public Scene3xx { +public: + Scene303(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene304 : public Scene3xx { +private: + int _explosionSpriteId; + +public: + Scene304(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene307 : public Scene3xx { +private: + ForceField _forceField; + + bool _afterPeeingFl; + bool _duringPeeingFl; + bool _grateOpenedFl; + bool _activePrisonerFl; + + int _animationMode; + int _prisonerMessageId; + int _fieldCollisionCounter; + + uint32 _lastFrameTime; + uint32 _guardTime; + uint32 _prisonerTimer; + + Common::String _subQuote2; + + Conversation _dialog1, _dialog2; + + void handleDialog(); + void handleRexDialog(int quote); + void handlePrisonerDialog(); + void handlePrisonerEncounter(); + void setDialogNode(int node); + void handlePrisonerSpeech(int firstQuoteId, int number, long timeout); + +public: + Scene307(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene308 : public Scene3xx { +private: + ForceField _forceField; + +public: + Scene308(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene309 : public Scene3xx { +private: + ForceField _forceField; + int _characterSpriteIndexes[3]; + int _messagesIndexes[3]; + int _lastFrame; + +public: + Scene309(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene310 : public Scene3xx { +private: + ForceField _forceField; + +public: + Scene310(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene311 : public Scene3xx { +private: + bool _checkGuardFl; + +public: + Scene311(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene313 : public Scene3xx { +public: + Scene313(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene316 : public Scene3xx { +private: + void handleRexInGrate(); + void handleRoxInGrate(); + +public: + Scene316(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene318 : public Scene3xx { +private: + uint32 _dropTimer; + + int _lastFrame; + int _animMode; + int _internCounter; + int _counter; + + bool _dialogFl; + bool _internTalkingFl; + bool _internWalkingFl; + bool _internVisibleFl; + bool _explosionFl; + + uint32 _lastFrameCounter; + + Common::String _subQuote2; + + Conversation _dialog1; + + void handleDialog(); + void handleRexDialogs(int quote); + void handleInternDialog(int quoteId, int quoteNum, uint32 timeout); + +public: + Scene318(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene319 : public Scene3xx { +private: + Conversation _dialog1, _dialog2, _dialog3; + + int _animMode, _animFrame; + int _nextAction1, _nextAction2; + int _slacheMode; + int _slacheTopic; + int _slachePosY; + + bool _slacheTalkingFl; + bool _slacheReady; + bool _slacheInitFl; + + Common::String _subQuote2; + + void handleRexDialogues(int quote); + void handleSlacheDialogs(int quoteId, int counter, uint32 timer); +public: + Scene319(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene320 : public Scene300s { +private: + void setRightView(int view); + void setLeftView(int view); + void handleButtons(); + + bool _blinkFl; + bool _flippedFl; + + int _buttonId; + int _lastFrame; + int _leftItemId; + int _posX; + int _rightItemId; + +public: + Scene320(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene321 : public Scene3xx { +public: + Scene321(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); +}; + +class Scene322 : public SceneTeleporter { +public: + Scene322(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene351 : public Scene3xx { +public: + Scene351(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene352 : public Scene3xx { +private: + bool _vaultOpenFl; + bool _mustPutArmDownFl; + bool _leaveRoomFl; + + int _tapePlayerHotspotIdx; + int _hotspot1Idx; + int _hotspot2Idx; + int _lampHostpotIdx; + int _commonSequenceIdx; + int _commonSpriteIndex; + + void putArmDown(bool corridorExit, bool doorwayExit); + +public: + Scene352(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene353 : public Scene3xx { +public: + Scene353(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene354 : public Scene3xx { +public: + Scene354(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene357 : public Scene3xx { +public: + Scene357(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene358 : public Scene3xx { +public: + Scene358(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene359 : public Scene3xx { +private: + int _cardHotspotId; + +public: + Scene359(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene360 : public Scene3xx { +public: + Scene360(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene361 : public Scene3xx { +private: + void handleRexAction(); + void handleRoxAction(); + +public: + Scene361(MADSEngine *vm) : Scene3xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene366 : public Scene300s { +public: + Scene366(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene387 : public Scene300s { +public: + Scene387(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene388 : public Scene300s { +public: + Scene388(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene389 : public Scene300s { +private: + uint32 _monsterTime; + + int _circularQuoteId; + +public: + Scene389(MADSEngine *vm); + virtual void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene390 : public Scene300s { +public: + Scene390(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene391 : public Scene300s { +public: + Scene391(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene399 : public Scene300s { +public: + Scene399(MADSEngine *vm) : Scene300s(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES3_H */ diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp new file mode 100644 index 0000000000..d114232255 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes4.cpp @@ -0,0 +1,4191 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes4.h" + +namespace MADS { + +namespace Nebular { + +void Scene4xx::setAAName() { + _game._aaName = Resources::formatAAName(4); +} + +void Scene4xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 403) || (_scene->_nextSceneId == 409)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_FEMALE) + _game._player._spritesPrefix = "ROX"; + else + _game._player._spritesPrefix = "RXM"; + + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene4xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 401: + _vm->_sound->startQueuedCommands(); + if (_scene->_priorSceneId == 402) + _vm->_sound->command(12, 64); + else + _vm->_sound->command(12, 1); + break; + + case 402: + _vm->_sound->startQueuedCommands(); + _vm->_sound->command(12, 127); + break; + + case 405: + case 407: + case 409: + case 410: + case 413: + _vm->_sound->command(10); + break; + + case 408: + _vm->_sound->command(52); + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene401::Scene401(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) { + _northFl = false; + _timer = 0; +} + +void Scene401::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_northFl); + s.syncAsSint16LE(_destPos.x); + s.syncAsSint16LE(_destPos.y); + s.syncAsUint32LE(_timer); +} + +void Scene401::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene401::enter() { + if (_scene->_priorSceneId != -2) + _northFl = false; + + _timer = 0; + + if (_scene->_priorSceneId == 402) { + _game._player._playerPos = Common::Point(203, 115); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 354) { + _game._player._playerPos = Common::Point(149, 90); + _game._player._facing = FACING_SOUTH; + _northFl = true; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(142, 131); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x1D4, 0); + sceneEntrySound(); +} + +void Scene401::step() { + if (_game._trigger == 70) { + _scene->_nextSceneId = 354; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 80) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._stepEnabled = true; + _game._player._visible = true; + _northFl = false; + _game._player.walk(Common::Point(149, 110), FACING_SOUTH); + } + + if (_scene->_frameStartTime >= _timer) { + int dist = 64 - ((_vm->hypotenuse(_game._player._playerPos.x - 219, _game._player._playerPos.y - 115) * 64) / 120); + + if (dist > 64) + dist = 64; + else if (dist < 1) + dist = 1; + + _vm->_sound->command(12, dist); + _timer = _scene->_frameStartTime + _game._player._ticksAmount; + } + +} + +void Scene401::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.walk(Common::Point(149, 89), FACING_NORTH); + _northFl = false; + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_northFl) + _game._player._walkOffScreenSceneId = 405; + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_game._player._needToWalk && _northFl) { + if (_globals[kSexOfRex] == REX_MALE) + _destPos = Common::Point(148, 94); + else + _destPos = Common::Point(149, 99); + + _game._player.walk(_destPos, FACING_SOUTH); + } +} + +void Scene401::actions() { + if ((_game._player._playerPos == _destPos) && _northFl) { + if (_globals[kSexOfRex] == REX_MALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 1), 70); + _globals[kHasBeenScanned] = true; + _vm->_sound->command(22); + int idx = _scene->_kernelMessages.add(Common::Point(153, 46), 0x1110, 32, 0, 60, _game.getQuote(0x1D4)); + _scene->_kernelMessages.setQuoted(idx, 4, true); + } + + if (_globals[kSexOfRex] == REX_FEMALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 2), 80); + _vm->_sound->command(23); + _globals[kHasBeenScanned] = true; + } + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_BAR)) { + if (!_northFl) + _scene->_nextSceneId = 402; + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) + _scene->_nextSceneId = 354; + else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) { + if (_globals[kHasBeenScanned]) + _vm->_dialogs->show(40111); + else + _vm->_dialogs->show(40110); + } else if (_action.isAction(VERB_LOOK, NOUN_BAR)) + _vm->_dialogs->show(40112); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40113); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40114); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(40115); + else if (_action._lookFlag) + _vm->_dialogs->show(40116); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene402::Scene402(MADSEngine *vm) : Scene4xx(vm) { + _lightOn = false; + _blowingSmoke = false; + _leftWomanMoving = false; + _rightWomanMoving = false; + _firstTalkToGirlInChair = false; + _waitingGinnyMove = false; + _ginnyLooking = false; + _bigBeatFl = false; + _roxOnStool = false; + _bartenderSteady = false; + _bartenderHandsHips = false; + _bartenderLooksLeft = false; + _bartenderReady = false; + _bartenderTalking = false; + _bartenderCalled = false; + _conversationFl = false; + _activeTeleporter = false; + _activeArrows = false; + _activeArrow1 = false; + _activeArrow2 = false; + _activeArrow3 = false; + _cutSceneReady = false; + _cutSceneNeeded = false; + _helgaReady = false; + _refuseAlienLiquor = false; + + _drinkTimer = -1; + _beatCounter = -1; + _bartenderMode = -1; + _bartenderDialogNode = -1; + _bartenderCurrentQuestion = -1; + _helgaTalkMode = -1; + _roxMode = -1; + _rexMode = -1; + _talkTimer = -1; +} + +void Scene402::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_lightOn); + s.syncAsByte(_blowingSmoke); + s.syncAsByte(_leftWomanMoving); + s.syncAsByte(_rightWomanMoving); + s.syncAsByte(_firstTalkToGirlInChair); + s.syncAsByte(_waitingGinnyMove); + s.syncAsByte(_ginnyLooking); + s.syncAsByte(_bigBeatFl); + s.syncAsByte(_roxOnStool); + s.syncAsByte(_bartenderSteady); + s.syncAsByte(_bartenderHandsHips); + s.syncAsByte(_bartenderLooksLeft); + s.syncAsByte(_bartenderReady); + s.syncAsByte(_bartenderTalking); + s.syncAsByte(_bartenderCalled); + s.syncAsByte(_conversationFl); + s.syncAsByte(_activeTeleporter); + s.syncAsByte(_activeArrows); + s.syncAsByte(_activeArrow1); + s.syncAsByte(_activeArrow2); + s.syncAsByte(_activeArrow3); + s.syncAsByte(_cutSceneReady); + s.syncAsByte(_cutSceneNeeded); + s.syncAsByte(_helgaReady); + s.syncAsByte(_refuseAlienLiquor); + + s.syncAsSint16LE(_drinkTimer); + s.syncAsSint16LE(_beatCounter); + s.syncAsSint16LE(_bartenderMode); + s.syncAsSint16LE(_bartenderDialogNode); + s.syncAsSint16LE(_bartenderCurrentQuestion); + s.syncAsSint16LE(_helgaTalkMode); + s.syncAsSint16LE(_roxMode); + s.syncAsSint16LE(_rexMode); + s.syncAsSint16LE(_talkTimer); +} + +void Scene402::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BARTENDER); + _scene->addActiveVocab(NOUN_ALIEN_LIQUOR); + _scene->addActiveVocab(VERB_DRINK); + _scene->addActiveVocab(NOUN_BINOCULARS); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_CREDIT_CHIP); + _scene->addActiveVocab(VERB_TAKE); + _scene->addActiveVocab(NOUN_REPAIR_LIST); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene402::setDialogNode(int node) { + if (node > 0) + _bartenderDialogNode = node; + + _game._player._stepEnabled = true; + + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _conversationFl = false; + _bartenderDialogNode = 0; + break; + + case 1: + _dialog1.start(); + _bartenderDialogNode = 1; + break; + + case 2: + _dialog2.start(); + _bartenderDialogNode = 2; + break; + + case 3: + _dialog3.start(); + _bartenderDialogNode = 3; + break; + + case 4: + _dialog4.start(); + _bartenderDialogNode = 4; + break; + + default: + break; + } +} + +void Scene402::handleConversation1() { + switch (_action._activeAction._verbId) { + case 0x214: { + int quoteId = 0; + int quotePosX = 0; + switch (_vm->getRandomNumber(1, 3)) { + case 1: + quoteId = 0x1E4; + _bartenderCurrentQuestion = 4; + quotePosX = 205; + break; + + case 2: + quoteId = 0x1E5; + _bartenderCurrentQuestion = 5; + quotePosX = 203; + break; + + case 3: + quoteId = 0x1E6; + _bartenderCurrentQuestion = 6; + quotePosX = 260; + break; + + default: + break; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(quotePosX, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(quoteId)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + setDialogNode(2); + } + break; + + case 0x215: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _bartenderCurrentQuestion = 1; + setDialogNode(3); + break; + + case 0x237: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + setDialogNode(0); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + break; + + default: + break; + } +} + +void Scene402::handleConversation2() { + switch (_action._activeAction._verbId) { + case 0x216: + _dialog2.write(0x216, false); + _dialog2.write(0x21D, true); + break; + + case 0x219: + _dialog2.write(0x219, false); + _dialog2.write(0x220, true); + break; + + case 0x21A: + _dialog2.write(0x21A, false); + _dialog2.write(0x223, true); + break; + + case 0x21B: + _dialog2.write(0x21B, false); + _dialog2.write(0x224, true); + break; + + case 0x21D: + _dialog2.write(0x21D, false); + _dialog2.write(0x227, true); + break; + + case 0x220: + _dialog2.write(0x220, false); + _dialog2.write(0x22A, true); + break; + + case 0x223: + _dialog2.write(0x223, false); + _dialog2.write(0x22D, true); + break; + + case 0x224: + _dialog2.write(0x224, false); + _dialog2.write(0x230, true); + break; + + case 0x227: + _dialog2.write(0x227, false); + break; + + case 0x22A: + _dialog2.write(0x22A, false); + break; + + case 0x22D: + _dialog2.write(0x22D, false); + break; + + case 0x230: + _dialog2.write(0x230, false); + break; + + case 0x21C: + setDialogNode(0); + break; + + default: + break; + + } + + if (_action._activeAction._verbId != 0x21C) { + switch (_vm->getRandomNumber(1, 3)) { + case 1: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7)); + _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8)); + _bartenderCurrentQuestion = 7; + break; + + case 2: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9)); + _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA)); + _bartenderCurrentQuestion = 8; + break; + + case 3: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 150; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB)); + _bartenderCurrentQuestion = 9; + break; + + default: + break; + } + _dialog2.start(); + } else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + } +} + +void Scene402::handleConversation3() { + switch (_action._activeAction._verbId) { + case 0x233: + case 0x234: + case 0x235: + case 0x236: + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 86); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE)); + setDialogNode(4); + _bartenderCurrentQuestion = 2; + break; + + case 0x237: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(208, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1FD)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1120; + setDialogNode(0); + break; + + default: + break; + } +} + +void Scene402::handleConversation4() { + switch (_action._activeAction._verbId) { + case 0x238: + _scene->_kernelMessages.reset(); + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(196, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F0)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F1)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F2)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _dialog4.write(0x238, false); + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x239: + _game._player._stepEnabled = false; + _roxMode = 21; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 92); + _scene->_userInterface.setup(kInputBuildingSentences); + _conversationFl = false; + break; + + case 0x23A: + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(193, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F4)); + _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F5)); + _dialog4.write(0x23A, false); + _globals[kHasSaidTimer] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x23D: + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(153, 27), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F6)); + _scene->_kernelMessages.add(Common::Point(230, 41), 0xFDFC, 0, 0, 150, _game.getQuote(0x1F7)); + _dialog4.write(0x23D, false); + _globals[kHasSaidBinocs] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1100; + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 95); + _refuseAlienLiquor = true; + break; + + case 0x23E: + _scene->_kernelMessages.reset(); + setDialogNode(0); + _game._player._stepEnabled = false; + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F8)); + _bartenderMode = 22; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1050; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(50, 95); + _refuseAlienLiquor = true; + break; + + default: + break; + } +} + +void Scene402::handleDialogs() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + if (_vm->_font->getWidth(curQuote, _scene->_textSpacing) > 200) { + Common::String subQuote1, subQuote2; + _game.splitQuote(curQuote, subQuote1, subQuote2); + _scene->_kernelMessages.add(Common::Point(230, 42), 0x1110, 32, 0, 140, subQuote1); + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 140, subQuote2); + _scene->_sequences.addTimer(160, 120); + } else { + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 1, 140, curQuote); + _scene->_sequences.addTimer(160, 120); + } + } else if (_game._trigger == 120) { + _game._player._stepEnabled = true; + switch (_bartenderDialogNode) { + case 1: + handleConversation1(); + break; + + case 2: + handleConversation2(); + break; + + case 3: + handleConversation3(); + break; + + case 4: + handleConversation4(); + break; + + default: + break; + } + } +} + +void Scene402::enter() { + _globals._spriteIndexes[0] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[15] = _scene->_sprites.addSprites(formAnimName('x', 5)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('b', 3)); + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', 0)); + _globals._spriteIndexes[16] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[17] = _scene->_sprites.addSprites(formAnimName('z', 0)); + _globals._spriteIndexes[18] = _scene->_sprites.addSprites(formAnimName('z', 1)); + _globals._spriteIndexes[19] = _scene->_sprites.addSprites(formAnimName('z', 2)); + _globals._spriteIndexes[20] = _scene->_sprites.addSprites(formAnimName('x', 6)); + _globals._spriteIndexes[21] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[22] = _scene->_sprites.addSprites("*ROXCL_8"); + + if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(160, 150); + _game._player._facing = FACING_NORTH; + _roxOnStool = false; + _bartenderDialogNode = 1; + _conversationFl = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(160, 150); + _game._player._facing = FACING_NORTH; + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _game._objects.addToInventory(OBJ_BINOCULARS); + _game._objects.addToInventory(OBJ_TIMER_MODULE); + _roxOnStool = false; + _bartenderDialogNode = 1; + _conversationFl = false; + } + + _game.loadQuoteSet(0x1D7, 0x1D8, 0x1D9, 0x1DA, 0x1DB, 0x1DC, 0x1DD, 0x1DE, 0x1DF, 0x1E2, 0x1E3, 0x1E6, 0x1E5, 0x1E7, + 0x1E8, 0x1E9, 0x1EA, 0x1EF, 0x1F0, 0x1F1, 0x1F2, 0x1F3, 0x1F4, 0x1F5, 0x1F6, 0x1F7, 0x1F8, 0x1F9, 0x1FA, 0x1FB, + 0x1FC, 0x1EB, 0x1EC, 0x1ED, 0x1EE, 0x1E4, 0x1FD, 0x1E0, 0x1E1, 0x1FE, 0x1FF, 0x200, 0x201, 0x202, 0x203, 0x204, + 0x205, 0x206, 0x207, 0x208, 0x209, 0x20A, 0x20B, 0x20C, 0x20F, 0x20D, 0x20E, 0x210, 0x211, 0x212, 0x213, 0x214, + 0x215, 0x237, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x233, + 0x234, 0x235, 0x236, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0x23F, 0); + + _vm->_palette->setEntry(250, 47, 41, 40); + _vm->_palette->setEntry(251, 50, 63, 55); + _vm->_palette->setEntry(252, 38, 34, 25); + _vm->_palette->setEntry(253, 45, 41, 35); + + _dialog1.setup(0x60, 0x214, 0x215, 0x237, 0); + _dialog2.setup(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21D, 0x220, 0x223, 0x224, 0x227, 0x22A, 0x22D, 0x230, 0x21C, 0); + _dialog3.setup(0x62, 0x233, 0x234, 0x235, 0x236, 0x237, -1); + _dialog4.setup(0x63, 0x238, 0x239, 0x23A, 0x23D, 0x23E, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog2.set(0x61, 0x216, 0x219, 0x21A, 0x21B, 0x21C, 0); + _dialog4.set(0x63, 0x238, 0x23E, 0); + _dialog1.set(0x60, 0x214, 0x215, 0x237, 0); + } + + if (_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _dialog4.write(0x239, true); + else + _dialog4.write(0x239, false); + + if (_game._objects.isInInventory(OBJ_BINOCULARS) && !_globals[kHasSaidBinocs]) + _dialog4.write(0x23D, true); + else + _dialog4.write(0x23D, false); + + if (_game._objects.isInInventory(OBJ_TIMER_MODULE) && !_globals[kHasSaidTimer]) + _dialog4.write(0x23A, true); + else + _dialog4.write(0x23A, false); + + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + if (_conversationFl) { + switch (_bartenderDialogNode) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _bartenderDialogNode = 1; + break; + + case 1: + _dialog1.start(); + break; + + case 2: + _dialog2.start(); + break; + + case 3: + _dialog3.start(); + break; + + case 4: + _dialog4.start(); + break; + + default: + break; + } + + switch (_bartenderCurrentQuestion) { + case 1: + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EC)); + break; + + case 2: + _scene->_kernelMessages.add(Common::Point(188, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1ED)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EE)); + break; + + case 3: + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF)); + break; + + case 4: + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E4)); + break; + + case 5: + _scene->_kernelMessages.add(Common::Point(203, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E5)); + break; + + case 6: + _scene->_kernelMessages.add(Common::Point(260, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E6)); + break; + + case 7: + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E7)); + _scene->_kernelMessages.add(Common::Point(201, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E8)); + break; + + case 8: + _scene->_kernelMessages.add(Common::Point(220, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E9)); + _scene->_kernelMessages.add(Common::Point(190, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EA)); + break; + + case 9: + _scene->_kernelMessages.add(Common::Point(196, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EB)); + break; + + case 10: + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3)); + break; + + default: + break; + } + } + + _firstTalkToGirlInChair = false; + _lightOn = false; + _blowingSmoke = false; + _leftWomanMoving = false; + _rightWomanMoving = false; + _ginnyLooking = false; + _beatCounter = 0; + _waitingGinnyMove = false; + _bigBeatFl = true; + _bartenderHandsHips = false; + _bartenderSteady = true; + _bartenderLooksLeft = false; + _activeTeleporter = false; + _activeArrows = false; + _activeArrow1 = false; + _activeArrow2 = false; + _activeArrow3 = false; + _cutSceneReady = false; + _cutSceneNeeded = false; + _helgaReady = true; + _bartenderReady = true; + _drinkTimer = 0; + _bartenderTalking = false; + _bartenderCalled = false; + _helgaTalkMode = 0; + _rexMode = 0; + _refuseAlienLiquor = false; + + _scene->loadAnimation(Resources::formatName(402, 'd', 1, EXT_AA, "")); + _scene->_activeAnimation->_resetFlag = true; + + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + + if (!_game._objects.isInInventory(OBJ_REPAIR_LIST)) { + _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[14], Common::Point(210, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_REPAIR_LIST, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + + { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + } + + if (!_game._objects.isInRoom(OBJ_ALIEN_LIQUOR) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) { + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + + if (_globals[kBottleDisplayed]) { + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + } + + if (_roxOnStool) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _game._player._visible = false; + } + + sceneEntrySound(); +} + +void Scene402::step() { + if (_game._trigger == 104) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242); + _game._player._stepEnabled = true; + } + + if ((_vm->getRandomNumber(1, 1500) == 1) && (!_activeTeleporter) && (_game._player._playerPos.x < 150)) { + _vm->_sound->command(30); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 13, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 48); + _activeTeleporter = true; + _globals[kSomeoneHasExploded] = true; + } + + if (_game._trigger == 48) + _activeTeleporter = false; + + if (_game._trigger == 100) { + _bartenderReady = false; + if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + + if (!_bartenderTalking) { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 7, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 3, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderTalking = true; + if (_talkTimer > 1000) + _scene->_sequences.addTimer(_talkTimer - 1000, 101); + else + _scene->_sequences.addTimer(_talkTimer, 101); + } + } + + if ((_game._trigger == 101) && _bartenderTalking) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _bartenderSteady = true; + _bartenderTalking = false; + if (_talkTimer < 1000) + _bartenderReady = true; + } + + if (_game._trigger == 28) + _game._player._stepEnabled = true; + + switch (_game._trigger) { + case 92: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 93); + break; + + case 93: { + int seqIdx = _globals._sequenceIndexes[7]; + switch (_roxMode) { + case 20: + _vm->_sound->command(57); + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + _game._objects.addToInventory(OBJ_CREDIT_CHIP); + _vm->_dialogs->showItem(OBJ_CREDIT_CHIP, 40242); + break; + + case 22: + _vm->_sound->command(57); + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + _globals[kBottleDisplayed] = false; + _vm->_dialogs->showItem(OBJ_ALIEN_LIQUOR, 40241); + break; + + case 21: + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + break; + + default: + break; + } + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 1, 3); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 94); + + if (_roxMode == 21) { + if (_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _game._objects.setRoom (OBJ_CREDIT_CHIP, NOWHERE); + + _bartenderMode = 20; + _scene->_sequences.addTimer(60, 95); + } + } + break; + + case 94: { + int seqIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + if (_roxMode == 22) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(230, 56), 0x1110, 32, 0, 120, _game.getQuote(0x23F)); + _bartenderMode = 21; + _globals[kHasPurchased] = true; + _scene->_sequences.addTimer(140, 95); + } else if (_roxMode == 20) + _game._player._stepEnabled = true; + + } + break; + } + + switch (_game._trigger) { + case 95: + _bartenderReady = false; + _game._player._stepEnabled = false; + if (_bartenderHandsHips || _bartenderTalking) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _bartenderTalking = false; + } + + if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } + + if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 96); + break; + + case 96: { + int seqIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[12] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 6, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 97); + } + break; + + case 97: { + int seqIdx = _globals._sequenceIndexes[12]; + switch (_bartenderMode) { + case 20: + _scene->_sequences.remove(_globals._sequenceIndexes[15]); + break; + + case 21: { + _globals._sequenceIndexes[15] = _scene->_sequences.startCycle(_globals._spriteIndexes[15], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[15], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[15], Common::Point(250, 80)); + int idx = _scene->_dynamicHotspots.add(NOUN_CREDIT_CHIP, VERB_TAKE, _globals._sequenceIndexes[15], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_NONE); + } + break; + + case 22: + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals[kBottleDisplayed] = false; + break; + + default: + break; + } + + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[12], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addTimer(10, 98); + } + break; + + case 98: + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _globals._sequenceIndexes[12] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[12], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[12], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 99); + break; + + case 99: { + int seqIdx = _globals._sequenceIndexes[12]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _bartenderSteady = true; + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + if (_bartenderMode == 20) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(210, 41), 0xFDFC, 0, 0, 100, _game.getQuote(0x1F3)); + _scene->_sequences.addTimer(5, 100); + _talkTimer = 180; + _roxMode = 22; + _scene->_sequences.addTimer(65, 92); + } else if ((_bartenderMode == 21) || (_bartenderMode == 22)) { + _game._player._stepEnabled = true; + _bartenderReady = true; + } + + } + break; + } + + switch (_game._trigger) { + case 86: + _bartenderReady = false; + _game._player._stepEnabled = false; + if ((_bartenderHandsHips) || (_bartenderTalking)) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _bartenderTalking = false; + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 87); + break; + + case 87: { + int seqIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], seqIdx); + _scene->_sequences.addTimer(10, 89); + + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 88); + } + break; + + case 88: + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 7); + _globals[kBottleDisplayed] = true; + break; + + case 89: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addTimer(10, 90); + break; + + case 90: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addTimer(10, 91); + break; + + case 91: { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _bartenderSteady = true; + _game._player._stepEnabled = true; + _bartenderReady = true; + } + break; + } + + if (!_waitingGinnyMove && !_ginnyLooking) { + _waitingGinnyMove = true; + ++ _beatCounter; + if (_beatCounter >= 20) { + _ginnyLooking = true; + _beatCounter = 0; + _scene->_sequences.addTimer(60, 54); + } else { + _scene->_sequences.addTimer(30, 75); + } + } + + switch (_game._trigger) { + case 75: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _bigBeatFl = !_bigBeatFl; + + if (_bigBeatFl) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.addTimer(8, 130); + } else { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.addTimer(8, 53); + } + + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + break; + + case 130: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(8, 131); + break; + + case 131: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(8, 53); + break; + + case 53: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _waitingGinnyMove = false; + break; + } + + if ((_game._trigger == 54) && _ginnyLooking) { + ++_beatCounter; + if (_beatCounter >= 10) { + _ginnyLooking = false; + _waitingGinnyMove = false; + _beatCounter = 0; + _bigBeatFl = true; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, _vm->getRandomNumber(1, 4)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addTimer(60, 54); + } + } + + if (_bartenderReady) { + if (_vm->getRandomNumber(1, 250) == 1) { + if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + } else if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + } else if (_bartenderSteady) { + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _bartenderSteady = false; + } + + switch (_vm->getRandomNumber(1, 3)) { + case 1: { + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[10], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderHandsHips = true; + } + break; + + case 2: { + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[11], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderLooksLeft = true; + } + break; + + case 3: { + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + } + break; + + default: + break; + } + } + } + + if (_game._trigger == 76) { + int seqIdx = _globals._sequenceIndexes[6]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + if (!_globals[kBeenThruHelgaScene]) { + _game._player._stepEnabled = false; + _cutSceneNeeded = true; + } else { + _game._player._stepEnabled = true; + } + _roxOnStool = true; + } + + switch (_game._trigger) { + case 77: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 78); + break; + + case 78: { + _vm->_sound->command(57); + int seqIdx = _globals._sequenceIndexes[7]; + _game._objects.addToInventory(OBJ_REPAIR_LIST); + _scene->_sequences.remove(_globals._sequenceIndexes[14]); + _globals._sequenceIndexes[7] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[7], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[7], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 79); + } + break; + + case 79: { + int seqIdx = _globals._sequenceIndexes[7]; + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[6], seqIdx); + _scene->_sequences.addTimer(20, 180); + } + break; + + case 180: + _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + if (_cutSceneNeeded && _cutSceneReady) { + _cutSceneNeeded = false; + _scene->_sequences.addTimer(20, 55); + _helgaReady = false; + _bartenderReady = false; + } + + if (_vm->getRandomNumber(1, 25) == 1) { + if (_lightOn) { + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _lightOn = false; + } else { + _globals._sequenceIndexes[0] = _scene->_sequences.startCycle(_globals._spriteIndexes[0], false, 1); + _lightOn = true; + } + } + + if (!_blowingSmoke && (_vm->getRandomNumber(1, 300) == 1)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 14); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 30); + _blowingSmoke = true; + } + + switch (_game._trigger) { + case 30: + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1],SEQUENCE_TRIGGER_EXPIRE, 0, 31); + break; + + case 31: + _blowingSmoke = false; + break; + } + + if (!_leftWomanMoving) { + if (_vm->getRandomNumber(1, 1000) == 1) { + switch (_vm->getRandomNumber(1, 2)) { + case 1: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 33); + _leftWomanMoving = true; + break; + + case 2: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.addTimer(12, 35); + _leftWomanMoving = true; + break; + + default: + break; + } + } + } + + switch (_game._trigger) { + case 33: { + int seqIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], seqIdx); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 250), 34); + } + break; + + case 34: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[2], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 38); + break; + + case 35: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 2); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 300), 36); + break; + + case 36: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.addTimer(12, 37); + break; + + case 37: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _leftWomanMoving = false; + break; + + case 38: + _leftWomanMoving = false; + break; + + default: + break; + } + + if (!_rightWomanMoving) { + if (_vm->getRandomNumber(1, 300) == 1) { + switch (_vm->getRandomNumber(1, 4)) { + case 1: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 2: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 3: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 4, 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + case 4: + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 3, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 32); + _rightWomanMoving = true; + break; + + default: + break; + } + } + } + + if (_game._trigger == 32) + _rightWomanMoving = false; + + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + switch (_vm->getRandomNumber(1, 50)) { + case 1: + _scene->_activeAnimation->setCurrentFrame(2); + break; + + case 2: + _scene->_activeAnimation->setCurrentFrame(7); + break; + + case 3: + _scene->_activeAnimation->setCurrentFrame(11); + break; + + default: + _scene->_activeAnimation->setCurrentFrame(0); + break; + } + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 4) && (_drinkTimer < 10)) { + ++ _drinkTimer; + _scene->_activeAnimation->setCurrentFrame(3); + } + + if (_drinkTimer == 10) { + _drinkTimer = 0; + _scene->_activeAnimation->setCurrentFrame(4); + _scene->_activeAnimation->_currentFrame = 5; + } + + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 6: + case 10: + case 14: + _scene->_activeAnimation->setCurrentFrame(0); + break; + + default: + break; + } + + switch (_game._trigger) { + case 39: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D8)); + _scene->_sequences.addTimer(150, 40); + break; + + case 40: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1D9)); + _scene->_sequences.addTimer(150, 41); + break; + + case 41: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DA)); + _game._player._stepEnabled = true; + break; + + case 42: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DC)); + _scene->_sequences.addTimer(150, 43); + break; + + case 43: + _scene->_kernelMessages.add(Common::Point(89, 67), 0xFDFC, 32, 0, 120, _game.getQuote(0x1DD)); + _game._player._stepEnabled = true; + break; + + case 44: + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 55: + if (_bartenderHandsHips) { + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _bartenderHandsHips = false; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + } else if (_bartenderLooksLeft) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _bartenderLooksLeft = false; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_BARTENDER, VERB_WALKTO, _globals._sequenceIndexes[9], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(228, 83), FACING_SOUTH); + _bartenderSteady = true; + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + } + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(180, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x1FE)); + _scene->_sequences.addTimer(120, 56); + break; + + case 56: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 57); + break; + + case 57: { + int seqIdx = _globals._sequenceIndexes[13]; + _scene->_sequences.remove(_globals._sequenceIndexes[20]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 58); + } + break; + + case 58: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 59); + } + break; + + case 59: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + } + break; + + case 60: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addTimer(10, 61); + } + break; + + case 61: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(181, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x1FF)); + _scene->_kernelMessages.add(Common::Point(171, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x200)); + _scene->_sequences.addTimer(150, 63); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 30, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 62); + break; + + case 62: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 63: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(160, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x201)); + _scene->_kernelMessages.add(Common::Point(165, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x202)); + _scene->_sequences.addTimer(150, 64); + break; + + case 64: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(210, 27), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E0)); + _scene->_kernelMessages.add(Common::Point(198, 41), 0xFDFC, 0, 0, 130, _game.getQuote(0x1E1)); + _scene->_sequences.addTimer(150, 65); + _scene->_sequences.addTimer(1, 100); + _talkTimer = 1130; + break; + + case 65: + _vm->_sound->command(30); + _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 66); + break; + + case 66: { + int seqIdx = _globals._sequenceIndexes[16]; + _globals._sequenceIndexes[16] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[16], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[16], 7, 37); + _scene->_sequences.setDepth(_globals._sequenceIndexes[16], 9); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[16], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[16], SEQUENCE_TRIGGER_EXPIRE, 0, 68); + + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 67); + } + break; + + case 67: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 13); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 68: + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 12, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 69); + break; + + case 69: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(179, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x203)); + _scene->_kernelMessages.add(Common::Point(167, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x204)); + _scene->_sequences.addTimer(150, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + } + break; + + case 70: + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 25, 4, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 12); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 71: + _scene->_sequences.addTimer(210, 73); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(168, 33), 0xFBFA, 0, 0, 180, _game.getQuote(0x205)); + _scene->_kernelMessages.add(Common::Point(151, 47), 0xFBFA, 0, 0, 180, _game.getQuote(0x206)); + if (!_game._objects.isInInventory(OBJ_REPAIR_LIST)) + _activeArrows = true; + break; + + case 72: { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + } + break; + + case 73: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 150, _game.getQuote(0x207)); + _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 150, _game.getQuote(0x208)); + _bartenderSteady = true; + _game._player._stepEnabled = true; + _helgaReady = true; + _bartenderReady = true; + _globals[kBeenThruHelgaScene] = true; + _activeArrows = false; + break; + + default: + break; + } + + if (_helgaReady) { + int rndVal = _vm->getRandomNumber(1, 1000); + if (rndVal < 6) + switch (rndVal) { + case 1: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 2, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + break; + + case 2: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 11, 13); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 3: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 4: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 15, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 14, 15); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + break; + + case 5: + _cutSceneReady = false; + _helgaReady = false; + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + default: + break; + } + } + + if (_game._trigger == 80) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 19); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addTimer(_vm->getRandomNumber(60, 120), 81); + } + + if (_game._trigger == 81) { + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 16, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 26); + } + + if (_game._trigger == 26) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _cutSceneReady = true; + + if (!_cutSceneNeeded) + _helgaReady = true; + } + + if (_game._trigger == 82) { + _scene->_sequences.remove(_globals._sequenceIndexes[20]); + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 6, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + } + + if (_game._trigger == 83) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 5, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 84); + } + + if (_game._trigger == 84) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[13], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[13], 1, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 85); + + _globals._sequenceIndexes[20] = _scene->_sequences.startCycle(_globals._spriteIndexes[20], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[20], 8); + _scene->_sequences.setPosition(_globals._sequenceIndexes[20], Common::Point(234, 72)); + } + + if (_game._trigger == 85) { + int seqIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], seqIdx); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _cutSceneReady = true; + if (!_cutSceneNeeded) + _helgaReady = true; + } + + if (_game._trigger == 102) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[7], 14, 18); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 103); + } else if (_game._trigger == 103) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _roxOnStool = false; + _game._player._facing = FACING_SOUTH; + _game._player.selectSeries(); + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + } + + if (_activeArrows) { + if (!_activeArrow1) { + _globals._sequenceIndexes[17] = _scene->_sequences.startCycle(_globals._spriteIndexes[17], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[17], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 49); + _activeArrow1 = true; + } + + if (!_activeArrow2) { + _globals._sequenceIndexes[18] = _scene->_sequences.startCycle(_globals._spriteIndexes[18], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[18], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 50); + _activeArrow2 = true; + } + + if (!_activeArrow3) { + _globals._sequenceIndexes[19] = _scene->_sequences.startCycle(_globals._spriteIndexes[19], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[19], 1); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 51); + _activeArrow3 = true; + } + } + + if (_game._trigger == 49) { + _scene->_sequences.remove(_globals._sequenceIndexes[17]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 45); + } + + if (_game._trigger == 45) + _activeArrow1 = false; + + if (_game._trigger == 50) { + _scene->_sequences.remove(_globals._sequenceIndexes[18]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 46); + } + + if (_game._trigger == 46) + _activeArrow2 = false; + + if (_game._trigger == 51) { + _scene->_sequences.remove(_globals._sequenceIndexes[19]); + _scene->_sequences.addTimer(_vm->getRandomNumber(10, 15), 47); + } + + if (_game._trigger == 47) + _activeArrow3 = false; +} + +void Scene402::preActions() { + if (_action.isAction(VERB_SIT_ON, NOUN_BAR_STOOL) && (_game._player._prepareWalkPos.x != 248)) + _game._player.walk(Common::Point(232, 112), FACING_EAST); + + if (_action.isAction(VERB_WALKTO, NOUN_WOMAN_ON_BALCONY)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (!_roxOnStool && _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP)) + _game._player.walk(Common::Point(246, 108), FACING_NORTH); + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_roxOnStool) + _game._player._needToWalk = true; + + if (_roxOnStool) { + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_BAR_STOOL) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) || _action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) || _action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE)) + _game._player._needToWalk = _game._player._readyToWalk; + + if (_game._player._needToWalk) { + _game._player._facing = FACING_SOUTH; + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 102); + } + } + + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && !_roxOnStool && !_game._objects.isInInventory(OBJ_REPAIR_LIST)) + _game._player.walk(Common::Point(191, 99), FACING_NORTHEAST); + + if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER) && !_roxOnStool) + _game._player.walk(Common::Point(228, 83), FACING_SOUTH); + + if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN) && !_roxOnStool) + _game._player.walk(Common::Point(208, 102), FACING_NORTHEAST); +} + +void Scene402::actions() { + if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && _roxOnStool) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 77); + _game._player._needToWalk = false; + } else if (_action.isAction(VERB_TAKE, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST) && !_roxOnStool) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[21] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[21], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[21], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[21]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_SPRITE, 2, 165); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[21], SEQUENCE_TRIGGER_EXPIRE, 0, 166); + } else if (_game._trigger == 165) { + _scene->_sequences.remove(_globals._sequenceIndexes[14]); + _game._objects.addToInventory(OBJ_REPAIR_LIST); + } + } else if (_game._trigger == 166) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 167); + } else if (_game._trigger == 167) { + _vm->_dialogs->showItem(OBJ_REPAIR_LIST, 40240); + _game._player._stepEnabled = true; + } else if (_game._screenObjects._inputMode == 1) + handleDialogs(); + else if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 401; + else if (_action.isAction(VERB_WALK_ONTO, NOUN_DANCE_FLOOR)) + ; // just... nothing + else if (_action.isAction(VERB_TALKTO, NOUN_REPAIR_WOMAN)) { + switch (_game._trigger) { + case 0: { + _game._player._stepEnabled = false; + int random = _vm->getRandomNumber(1, 3); + if (_helgaTalkMode == 0) + random = 1; + + int centerFlag; + Common::Point centerPos; + if (_roxOnStool) { + centerFlag = 0; + centerPos = Common::Point(230, 56); + } else { + centerFlag = 2; + centerPos = Common::Point(0, 0); + } + + switch (random) { + case 1: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x211)); + _scene->_sequences.addTimer(110, 25); + break; + + case 2: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x212)); + _scene->_sequences.addTimer(110, 25); + break; + + case 3: + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(0x213)); + _scene->_sequences.addTimer(110, 25); + break; + + default: + break; + } + } + break; + + case 25: + switch (_helgaTalkMode) { + case 0: + _game._player._stepEnabled = false; + _helgaTalkMode = 1; + _scene->_kernelMessages.add(Common::Point(177, 33), 0xFBFA, 0, 0, 130, _game.getQuote(0x209)); + _scene->_kernelMessages.add(Common::Point(182, 47), 0xFBFA, 0, 0, 130, _game.getQuote(0x20A)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(130, 28); + break; + + case 1: + _game._player._stepEnabled = false; + _helgaTalkMode = 2; + _scene->_kernelMessages.add(Common::Point(157, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20B)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 28); + break; + + case 2: + _game._player._stepEnabled = false; + _helgaTalkMode = 3; + _scene->_kernelMessages.add(Common::Point(172, 47), 0xFBFA, 0, 0, 100, _game.getQuote(0x20C)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(100, 28); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + break; + } + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && !_firstTalkToGirlInChair) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1D7)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(150, 39); + _game._player._stepEnabled = false; + _firstTalkToGirlInChair = true; + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_CHAIR) && _firstTalkToGirlInChair) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x1DB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(150, 42); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_IN_ALCOVE) || _action.isAction(VERB_WALKTO, NOUN_WOMAN_IN_ALCOVE)) { + _scene->_kernelMessages.add(Common::Point(102, 48), 0xFBFA, 0, 0, 120, _game.getQuote(0x1DE)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(120, 44); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_WALK_ALONG, NOUN_BAR_STOOL) && (_game._player._targetPos.x == 248)){ + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 120, _game.getQuote(0x20D)); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x20E)); + } else if (_action.isAction(VERB_WALK_ALONG, NOUN_BAR_STOOL) && !_roxOnStool && (_game._player._targetPos.x != 248)) { + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && _roxOnStool) { + _roxMode = 20; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 92); + } else if (_action.isAction(VERB_TAKE, NOUN_CREDIT_CHIP) && !_game._objects.isInInventory(OBJ_CREDIT_CHIP) && !_roxOnStool) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[22] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[22], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[22], 1, 2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[22], Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[22], 5); + _scene->_sequences.setScale(_globals._sequenceIndexes[22], 88); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[22], SEQUENCE_TRIGGER_EXPIRE, 0, 104); + } else if (_action.isAction(VERB_TALKTO, NOUN_BARTENDER)) { + switch (_game._trigger) { + case 0: { + int centerFlag; + Common::Point centerPos; + if (_roxOnStool) { + centerFlag = 0; + centerPos = Common::Point(230, 56); + } else { + centerFlag = 2; + centerPos = Common::Point(0, 0); + } + + _game._player._stepEnabled = false; + int quoteId; + if (_bartenderCalled) { + quoteId = 0x210; + } else { + quoteId = 0x20F; + _bartenderCalled = true; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(centerPos, 0x1110, 32 | centerFlag, 0, 90, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(110, 29); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(90, 28); + } + break; + + case 29: + _scene->_kernelMessages.reset(); + if (!_roxOnStool) { + if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) { + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1DF)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + } else if (_rexMode == 0) { + _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _rexMode = 1; + } else if (_rexMode == 1) { + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC)); + _game._player._stepEnabled = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _rexMode = 3; + } else { + _game._player._stepEnabled = true; + } + } else { + if (_game._objects.isInRoom(OBJ_ALIEN_LIQUOR)) { + if (!_refuseAlienLiquor) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(198, 27), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E2)); + _scene->_kernelMessages.add(Common::Point(199, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1E3)); + _bartenderCurrentQuestion = 10; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _conversationFl = true; + _bartenderDialogNode = 1; + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + _dialog1.start(); + } else { + _scene->_kernelMessages.add(Common::Point(177, 41), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x1EF)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _bartenderCurrentQuestion = 3; + _conversationFl = true; + _bartenderDialogNode = 1; + if (_dialog2.read(0) <= 1) + _dialog1.write(0x214, false); + + _dialog1.start(); + _game._player._stepEnabled = true; + } + } else { + if (_rexMode == 0) { + _scene->_kernelMessages.add(Common::Point(175, 13), 0xFDFC, 0, 0, 180, _game.getQuote(0x1F9)); + _scene->_kernelMessages.add(Common::Point(184, 27), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FA)); + _scene->_kernelMessages.add(Common::Point(200, 41), 0xFDFC, 0, 0, 180, _game.getQuote(0x1FB)); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 180; + _rexMode = 1; + } else if (_rexMode == 1) { + _scene->_kernelMessages.add(Common::Point(205, 41), 0xFDFC, 0, 0, 120, _game.getQuote(0x1FC)); + _game._player._stepEnabled = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(1, 100); + _talkTimer = 120; + _rexMode = 3; + } else { + _game._player._stepEnabled = true; + } + } + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_DANCE_FLOOR)) + _vm->_dialogs->show(40210); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) { + if (_globals[kSomeoneHasExploded]) + _vm->_dialogs->show(40212); + else + _vm->_dialogs->show(40211); + } else if (_action.isAction(VERB_LOOK, NOUN_BAR)) + _vm->_dialogs->show(40213); + else if (_action.isAction(VERB_LOOK, NOUN_BARTENDER)) + _vm->_dialogs->show(40214); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_ALCOVE)) + _vm->_dialogs->show(40215); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_ON_BALCONY)) + _vm->_dialogs->show(40216); + else if (_action.isAction(VERB_LOOK, NOUN_WOMAN_IN_CHAIR)) + _vm->_dialogs->show(40217); + else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_WOMAN)) + _vm->_dialogs->show(40218); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40219); + else if (_action._lookFlag) + _vm->_dialogs->show(40220); + else if (_action.isAction(VERB_LOOK, NOUN_WOMEN)) + _vm->_dialogs->show(40221); + else if (_action.isAction(VERB_PUSH, NOUN_REPAIR_WOMAN) || _action.isAction(VERB_PULL, NOUN_REPAIR_WOMAN)) + _vm->_dialogs->show(40222); + else if (_action.isAction(VERB_TALKTO, NOUN_WOMEN)) + _vm->_dialogs->show(40223); + else if (_action.isAction(VERB_TALKTO, NOUN_WOMAN_ON_BALCONY)) + _vm->_dialogs->show(40224); + else if (_action.isAction(VERB_LOOK, NOUN_RAILING)) + _vm->_dialogs->show(40225); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(40226); + else if (_action.isAction(VERB_TAKE, NOUN_TABLE)) + _vm->_dialogs->show(40227); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40228); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(40229); + else if (_action.isAction(VERB_LOOK, NOUN_BAR_STOOL)) + _vm->_dialogs->show(40230); + else if (_action.isAction(VERB_TAKE, NOUN_BAR_STOOL)) + _vm->_dialogs->show(40231); + else if (_action.isAction(VERB_LOOK, NOUN_CACTUS)) + _vm->_dialogs->show(40232); + else if (_action.isAction(VERB_TAKE, NOUN_CACTUS)) + _vm->_dialogs->show(40233); + else if (_action.isAction(VERB_LOOK, NOUN_DISCO_BALL)) + _vm->_dialogs->show(40234); + else if (_action.isAction(VERB_LOOK, NOUN_UPPER_DANCE_FLOOR)) + _vm->_dialogs->show(40235); + else if (_action.isAction(VERB_LOOK, NOUN_TREE)) + _vm->_dialogs->show(40236); + else if (_action.isAction(VERB_LOOK, NOUN_PLANT)) + _vm->_dialogs->show(40237); + else if (_action.isAction(VERB_TAKE, NOUN_PLANT)) + _vm->_dialogs->show(40238); + else if (_action.isAction(VERB_LOOK, NOUN_REPAIR_LIST) && _game._objects.isInRoom(OBJ_REPAIR_LIST)) + _vm->_dialogs->show(40239); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene405::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene405::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXCL_8"); + + if (_scene->_priorSceneId == 401) { + _game._player._playerPos = Common::Point(23, 123); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 406) { + _game._player._playerPos = Common::Point(300, 128); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 408) { + _game._player._playerPos = Common::Point(154, 109); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 413) { + _game._player._playerPos = Common::Point(284, 109); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(23, 123); + _game._player._facing = FACING_EAST; + } + + if (_globals[kArmoryDoorOpen]) + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + else + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + if (_scene->_roomChanged) { + _globals[kArmoryDoorOpen] = false; + _game._objects.addToInventory(OBJ_SECURITY_CARD); + } + + _game.loadQuoteSet(0x24F, 0); + sceneEntrySound(); +} + +void Scene405::step() { + if (_game._trigger == 80) { + _scene->_sequences.addTimer(20, 81); + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_game._trigger == 81) { + _game._player._stepEnabled = true; + _vm->_dialogs->show(40525); + } + + if (_game._trigger == 70) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; + _game._player._visible = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(19); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals[kArmoryDoorOpen] = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 75) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _globals[kArmoryDoorOpen] = true; + _game._player._stepEnabled = true; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle (_globals._spriteIndexes[2], + false, 1); + _vm->_sound->command(19); + } +} + +void Scene405::preActions() { + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 401; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 406; + + if (_action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen]) + _game._player.walk(Common::Point(212, 113), FACING_NORTH); +} + +void Scene405::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR)) + _scene->_nextSceneId = 413; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && _globals[kArmoryDoorOpen]) + _scene->_nextSceneId = 408; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_WIDE_DOOR) && !_globals[kArmoryDoorOpen]) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F)); + else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kArmoryDoorOpen]) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if ((_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_CLOSE, NOUN_WIDE_DOOR)) && _globals[kArmoryDoorOpen]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 87); + } else if (_action.isAction(VERB_LOOK, NOUN_CANNON_BALLS)) + _vm->_dialogs->show(40510); + else if (_action.isAction(VERB_TAKE, NOUN_CANNON_BALLS)) + _vm->_dialogs->show(40511); + else if (_action.isAction(VERB_LOOK, NOUN_WATER_FOUNTAIN)) + _vm->_dialogs->show(40512); + else if (_action.isAction(VERB_LOOK, NOUN_BACKBOARD) || _action.isAction(VERB_LOOK, NOUN_HOOP)) + _vm->_dialogs->show(40513); + else if (_action.isAction(VERB_LOOK, NOUN_LIGHT)) + _vm->_dialogs->show(40514); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(40515); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(40516); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(40517); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(40518); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag) + _vm->_dialogs->show(40519); + else if (_action.isAction(VERB_LOOK, NOUN_WIDE_DOOR)) { + if (_globals[kArmoryDoorOpen]) + _vm->_dialogs->show(40521); + else + _vm->_dialogs->show(40520); + } else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(40522); + else if (_action.isAction(VERB_LOOK, NOUN_COACH_LAMP)) + _vm->_dialogs->show(40523); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(40524); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene406::Scene406(MADSEngine *vm) : Scene4xx(vm) { + _hitStorageDoor = false; +} + +void Scene406::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_hitStorageDoor); +} + +void Scene406::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene406::enter() { + _game._player._visible = true; + if (_scene->_priorSceneId == 405) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 407) { + _game._player._playerPos = Common::Point(270, 127); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 410) { + _game._player._playerPos = Common::Point(30, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId == 411) { + _game._player._playerPos = Common::Point(153, 108); + _game._player._facing = FACING_SOUTH; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } + + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXCL_8"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + + if (_scene->_roomChanged) { + _globals[kStorageDoorOpen] = false; + _game._objects.addToInventory(OBJ_SECURITY_CARD); + } + + if (!_globals[kStorageDoorOpen]) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + + if (_scene->_priorSceneId != 411) + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + else { + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + _vm->_sound->command(19); + } + + _game.loadQuoteSet(0x24F, 0); + _hitStorageDoor = false; + sceneEntrySound(); +} + +void Scene406::step() { + if (_game._trigger == 90) { + _game._player._stepEnabled = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + } + + if (_game._trigger == 80) + _scene->_nextSceneId = 411; + + if (_game._trigger == 100) { + _vm->_dialogs->show(40622); + _hitStorageDoor = true; + } + + if (_game._trigger == 110) { + _scene->_sequences.addTimer(20, 111); + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_game._trigger == 111) { + _game._player._stepEnabled = true; + _vm->_dialogs->show(40613); + } + + if (_game._trigger == 70) { + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(19); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _globals[kStorageDoorOpen] = false; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 75) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 4, 1, 0, 0); + _globals[kStorageDoorOpen] = true; + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _vm->_sound->command(19); + } +} + +void Scene406::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_WEST)) + _game._player._walkOffScreenSceneId = 405; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_EAST)) + _game._player._walkOffScreenSceneId = 407; + + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_SIGN) || _action.isAction(VERB_LOOK, NOUN_TRASH)) + _game._player._needToWalk = true; +} + +void Scene406::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._targetPos.x> 100)) { + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 3, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _vm->_sound->command(19); + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && _globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100)) + _scene->_nextSceneId = 410; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && !_globals[kStorageDoorOpen] && (_game._player._targetPos.x < 100)) { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(0x24F)); + if (!_hitStorageDoor) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(80, 100); + } + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && !_globals[kStorageDoorOpen]) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT) && _globals[kStorageDoorOpen]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + Common::Point msgPos = Common::Point(_game._player._playerPos.x, _game._player._playerPos.y + 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], msgPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_PUT, NOUN_CARD_SLOT)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + _scene->_sequences.setPosition(_globals._sequenceIndexes[2], _game._player._playerPos); + _scene->_sequences.setScale(_globals._sequenceIndexes[2], 87); + } else if (_action.isAction(VERB_LOOK, NOUN_TRASH)) + _vm->_dialogs->show(40610); + else if (_action.isAction(VERB_TAKE, NOUN_TRASH)) + _vm->_dialogs->show(40611); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(40612); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_EXTINGUISHER)) + _vm->_dialogs->show(40614); + else if (_action.isAction(VERB_TAKE, NOUN_FIRE_EXTINGUISHER)) + _vm->_dialogs->show(40615); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_EAST)) + _vm->_dialogs->show(40616); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_WEST)) + _vm->_dialogs->show(40617); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR) || _action._lookFlag) + _vm->_dialogs->show(40618); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(40619); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) { + if (_globals[kStorageDoorOpen]) + _vm->_dialogs->show(40621); + else + _vm->_dialogs->show(40620); + } else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(40623); + else if (_action.isAction(VERB_LOOK, NOUN_SIGNPOST)) + _vm->_dialogs->show(40624); + else if (_action.isAction(VERB_TAKE, NOUN_SIGNPOST)) + _vm->_dialogs->show(40625); + else if (_action.isAction(VERB_LOOK, NOUN_BOULDER)) + _vm->_dialogs->show(40626); + else if (_action.isAction(VERB_TAKE, NOUN_BOULDER)) + _vm->_dialogs->show(40627); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(40628); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(40629); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene407::Scene407(MADSEngine *vm) : Scene4xx(vm), _destPos(0, 0) { + _fromNorth = false; +} + +void Scene407::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsByte(_fromNorth); + s.syncAsSint16LE(_destPos.x); + s.syncAsSint16LE(_destPos.y); +} + +void Scene407::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene407::enter() { + if (_scene->_priorSceneId != -2) + _fromNorth = false; + + if (_scene->_priorSceneId == 318) { + _game._player._playerPos = Common::Point(172, 92); + _game._player._facing = FACING_SOUTH; + _fromNorth = true; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(172, 132); + _game._player._facing = FACING_NORTH; + } + + _game.loadQuoteSet(0x250, 0); + sceneEntrySound(); +} + +void Scene407::step() { + if (_game._trigger == 70) { + _scene->_nextSceneId = 318; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 80) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._stepEnabled = true; + _game._player._visible = true; + _fromNorth = false; + _game._player.walk(Common::Point(173, 104), FACING_SOUTH); + } +} + +void Scene407::preActions() { + if (_action.isAction(VERB_TAKE)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) { + _game._player.walk(Common::Point(172, 91), FACING_NORTH); + _fromNorth = false; + } + + if (_game._player._needToWalk && _fromNorth) { + if (_globals[kSexOfRex] == REX_MALE) + _destPos = Common::Point(171, 95); + else + _destPos = Common::Point(173, 96); + + _game._player.walk(_destPos, FACING_SOUTH); + } +} + +void Scene407::actions() { + if ((_game._player._playerPos == _destPos) && _fromNorth) { + if (_globals[kSexOfRex] == REX_MALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 1), 70); + _globals[kHasBeenScanned] = true; + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 60, _game.getQuote(60)); + _vm->_sound->command(22); + } + + if (_globals[kSexOfRex] == REX_FEMALE) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _game._player._stepEnabled = false; + _game._player._visible = false; + _vm->_sound->command(21); + _scene->loadAnimation(formAnimName('s', 2), 80); + _vm->_sound->command(23); + _globals[kHasBeenScanned] = true; + } + } + + if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_SOUTH) && !_fromNorth) + _scene->_nextSceneId = 406; + else if (_action.isAction(VERB_WALK_DOWN, NOUN_CORRIDOR_TO_NORTH)) + _scene->_nextSceneId = 318; + else if (_action.isAction(VERB_LOOK, NOUN_SCANNER)) { + if (_globals[kHasBeenScanned]) + _vm->_dialogs->show(40711); + else + _vm->_dialogs->show(40710); + } else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(40712); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40713); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_NORTH)) + _vm->_dialogs->show(40714); + else if (_action._lookFlag) + _vm->_dialogs->show(40715); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene408::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_TARGET_MODULE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene408::enter() { + _game._player._playerPos = Common::Point(137, 150); + _game._player._facing = FACING_NORTH; + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*ROXRC_7"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', -1)); + + if (_game._objects.isInRoom(OBJ_TARGET_MODULE)) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(283, 128), FACING_NORTHEAST); + } + sceneEntrySound(); +} + +void Scene408::preActions() { + if ((_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_TARGET_MODULE)) || _action.isAction(VERB_PULL, NOUN_PIN) || _action.isAction(VERB_OPEN, NOUN_CARTON)) + _game._player._needToWalk = false; + + if ((_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE)) || _action.isAction(VERB_LOOK, NOUN_CHEST)) + _game._player._needToWalk = true; +} + +void Scene408::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 405; + _vm->_sound->command(58); + } else if (_action.isAction(VERB_TAKE, NOUN_TARGET_MODULE) && (_game._objects.isInRoom(OBJ_TARGET_MODULE) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[1]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._objects.addToInventory(OBJ_TARGET_MODULE); + _vm->_dialogs->showItem(OBJ_TARGET_MODULE, 40847); + break; + + case 2: + _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_ARMORED_VEHICLE)) + _vm->_dialogs->show(40810); + else if (_action.isAction(VERB_TAKE, NOUN_ARMORED_VEHICLE) || _action.isAction(VERB_TAKE, NOUN_ANVIL) || _action.isAction(VERB_TAKE, NOUN_TWO_TON_WEIGHT)) + _vm->_dialogs->show(40811); + else if (_action.isAction(VERB_LOOK, NOUN_MISSILE)) + _vm->_dialogs->show(40812); + else if (_action.isAction(VERB_TAKE, NOUN_MISSILE)) + _vm->_dialogs->show(40813); + else if (_action.isAction(VERB_LOOK, NOUN_GRENADE)) + _vm->_dialogs->show(40814); + else if (_action.isAction(VERB_TAKE, NOUN_GRENADE)) + _vm->_dialogs->show(40815); + else if (_action.isAction(VERB_TAKE, NOUN_PIN) || _action.isAction(VERB_PULL, NOUN_PIN)) + _vm->_dialogs->show(40816); + else if (_action.isAction(VERB_LOOK, NOUN_BLIMP)) + _vm->_dialogs->show(40817); + else if (_action.isAction(VERB_TAKE, NOUN_BLIMP)) + _vm->_dialogs->show(40818); + else if (_action.isAction(VERB_LOOK, NOUN_AMMUNITION)) + _vm->_dialogs->show(40819); + else if (_action.isAction(VERB_TAKE, NOUN_AMMUNITION)) + _vm->_dialogs->show(40820); + else if (_action.isAction(VERB_LOOK, NOUN_CATAPULT)) + _vm->_dialogs->show(40821); + else if (_action.isAction(VERB_TAKE, NOUN_CATAPULT)) + _vm->_dialogs->show(40822); + else if (_action.isAction(VERB_LOOK, NOUN_CHEST)) { + if (_game._objects.isInRoom(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(40823); + else + _vm->_dialogs->show(40824); + } else if (_action.isAction(VERB_TAKE, NOUN_CHEST)) + _vm->_dialogs->show(40825); + else if (_action.isAction(VERB_LOOK, NOUN_SUIT_OF_ARMOR)) + _vm->_dialogs->show(40826); + else if (_action.isAction(VERB_TAKE, NOUN_SUIT_OF_ARMOR)) + _vm->_dialogs->show(40827); + else if (_action.isAction(VERB_LOOK, NOUN_ESCAPE_HATCH)) + _vm->_dialogs->show(40828); + else if (_action.isAction(VERB_OPEN, NOUN_ESCAPE_HATCH) || _action.isAction(VERB_PULL, NOUN_ESCAPE_HATCH)) + _vm->_dialogs->show(40829); + else if (_action.isAction(VERB_LOOK, NOUN_BARRELS)) + _vm->_dialogs->show(40830); + else if (_action.isAction(VERB_TAKE, NOUN_BARRELS)) + _vm->_dialogs->show(40831); + else if (_action.isAction(VERB_LOOK, NOUN_INFLATABLE_RAFT)) + _vm->_dialogs->show(40832); + else if (_action.isAction(VERB_TAKE, NOUN_INFLATABLE_RAFT)) + _vm->_dialogs->show(40833); + else if (_action.isAction(VERB_LOOK, NOUN_TOMATO)) + _vm->_dialogs->show(40834); + else if (_action.isAction(VERB_TAKE, NOUN_TOMATO)) + _vm->_dialogs->show(40835); + else if (_action.isAction(VERB_LOOK, NOUN_ANVIL)) + _vm->_dialogs->show(40836); + else if (_action.isAction(VERB_LOOK, NOUN_TWO_TON_WEIGHT)) + _vm->_dialogs->show(40837); + else if (_action.isAction(VERB_LOOK, NOUN_POWDER_CONTAINER)) + _vm->_dialogs->show(40838); + else if (_action.isAction(VERB_LOOK, NOUN_POWDER_PUFF)) + _vm->_dialogs->show(40839); + else if (_action.isAction(VERB_TAKE, NOUN_POWDER_PUFF)) + _vm->_dialogs->show(40840); + else if (_action.isAction(VERB_LOOK, NOUN_CARTON)) + _vm->_dialogs->show(40841); + else if (_action.isAction(VERB_TAKE, NOUN_CARTON)) + _vm->_dialogs->show(40842); + else if (_action.isAction(VERB_OPEN, NOUN_CARTON)) + _vm->_dialogs->show(40843); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(40844); + else if (_action._lookFlag) + _vm->_dialogs->show(40845); + else if (_action.isAction(VERB_LOOK, NOUN_TARGET_MODULE) && _game._objects.isInRoom(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(40846); + else if (_action.isAction(VERB_LOOK, NOUN_LOADING_RAMP)) + _vm->_dialogs->show(40848); + else if (_action.isAction(VERB_OPEN, NOUN_CHEST)) + _vm->_dialogs->show(40849); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene409::setup() { + _game._player._spritesPrefix = ""; + + // The original is calling Scene4xx::setAAName() + _game._aaName = Resources::formatAAName(4); +} + +void Scene409::enter() { + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + teleporterEnter(); + + // The original is calling Scene4xx::sceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(10); +} + +void Scene409::step() { + teleporterStep(); +} + +void Scene409::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) + _vm->_dialogs->show(40910); + else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(40910); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(40911); + else if (_action.isAction(VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(40911); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(40912); + else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY) + || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY) + || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY) + || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY) + || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(40913); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE)) + _vm->_dialogs->show(40914); + else if (_action._lookFlag) + _vm->_dialogs->show(40914); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene410::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene410::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('y', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*ROXRC_7"); + + if (_game._objects.isInRoom(OBJ_CHARGE_CASES)) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + else + _scene->_hotspots.activate(NOUN_CHARGE_CASES, false); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(155, 150); + _game._player._facing = FACING_NORTH; + } + + sceneEntrySound(); + + _scene->loadAnimation(Resources::formatName(410, 'r', -1, EXT_AA, "")); + _scene->_activeAnimation->_resetFlag = true; +} + +void Scene410::step() { + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(2); + else + _scene->_activeAnimation->setCurrentFrame(0); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 9) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(10); + else + _scene->_activeAnimation->setCurrentFrame(8); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 5) { + if (_vm->getRandomNumber(1, 30) == 1) + _scene->_activeAnimation->setCurrentFrame(6); + else + _scene->_activeAnimation->setCurrentFrame(4); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 3) { + if (_vm->getRandomNumber(1, 2) == 1) + _scene->_activeAnimation->setCurrentFrame(4); + else // == 2 + _scene->_activeAnimation->setCurrentFrame(8); + } +} + +void Scene410::preActions() { + if (_action.isAction(VERB_TAKE) && !_action.isObject(NOUN_CHARGE_CASES)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_OPEN, NOUN_SACKS) || _action.isAction(VERB_OPEN, NOUN_SACK)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_CAN)) + _game._player._needToWalk = true; +} + +void Scene410::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 406; + else if (_action.isAction(VERB_TAKE, NOUN_CHARGE_CASES) && (_game._objects.isInRoom(OBJ_CHARGE_CASES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_hotspots.activate(NOUN_CHARGE_CASES, false); + _game._objects.addToInventory(OBJ_CHARGE_CASES); + _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41032); + break; + + case 2: + _game._player._priorTimer = _game._player._ticksAmount + _scene->_frameStartTime; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_BARREL)) + _vm->_dialogs->show(41010); + else if (_action.isAction(VERB_TAKE, NOUN_BARREL)) + _vm->_dialogs->show(41011); + else if (_action.isAction(VERB_OPEN, NOUN_BARREL)) + _vm->_dialogs->show(41012); + else if (_action.isAction(VERB_LOOK, NOUN_RUG)) + _vm->_dialogs->show(41013); + else if (_action.isAction(VERB_TAKE, NOUN_RUG)) + _vm->_dialogs->show(41014); + else if (_action.isAction(VERB_LOOK, NOUN_CARTON) || _action.isAction(VERB_OPEN, NOUN_CARTON)) { + if (_game._objects.isInRoom(OBJ_CHARGE_CASES)) + _vm->_dialogs->show(41015); + else + _vm->_dialogs->show(41016); + } else if (_action.isAction(VERB_LOOK, NOUN_FLOUR)) + _vm->_dialogs->show(41017); + else if (_action.isAction(VERB_TAKE, NOUN_FLOUR)) + _vm->_dialogs->show(41018); + else if (_action.isAction(VERB_LOOK, NOUN_SACKS)) + _vm->_dialogs->show(41019); + else if (_action.isAction(VERB_LOOK, NOUN_SACK)) + _vm->_dialogs->show(41019); + else if (_action.isAction(VERB_OPEN, NOUN_SACKS)) + _vm->_dialogs->show(41020); + else if (_action.isAction(VERB_OPEN, NOUN_SACK)) + _vm->_dialogs->show(41020); + else if (_action.isAction(VERB_LOOK, NOUN_BUCKET_OF_TAR)) + _vm->_dialogs->show(41021); + else if (_action.isAction(VERB_TAKE, NOUN_BUCKET_OF_TAR)) + _vm->_dialogs->show(41022); + else if (_action.isAction(VERB_LOOK, NOUN_CAN)) + _vm->_dialogs->show(41023); + else if (_action.isAction(VERB_TAKE, NOUN_CAN)) + _vm->_dialogs->show(41024); + else if (_action.isAction(VERB_LOOK, NOUN_CHARGE_CASES) && _game._objects.isInRoom(OBJ_CHARGE_CASES)) + _vm->_dialogs->show(41025); + else if (_action.isAction(VERB_LOOK, NOUN_FENCE)) + _vm->_dialogs->show(41027); + else if (_action.isAction(VERB_LOOK, NOUN_SHELVES)) + _vm->_dialogs->show(41028); + else if (_action.isAction(VERB_LOOK, NOUN_RAT)) + _vm->_dialogs->show(41029); + else if (_action.isAction(VERB_TAKE, NOUN_RAT)) + _vm->_dialogs->show(41030); + else if (_action.isAction(VERB_THROW, NOUN_RAT)) + _vm->_dialogs->show(41031); + else if (_action._lookFlag) + _vm->_dialogs->show(41033); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene411::Scene411(MADSEngine *vm) : Scene4xx(vm) { + _curAnimationFrame = -1; + _newIngredient = -1; + _newQuantity = -1; + _resetFrame = -1; + _badThreshold = -1; + + _killRox = false; + _makeMushroomCloud = false; +} + +void Scene411::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsSint32LE(_curAnimationFrame); + s.syncAsSint32LE(_newIngredient); + s.syncAsSint32LE(_newQuantity); + s.syncAsSint32LE(_resetFrame); + s.syncAsSint32LE(_badThreshold); + + s.syncAsByte(_killRox); + s.syncAsByte(_makeMushroomCloud); +} + +bool Scene411::addIngredient() { + bool retVal = false; + + switch (_newIngredient) { + case OBJ_LECITHIN: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 1) + retVal = true; + + _badThreshold = 1; + break; + + case OBJ_ALIEN_LIQUOR: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 0) + retVal = true; + + _badThreshold = 0; + break; + + case OBJ_FORMALDEHYDE: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 3) + retVal = true; + + _badThreshold = 3; + break; + + case OBJ_PETROX: + if (_globals[kIngredientList + _globals[kNextIngredient]] == 2) + retVal = true; + + _badThreshold = 2; + break; + + default: + break; + } + + if (!retVal && (_globals[kNextIngredient] == 0)) + _globals[kBadFirstIngredient] = _badThreshold; + + if (_globals[kNextIngredient] == 0) + retVal = true; + + return(retVal); +} + +bool Scene411::addQuantity() { + bool retVal = false; + + if (_globals[kIngredientQuantity + _globals[kNextIngredient]] == _newQuantity) + retVal = true; + + if (!retVal && (_globals[kNextIngredient] == 0)) + _globals[kBadFirstIngredient] = _badThreshold; + + if (_globals[kNextIngredient] == 0) + retVal = true; + + return(retVal); +} + +int Scene411::computeQuoteAndQuantity() { + int quoteId; + int quantity; + + switch (_action._activeAction._verbId) { + case 0x252: + quoteId = 0x26F; + quantity = 0; + break; + + case 0x253: + quoteId = 0x271; + quantity = 0; + break; + + case 0x254: + quoteId = 0x270; + quantity = 0; + break; + + case 0x255: + quoteId = 0x272; + quantity = 0; + break; + + case 0x256: + quoteId = 0x267; + quantity = 2; + break; + + case 0x257: + quoteId = 0x269; + quantity = 2; + break; + + case 0x258: + quoteId = 0x268; + quantity = 2; + break; + + case 0x259: + quoteId = 0x26A; + quantity = 2; + break; + + case 0x25A: + quoteId = 0x26B; + quantity = 3; + break; + + case 0x25B: + quoteId = 0x26D; + quantity = 3; + break; + + case 0x25C: + quoteId = 0x26C; + quantity = 3; + break; + + case 0x25D: + quoteId = 0x26E; + quantity = 3; + break; + + case 0x25E: + quoteId = 0x263; + quantity = 1; + break; + + case 0x25F: + quoteId = 0x265; + quantity = 1; + break; + + case 0x260: + quoteId = 0x264; + quantity = 1; + break; + + case 0x261: + quoteId = 0x266; + quantity = 1; + break; + + default: + quoteId = 0; + quantity = 0; + break; + } + + _scene->_kernelMessages.add(Common::Point(202, 82), 0x1110, 32, 0, 120, _game.getQuote(quoteId)); + return quantity; +} + +void Scene411::handleKettleAction() { + switch (_globals[kNextIngredient]) { + case 1: + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], + false, 15, 0, 0, 0); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], + false, 6, 0, 0, 0); + break; + + case 3: + _makeMushroomCloud = true; + break; + + default: + break; + } +} + +void Scene411::handleDialog() { + if ((_action._activeAction._verbId != 0x262) && (_game._trigger == 0)) { + if (_game._objects.isInInventory(_newIngredient)) { + switch (_newIngredient) { + case OBJ_FORMALDEHYDE: + _resetFrame = 17; + break; + + case OBJ_PETROX: + _resetFrame = 55; + break; + + case OBJ_LECITHIN: + _resetFrame = 36; + break; + + default: + _resetFrame = 112; + break; + } + + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + } + _scene->_kernelMessages.reset(); + _newQuantity = computeQuoteAndQuantity (); + + if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1)) + _killRox = true; + else if (addIngredient() && addQuantity()) { + handleKettleAction(); + _globals[kNextIngredient]++; + } else + _killRox = true; + + _scene->_userInterface.setup(kInputBuildingSentences); + } else if (_action._activeAction._verbId == 0x262) + _scene->_userInterface.setup(kInputBuildingSentences); +} + +void Scene411::giveToRex(int object) { + switch (object) { + case 0: + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + break; + + case 1: + _game._objects.addToInventory(OBJ_LECITHIN); + break; + + case 2: + _game._objects.addToInventory(OBJ_PETROX); + break; + + case 3: + _game._objects.addToInventory(OBJ_FORMALDEHYDE); + break; + + default: + break; + } +} + +void Scene411::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_ALIEN_LIQUOR); + _scene->addActiveVocab(NOUN_FORMALDEHYDE); + _scene->addActiveVocab(NOUN_PETROX); + _scene->addActiveVocab(NOUN_LECITHIN); +} + +void Scene411::enter() { + if (_scene->_priorSceneId == 411) { + if ((_globals[kNextIngredient] == 1) && (_globals[kBadFirstIngredient] > -1)) + giveToRex(_globals[kBadFirstIngredient]); + else if (_globals[kNextIngredient] > 0) { + for (int i = 0; i < _globals[kNextIngredient]; i ++) + giveToRex(_globals[kIngredientList + i]); + } + _globals[kNextIngredient] = 0; + _globals[kBadFirstIngredient] = -1; + } + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('f', 2)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('c', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('a', 6)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*ROXRC_9"); + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 50, 0, 0, 0); + + _game.loadQuoteSet(0x252, 0x25E, 0x25A, 0x256, 0x253, 0x25F, 0x25B, 0x257, 0x254, 0x260, 0x25C, 0x258, 0x255, + 0x261, 0x25D, 0x259, 0x262, 0x267, 0x263, 0x26B, 0x26F, 0x268, 0x264, 0x26C, 0x270, 0x26A, 0x266, 0x26E, + 0x272, 0x269, 0x265, 0x26D, 0x271, 0); + + _dialog1.setup(0x5B, 0x252, 0x25E, 0x25A, 0x256, 0x262, -1); + _dialog2.setup(0x5C, 0x253, 0x25F, 0x25B, 0x257, 0x262, -1); + _dialog3.setup(0x5D, 0x254, 0x260, 0x25C, 0x258, 0x262, -1); + _dialog4.setup(0x5E, 0x255, 0x261, 0x25D, 0x259, 0x262, -1); + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_hotspots.activate(NOUN_KETTLE, true); + } else { + _scene->_hotspots.activate(NOUN_KETTLE, false); + _scene->_hotspots.activate(NOUN_EXPLOSIVES, true); + } + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + } else if (!_game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + switch (_globals[kNextIngredient]) { + case 1: + _vm->_sound->command(53); + break; + + case 2: + _vm->_sound->command(53); + _vm->_sound->command(54); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); + break; + + case 3: + _vm->_sound->command(53); + _vm->_sound->command(54); + _vm->_sound->command(55); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + break; + + case 4: + _vm->_sound->command(53); + _vm->_sound->command(54); + _vm->_sound->command(55); + _vm->_sound->command(56); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 0, 0, 0); + break; + + default: + _vm->_sound->command(10); + break; + } + } + + if (_globals[kNextIngredient] >= 4 && _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + } + + if (_game._objects.isInRoom(OBJ_FORMALDEHYDE)) { + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 1); + int idx = _scene->_dynamicHotspots.add(NOUN_FORMALDEHYDE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(206, 145), FACING_SOUTHEAST); + } + + if (_game._objects.isInRoom(OBJ_PETROX)) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_PETROX, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(186, 112), FACING_NORTHEAST); + } + + if (_game._objects.isInRoom(OBJ_LECITHIN)) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_LECITHIN, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(220, 121), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(60, 146); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_ALIEN_LIQUOR); + _game._objects.addToInventory(OBJ_CHARGE_CASES); + _game._objects.addToInventory(OBJ_TAPE_PLAYER); + _game._objects.addToInventory(OBJ_AUDIO_TAPE); + } + + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->setCurrentFrame(128); + + _makeMushroomCloud = false; + _killRox = false; +} + +void Scene411::step() { + if (_scene->_activeAnimation != nullptr) { + if (_curAnimationFrame != _scene->_activeAnimation->getCurrentFrame()) { + _curAnimationFrame = _scene->_activeAnimation->getCurrentFrame(); + _resetFrame = -1; + + switch (_curAnimationFrame) { + case 16: + _game._player._stepEnabled = true; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _resetFrame = 128; + break; + + case 35: + case 54: + case 71: + case 127: + if (_killRox) { + _resetFrame = 72; + } else { + _resetFrame = 0; + _game._objects.removeFromInventory(_newIngredient, NOWHERE); + switch (_globals[kNextIngredient]) { + case 1: + _vm->_sound->command(53); + break; + + case 2: + _vm->_sound->command(54); + break; + + case 3: + _vm->_sound->command(55); + break; + + case 4: + _vm->_sound->command(56); + break; + + default: + break; + } + } + break; + + case 22: + case 41: + case 59: + case 115: + if (_makeMushroomCloud) { + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0); + _makeMushroomCloud = false; + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_hotspots.activate(NOUN_KETTLE, true); + } + break; + + case 111: + _resetFrame = 111; + _scene->_reloadSceneFlag = true; + break; + + case 129: + _resetFrame = 128; + break; + + default: + break; + } + + if ((_resetFrame >= 0) && (_resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + _curAnimationFrame = _resetFrame; + } + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 86) + _vm->_sound->command(59); +} + +void Scene411::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE))) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) || _action.isAction(VERB_LOOK, NOUN_KETTLE) || _action.isAction(VERB_LOOK, NOUN_MISHAP) || + _action.isAction(VERB_LOOK, NOUN_ALCOVE) || _action.isAction(VERB_LOOK, NOUN_SINK) || _action.isAction(VERB_PUT, NOUN_SINK) || + _action.isAction(VERB_LOOK, NOUN_EXPERIMENT) || _action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD)) + _game._player._needToWalk = true; + + if (_action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH)) + _game._player._needToWalk = false; +} + +void Scene411::actions() { + if (_game._screenObjects._inputMode != 1) { + handleDialog(); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_WALK_INTO, NOUN_CORRIDOR_TO_SOUTH)) { + _scene->_nextSceneId = 406; + _vm->_sound->command(10); + _action._inProgress = false; + return; + } + + if ((_globals[kNextIngredient] >= 4) && (_action.isAction(VERB_TAKE, NOUN_EXPLOSIVES) || _action.isAction(VERB_PUT, NOUN_CHARGE_CASES, NOUN_EXPLOSIVES)) + && !_game._objects[OBJ_CHARGE_CASES].getQuality(3) + && _game._objects.isInInventory(OBJ_CHARGE_CASES)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(10); + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + break; + + case 110: { + int idx = _globals._sequenceIndexes[10]; + _globals._sequenceIndexes[10] = _scene->_sequences.startCycle(_globals._spriteIndexes[10], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], idx); + _scene->_sequences.addTimer(180, 111); + } + break; + + case 111: + _scene->_hotspots.activate(NOUN_KETTLE, true); + _scene->_hotspots.activate(NOUN_EXPLOSIVES, false); + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], true, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + + _globals._sequenceIndexes[10] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[10], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[10], SEQUENCE_TRIGGER_EXPIRE, 0, 112); + // No break on purpose + case 112: + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + _game._objects[OBJ_CHARGE_CASES].setQuality(3, 1); + _vm->_dialogs->showItem(OBJ_CHARGE_CASES, 41142); + break; + } + _action._inProgress = false; + return; + } else if (!_game._objects.isInInventory(OBJ_CHARGE_CASES) && _action.isAction(VERB_TAKE, NOUN_EXPLOSIVES)) { + _vm->_dialogs->show(41143); + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_PETROX) && (_game._objects.isInRoom(OBJ_PETROX) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._objects.addToInventory(OBJ_PETROX); + _vm->_dialogs->showItem(OBJ_PETROX, 41120); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_LECITHIN) && (_game._objects.isInRoom(OBJ_LECITHIN) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _game._objects.addToInventory(OBJ_LECITHIN); + _vm->_dialogs->showItem(OBJ_LECITHIN, 41124); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + break; + + default: + break; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_FORMALDEHYDE) && _game._objects.isInRoom(OBJ_FORMALDEHYDE) && (_game._trigger == 0)) { + _vm->_sound->command(57); + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[11], 1); + _scene->_sequences.addTimer(20, 100); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _game._objects.addToInventory(OBJ_FORMALDEHYDE); + _action._inProgress = false; + return; + } + + if (_game._trigger == 100) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + _scene->_sequences.addTimer(20, 10); + } + + if (_game._trigger == 10) + _vm->_dialogs->showItem(OBJ_FORMALDEHYDE, 41124); + + if (_action.isAction(VERB_PUT, NOUN_KETTLE)) { + if (_action.isObject(NOUN_PETROX) || _action.isObject(NOUN_FORMALDEHYDE) || _action.isObject(NOUN_LECITHIN) || _action.isObject(NOUN_ALIEN_LIQUOR)) { + _newIngredient = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + switch (_newIngredient) { + case OBJ_ALIEN_LIQUOR: + _dialog1.start(); + break; + + case OBJ_FORMALDEHYDE: + _dialog3.start(); + break; + + case OBJ_PETROX: + _dialog4.start(); + break; + + case OBJ_LECITHIN: + _dialog2.start(); + break; + + default: + break; + } + } + } + + + if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(41110); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_PURIFIER)) + _vm->_dialogs->show(41111); + else if (_action.isAction(VERB_LOOK, NOUN_LAB_EQUIPMENT)) + _vm->_dialogs->show(41112); + else if (_action.isAction(VERB_LOOK, NOUN_KNIFE_SWITCH)) + _vm->_dialogs->show(41113); + else if (_action.isAction(VERB_PUSH, NOUN_KNIFE_SWITCH) || _action.isAction(VERB_PULL, NOUN_KNIFE_SWITCH)) + _vm->_dialogs->show(41114); + else if (_action.isAction(VERB_LOOK, NOUN_TOXIC_WASTE)) + _vm->_dialogs->show(41115); + else if (_action.isAction(VERB_TAKE, NOUN_TOXIC_WASTE)) + _vm->_dialogs->show(41116); + else if (_action.isAction(VERB_LOOK, NOUN_DRAWING_BOARD)) + _vm->_dialogs->show(41117); + else if (_action.isAction(VERB_LOOK, NOUN_EXPERIMENT)) + _vm->_dialogs->show(41118); + else if (_action.isAction(VERB_LOOK, NOUN_PETROX) && _game._objects.isInRoom(OBJ_PETROX)) + _vm->_dialogs->show(41119); + else if (_action.isAction(VERB_LOOK, NOUN_ALCOVE)) + _vm->_dialogs->show(41121); + else if ((_action.isAction(VERB_LOOK, NOUN_FORMALDEHYDE)) && (_game._objects.isInRoom(OBJ_FORMALDEHYDE))) + _vm->_dialogs->show(41122); + else if ((_action.isAction(VERB_LOOK, NOUN_LECITHIN)) && (_game._objects.isInRoom(OBJ_LECITHIN))) + _vm->_dialogs->show(41123); + else if (_action.isAction(VERB_LOOK, NOUN_KETTLE)) { + if (_globals[kNextIngredient] > 0 && !_game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _vm->_dialogs->show(41126); + } else if (_globals[kNextIngredient] == 0 || _game._objects[OBJ_CHARGE_CASES].getQuality(3)) { + _vm->_dialogs->show(41125); + } + } else if (_action.isAction(VERB_LOOK, NOUN_EXPLOSIVES) && _game._objects[OBJ_CHARGE_CASES].getQuality(3) == 0) { + _vm->_dialogs->show(41127); + } else if (_action.isAction(VERB_TAKE, NOUN_KETTLE)) + _vm->_dialogs->show(41128); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(41129); + else if (_action.isAction(VERB_LOOK, NOUN_MISHAP)) + _vm->_dialogs->show(41130); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(41131); + else if (_action._lookFlag) + _vm->_dialogs->show(41132); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_HORN)) + _vm->_dialogs->show(41133); + else if (_action.isAction(VERB_LOOK, NOUN_DEBRIS)) + _vm->_dialogs->show(41134); + else if (_action.isAction(VERB_LOOK, NOUN_HEATER)) + _vm->_dialogs->show(41135); + else if (_action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(41136); + else if (_action.isAction(VERB_LOOK, NOUN_SINK)) + _vm->_dialogs->show(41137); + else if (_action.isAction(VERB_PUT, NOUN_SINK)) + _vm->_dialogs->show(41138); + else if (_action.isAction(VERB_TAKE, NOUN_EXPERIMENT)) + _vm->_dialogs->show(41139); + else if (_action.isAction(VERB_LOOK, NOUN_ELECTRODES)) + _vm->_dialogs->show(41140); + else if (_action.isAction(VERB_TAKE, NOUN_ELECTRODES)) + _vm->_dialogs->show(41141); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene413::Scene413(MADSEngine *vm) : Scene4xx(vm) { + _rexDeath = -1; + _canMove = -1; +} + +void Scene413::synchronize(Common::Serializer &s) { + Scene4xx::synchronize(s); + + s.syncAsSint32LE(_rexDeath); + s.syncAsSint32LE(_canMove); +} + +void Scene413::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene413::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _rexDeath = false; + + if (_scene->_priorSceneId == 405) { + _game._player._playerPos = Common::Point(142, 146); + _game._player._facing = FACING_NORTH; + _game._player._visible = true; + } else if (_scene->_priorSceneId != -2) { + if (_globals[kSexOfRex] == REX_MALE) { + _scene->loadAnimation(Resources::formatName(413, 'd', 1, EXT_AA, ""), 78); + _vm->_sound->command(30); + _game._player._visible = false; + _game._player._stepEnabled = false; + _rexDeath = true; + } else if (!_globals[kTeleporterCommand]) { + _game._player._playerPos = Common::Point(136, 117); + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._facing = FACING_SOUTH; + _game._player._visible = true; + } + } + + if ((_globals[kTeleporterCommand]) && (!_rexDeath)) { + switch (_globals[kTeleporterCommand]) { + case 1: + _vm->_sound->command(30); + _game._player._visible = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 76); + break; + + case 2: + _game._player._visible = false; + _vm->_sound->command(30); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 20); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 77); + break; + + case 3: + case 4: + _game._player._playerPos = Common::Point(136, 117); + _game._player._facing = FACING_SOUTH; + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + _globals[kTeleporterCommand] = 0; + } + + _canMove = true; + sceneEntrySound(); +} + +void Scene413::step() { + if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 38) + _scene->_activeAnimation->setCurrentFrame(37); + + if (_scene->_activeAnimation && _scene->_activeAnimation->getCurrentFrame() == 21 && _canMove) { + _vm->_sound->command(27); + _canMove = false; + } + + if (_game._trigger == 76) { + _game._player._playerPos = Common::Point(136, 117); + _game._player.walk(Common::Point(141, 130), FACING_SOUTH); + _game._player._facing = FACING_SOUTH; + _game._player.selectSeries(); + _game._player._visible = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 77) { + _globals[kTeleporterCommand] = TELEPORTER_BEAM_IN; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_game._trigger == 78) { + _scene->_reloadSceneFlag = true; + _scene->_nextSceneId = _scene->_priorSceneId; + _globals[kTeleporterCommand] = TELEPORTER_NONE; + } +} + +void Scene413::preActions() { + if (_action.isAction(VERB_TAKE) || _action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE) || _action.isAction(VERB_LOOK, NOUN_DISPLAY) + || _action.isAction(VERB_LOOK, NOUN_PICTURE) || _action.isAction(VERB_LOOK, NOUN_PLANT)) { + _game._player._needToWalk = true; + } +} + +void Scene413::actions() { + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 409; + } else if (_action.isAction(VERB_WALK_INSIDE, NOUN_CORRIDOR_TO_SOUTH)) + _scene->_nextSceneId = 405; + else if (_action.isAction(VERB_LOOK, NOUN_WOODEN_STATUE)) + _vm->_dialogs->show(41310); + else if (_action.isAction(VERB_TAKE, NOUN_WOODEN_STATUE)) + _vm->_dialogs->show(41311); + else if (_action.isAction(VERB_LOOK, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(41312); + else if (_action.isAction(VERB_PUT, NOUN_CONVEYOR_BELT)) + _vm->_dialogs->show(41313); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(41314); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(41315); + else if (_action.isAction(VERB_LOOK, NOUN_CORRIDOR_TO_SOUTH)) + _vm->_dialogs->show(41316); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(41317); + else if (_action.isAction(VERB_LOOK, NOUN_PLANT)) + _vm->_dialogs->show(41318); + else if (_action.isAction(VERB_TAKE, NOUN_PLANT)) + _vm->_dialogs->show(41319); + else if (_action._lookFlag) + _vm->_dialogs->show(41320); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes4.h b/engines/mads/nebular/nebular_scenes4.h new file mode 100644 index 0000000000..fbd5ce81f0 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes4.h @@ -0,0 +1,258 @@ +/* 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 MADS_NEBULAR_SCENES4_H +#define MADS_NEBULAR_SCENES4_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene4xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene4xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene401 : public Scene4xx { +private: + bool _northFl; + Common::Point _destPos; + uint32 _timer; + +public: + Scene401(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene402 : public Scene4xx { +private: + bool _lightOn; + bool _blowingSmoke; + bool _leftWomanMoving; + bool _rightWomanMoving; + bool _firstTalkToGirlInChair; + bool _waitingGinnyMove; + bool _ginnyLooking; + bool _bigBeatFl; + bool _roxOnStool; + bool _bartenderSteady; + bool _bartenderHandsHips; + bool _bartenderLooksLeft; + bool _bartenderReady; + bool _bartenderTalking; + bool _bartenderCalled; + bool _conversationFl; + bool _activeTeleporter; + bool _activeArrows; + bool _activeArrow1; + bool _activeArrow2; + bool _activeArrow3; + bool _cutSceneReady; + bool _cutSceneNeeded; + bool _helgaReady; + bool _refuseAlienLiquor; + + int _drinkTimer; + int _beatCounter; + int _bartenderMode; + int _bartenderDialogNode; + int _bartenderCurrentQuestion; + int _helgaTalkMode; + int _roxMode; + int _rexMode; + int _talkTimer; + + Conversation _dialog1; + Conversation _dialog2; + Conversation _dialog3; + Conversation _dialog4; + + void setDialogNode(int node); + void handleConversation1(); + void handleConversation2(); + void handleConversation3(); + void handleConversation4(); + void handleDialogs(); + +public: + Scene402(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene405 : public Scene4xx { +public: + Scene405(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene406 : public Scene4xx { +private: + bool _hitStorageDoor; + +public: + Scene406(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene407 : public Scene4xx { +private: + bool _fromNorth; + Common::Point _destPos; + +public: + Scene407(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene408 : public Scene4xx { +public: + Scene408(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene409 : public SceneTeleporter { +public: + Scene409(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene410 : public Scene4xx { +public: + Scene410(MADSEngine *vm) : Scene4xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene411 : public Scene4xx { +private: + int _curAnimationFrame; + int _newIngredient; + int _newQuantity; + int _resetFrame; + int _badThreshold; + + bool _killRox; + bool _makeMushroomCloud; + + Conversation _dialog1; + Conversation _dialog2; + Conversation _dialog3; + Conversation _dialog4; + + void giveToRex(int object); + void handleDialog(); + void handleKettleAction(); + + int computeQuoteAndQuantity(); + + bool addQuantity(); + bool addIngredient(); + +public: + Scene411(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene413 : public Scene4xx { +private: + int _rexDeath; + int _canMove; + +public: + Scene413(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES4_H */ diff --git a/engines/mads/nebular/nebular_scenes5.cpp b/engines/mads/nebular/nebular_scenes5.cpp new file mode 100644 index 0000000000..fd5e244872 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes5.cpp @@ -0,0 +1,2872 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes5.h" + +namespace MADS { + +namespace Nebular { + +void Scene5xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene5xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 502) || (_scene->_nextSceneId == 504) || (_scene->_nextSceneId == 505) || (_scene->_nextSceneId == 515)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else if ((_scene->_nextSceneId == 501) || (_scene->_nextSceneId == 503) || (_scene->_nextSceneId == 551)) + _game._player._spritesPrefix = "ROX"; + + _game._player._scalingVelocity = true; + + if ((_scene->_nextSceneId == 512) || (_scene->_nextSceneId == 507)) + _game._player._scalingVelocity = false; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene5xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 501: + case 502: + case 504: + case 505: + case 506: + case 507: + case 508: + case 511: + case 512: + case 513: + case 515: + case 551: + if (_scene->_priorSceneId == 503) + _vm->_sound->command(38); + else + _vm->_sound->command(29); + break; + case 503: + _vm->_sound->command(41); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene501::Scene501(MADSEngine *vm) : Scene5xx(vm) { + _mainSequenceId = -1; + _mainSpriteId = -1; + _doorHotspotid = -1; + + _rexPunched = false; +} + +void Scene501::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_mainSequenceId); + s.syncAsSint16LE(_mainSpriteId); + s.syncAsSint16LE(_doorHotspotid); + s.syncAsByte(_rexPunched); +} + +void Scene501::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DOOR); + _scene->addActiveVocab(VERB_WALK_THROUGH); +} + +void Scene501::handleSlotActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + int numTicks, frameIndex; + if (_globals[kSexOfRex] == REX_MALE) { + _mainSpriteId = _globals._spriteIndexes[4]; + numTicks = 8; + frameIndex = 3; + } else { + _mainSpriteId = _globals._spriteIndexes[5]; + numTicks = 10; + frameIndex = 2; + } + + _mainSequenceId = _scene->_sequences.startReverseCycle(_mainSpriteId, false, numTicks, 1, 0, 0); + _scene->_sequences.setAnimRange(_mainSequenceId, 1, frameIndex); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _vm->_sound->command(10); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_SPRITE, frameIndex, 1); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _mainSequenceId); + _game._player._visible = true; + _scene->_sequences.addTimer(15, 3); + break; + + case 3: + _game._player.walk(Common::Point(282, 110), FACING_NORTH); + _scene->_sequences.addTimer(60, 4); + break; + + default: + break; + } +} + +void Scene501::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + + if (_globals[kSexOfRex] == REX_MALE) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXCD_7"); + } else { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*ROXRC_9"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites("*ROXCD_7"); + } + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _doorHotspotid = _scene->_dynamicHotspots.setPosition(idx,Common::Point(282, 110), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _rexPunched = true; + + if (_scene->_priorSceneId == 504) { + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(74, 121); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + if (_globals[kSexOfRex] == REX_MALE) + _scene->loadAnimation(formAnimName('G', 2), 70); + else + _scene->loadAnimation(formAnimName('R', 2), 70); + } else if (_scene->_priorSceneId == 503) { + _game._player._playerPos = Common::Point(317, 102); + _game._player._facing = FACING_SOUTHWEST; + _scene->_sequences.addTimer(15, 80); + } else if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(299, 131); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_FAKE_ID); + _game._objects.addToInventory(OBJ_SECURITY_CARD); + _game._objects.addToInventory(OBJ_ID_CARD); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x275, 0x276, 0x277, 0); + + if (!_game._visitedScenes._sceneRevisited) + _scene->_sequences.addTimer(2, 90); +} + +void Scene501::step() { + if (_game._trigger == 90) + _vm->_dialogs->show(50127); + + if (_game._trigger >= 80) { + switch (_game._trigger) { + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 6, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _scene->_dynamicHotspots.remove(_doorHotspotid); + _game._player.walk(Common::Point(276, 110), FACING_SOUTHWEST); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(12); + _doorHotspotid = _scene->_dynamicHotspots.add(NOUN_DOOR, VERB_WALK_THROUGH, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_globals._sequenceIndexes[3], Common::Point(282, 110), FACING_NORTH); + _scene->_dynamicHotspots.setCursor(_doorHotspotid, CURSOR_GO_UP); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + break; + + case 83: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + break; + + default: + break; + } + } + + if (_game._trigger >= 70 && _game._trigger <= 73) { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(15, 71); + break; + + case 71: + _game._player.walk(Common::Point(92, 130), FACING_SOUTH); + _scene->_sequences.addTimer(30, 72); + break; + + case 72: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + break; + + default: + break; + } + } +} + +void Scene501::preActions() { + if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_EAST) || _action.isObject(NOUN_SIDEWALK_TO_EAST))) + _game._player._walkOffScreenSceneId = 551; +} + +void Scene501::actions() { + if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) + _mainSpriteId = _globals._spriteIndexes[6]; + else + _mainSpriteId = _globals._spriteIndexes[7]; + + _mainSequenceId = _scene->_sequences.addSpriteCycle(_mainSpriteId, false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _scene->_sequences.addSubEntry(_mainSequenceId, SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _mainSequenceId; + _mainSequenceId = _scene->_sequences.startCycle(_mainSpriteId, false, -2); + _scene->_sequences.setMsgLayout(_mainSequenceId); + _scene->_sequences.updateTimeout(_mainSequenceId, syncIdx); + _scene->_sequences.addTimer(30, 4); + } + break; + + case 4: + _scene->_nextSceneId = 504; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT)) + _vm->_dialogs->show(50113); + else if (_action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + case 1: + case 2: + case 3: + handleSlotActions(); + break; + + case 4: + if (_globals[kSexOfRex] == REX_MALE) { + _game._player._visible = false; + _vm->_sound->command(13); + _scene->loadAnimation(formAnimName('G', 1), 5); + } else { + _rexPunched = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 6, 120, _game.getQuote(0x277)); + } + break; + + case 5: + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 6); + break; + + case 6: + if (_globals[kSexOfRex] == REX_MALE) { + if (_rexPunched) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x275)); + _rexPunched = false; + } else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x276)); + } + } + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + case 1: + case 2: + case 3: + handleSlotActions(); + break; + + case 4: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.remove(_doorHotspotid); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _vm->_sound->command(11); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 6); + break; + + case 6: + _game._player.walk(Common::Point(317, 102), FACING_NORTHEAST); + _scene->_sequences.addTimer(120, 7); + break; + + case 7: { + _vm->_sound->command(12); + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _vm->_sound->command(12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + } + break; + + case 8: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 503; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(50121); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(50110); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(50112); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(50114); + else if (_action.isAction(VERB_TAKE, NOUN_SIGN)) + _vm->_dialogs->show(50115); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_EAST)) + _vm->_dialogs->show(50118); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) + || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(50119); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(50120); + else if (_action.isAction(VERB_OPEN, NOUN_DOOR)) + _vm->_dialogs->show(50122); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(50123); + else if (_action.isAction(VERB_OPEN, NOUN_FIRE_HYDRANT)) + _vm->_dialogs->show(50124); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD)) + _vm->_dialogs->show(50125); + else if (_action.isAction(VERB_LOOK, NOUN_PIPES) || _action.isAction(VERB_LOOK, NOUN_PIPE)) + _vm->_dialogs->show(50126); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) { + if (!_game._visitedScenes.exists(504)) + _vm->_dialogs->show(50116); + else + _vm->_dialogs->show(50117); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene502::setup() { + _game._player._spritesPrefix = ""; + // The original is using Scene5xx_setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene502::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + + teleporterEnter(); + + // The original uses scene5xx_sceneEntrySound + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else if (_scene->_priorSceneId == 503) + _vm->_sound->command(38); + else + _vm->_sound->command(29); +} + +void Scene502::step() { + teleporterStep(); +} + +void Scene502::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(50210); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(50211); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(50212); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(50213); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag) + _vm->_dialogs->show(50214); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene503::Scene503(MADSEngine *vm) : Scene5xx(vm) { + _detonatorHotspotId = -1; +} + +void Scene503::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_detonatorHotspotId); +} + +void Scene503::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_DETONATORS); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene503::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMBD_2"); + else + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*ROXBD_2"); + + if (_game._objects[OBJ_DETONATORS]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _detonatorHotspotId = _scene->_dynamicHotspots.add(NOUN_DETONATORS, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_detonatorHotspotId, Common::Point(254, 135), FACING_SOUTH); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(191, 152); + _game._player._facing = FACING_NORTHWEST; + } + + sceneEntrySound(); +} + +void Scene503::actions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _scene->_nextSceneId = 501; + else if (_action.isAction(VERB_TAKE, NOUN_DETONATORS)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_DETONATORS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_detonatorHotspotId); + _game._objects.addToInventory(OBJ_DETONATORS); + _vm->_dialogs->showItem(OBJ_DETONATORS, 50326); + break; + + case 2: + if (_globals[kSexOfRex] == REX_MALE) + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + else + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(50328); + else if (_action.isAction(VERB_LOOK, NOUN_MONITORING_EQUIPMENT)) + _vm->_dialogs->show(50310); + else if (_action.isAction(VERB_LOOK, NOUN_PHOTON_RIFLES)) + _vm->_dialogs->show(50311); + else if (_action.isAction(VERB_TAKE, NOUN_PHOTON_RIFLES) || _action.isAction(VERB_TAKE, NOUN_NUCLEAR_SLINGSHOT)) + _vm->_dialogs->show(50312); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY_CASE)) + _vm->_dialogs->show(50313); + else if (_action.isAction(VERB_LOOK, NOUN_NUCLEAR_SLINGSHOT)) + _vm->_dialogs->show(50314); + else if (_action.isAction(VERB_LOOK, NOUN_WATER_COOLER)) + _vm->_dialogs->show(50315); + else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(50316); + else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(50317); + else if (_action.isAction(VERB_LOOK, NOUN_WARNING_LABEL)) + _vm->_dialogs->show(50318); + else if (_action.isAction(VERB_LOOK, NOUN_DESK)) + _vm->_dialogs->show(50319); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(50320); + else if (_action.isAction(VERB_LOOK, NOUN_FILE_CABINETS)) + _vm->_dialogs->show(50322); + else if (_action.isAction(VERB_LOOK, NOUN_BOX)) { + if (_game._objects.isInRoom(OBJ_DETONATORS)) + _vm->_dialogs->show(50323); + else + _vm->_dialogs->show(50324); + } else if (_action.isAction(VERB_LOOK, NOUN_DETONATORS) && (_action._savedFields._mainObjectSource == 4)) + _vm->_dialogs->show(50325); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOWS)) + _vm->_dialogs->show(50327); + else if (_action.isAction(VERB_OPEN, NOUN_DISPLAY_CASE)) + _vm->_dialogs->show(50329); + else if (_action.isAction(VERB_THROW, NOUN_DISPLAY_CASE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(50330); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene504::Scene504(MADSEngine *vm) : Scene5xx(vm) { + _carAnimationMode = -1; + _carFrame = -1; +} + +void Scene504::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_carAnimationMode); + s.syncAsSint16LE(_carFrame); +} + +void Scene504::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene504::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + for (int i = 0; i < 4; i++) + _globals._spriteIndexes[5 + i] = _scene->_sprites.addSprites(formAnimName('m', i)); + + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _scene->changeVariant(1); + } + + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 0); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 0, 0, 0); + _carFrame = -1; + + if ((_scene->_priorSceneId == 505) && (_globals[kHoverCarDestination] != _globals[kHoverCarLocation])){ + _carAnimationMode = 1; + _scene->loadAnimation(formAnimName('A', -1)); + _vm->_sound->command(14); + _scene->_sequences.addTimer(1, 70); + _game._player._stepEnabled = false; + } else { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _carAnimationMode = 1; + _scene->loadAnimation(formAnimName('A', -1)); + if ((_scene->_priorSceneId != -2) && (_scene->_priorSceneId != 505)) + _globals[kHoverCarLocation] = _scene->_priorSceneId; + + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + } + + if (_globals[kTimebombTimer] > 10500) + _globals[kTimebombTimer] = 10500; + + sceneEntrySound(); +} + +void Scene504::step() { + if ((_carAnimationMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame; + + if (_carFrame == 1) + nextFrame = 0; + else + nextFrame = -1; + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + if (_globals[kHoverCarDestination] != -1) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _carAnimationMode = 2; + if (((_globals[kHoverCarLocation] >= 500 && _globals[kHoverCarLocation] <= 599) && + (_globals[kHoverCarDestination] >= 500 && _globals[kHoverCarDestination] <= 599)) || + ((_globals[kHoverCarLocation] >= 600 && _globals[kHoverCarLocation] <= 699) && + (_globals[kHoverCarDestination] >= 600 && _globals[kHoverCarDestination] <= 699))) { + _scene->loadAnimation(formAnimName('A', -1), 71); + } else if (_globals[kHoverCarLocation] > _globals[kHoverCarDestination]) + _scene->loadAnimation(formAnimName('C', -1), 71); + else + _scene->loadAnimation(formAnimName('B', -1), 71); + } + break; + + case 71: + _vm->_sound->command(15); + _scene->_nextSceneId = _globals[kHoverCarDestination]; + break; + + default: + break; + } + } + + if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_game._difficulty != 3)) { + _globals[kTimebombStatus] = TIMEBOMB_DEAD; + _globals[kTimebombTimer] = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } +} + +void Scene504::preActions() { + _game._player._needToWalk = false; +} + +void Scene504::actions() { + if (_action.isAction(VERB_EXIT_FROM, NOUN_CAR)) { + _vm->_sound->command(15); + _scene->_nextSceneId = _globals[kHoverCarLocation]; + } else if (_action.isAction(VERB_ACTIVATE, NOUN_CAR_CONTROLS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _vm->_sound->command(39); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 18, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 14); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 13); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + } + break; + + case 2: + _scene->_sequences.addTimer(10, 3); + break; + + case 3: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + if (_globals[kSexOfRex] == REX_MALE) { + _vm->_sound->command(34); + _scene->_sequences.addTimer(60, 4); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 14); + } else { + _vm->_sound->command(40); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 18, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 14); + _scene->_sequences.addTimer(120, 5); + } + break; + + case 4: + _game._player._stepEnabled = true; + _globals[kHoverCarDestination] = _globals[kHoverCarLocation]; + _scene->_nextSceneId = 505; + break; + + case 5: + _game._player._stepEnabled = true; + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _vm->_dialogs->show(50421); + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_INTERIOR_OF_CAR)) + _vm->_dialogs->show(50412); + else if (_action.isAction(VERB_LOOK, NOUN_GLOVE_COMPARTMENT)) + _vm->_dialogs->show(50410); + else if (_action.isAction(VERB_LOOK, NOUN_CAR_CONTROLS) || _action.isAction(VERB_LOOK, NOUN_DASHBOARD)) + _vm->_dialogs->show(50411); + else if (_action.isAction(VERB_LOOK, NOUN_SCENT_PACKET)) + _vm->_dialogs->show(50413); + else if (_action.isAction(VERB_LOOK, NOUN_SODA_CANS)) + _vm->_dialogs->show(50414); + else if (_action.isAction(VERB_LOOK, NOUN_KITTY)) + _vm->_dialogs->show(50415); + else if (_action.isAction(VERB_LOOK, NOUN_WINDSHIELD) || _action.isAction(VERB_LOOK_THROUGH, NOUN_WINDSHIELD)) + _vm->_dialogs->show(50416); + else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR)) + _vm->_dialogs->show(50417); + else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR)) + _vm->_dialogs->show(50418); + else if (_action.isAction(VERB_LOOK, NOUN_MOLDY_SOCK)) + _vm->_dialogs->show(50419); + else if (_action.isAction(VERB_TAKE, NOUN_MOLDY_SOCK)) + _vm->_dialogs->show(50420); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene505::Scene505(MADSEngine *vm) : Scene5xx(vm) { + _frame = -1; + _nextButtonId = -1; + _homeSelectedId = -1; + _selectedId = -1; + _activeCars = -1; + + for (int i = 0; i < 9; i++) + _carLocations[i] = -1; +} + +void Scene505::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_frame); + s.syncAsSint16LE(_nextButtonId); + s.syncAsSint16LE(_homeSelectedId); + s.syncAsSint16LE(_selectedId); + s.syncAsSint16LE(_activeCars); + + for (int i = 0; i < 9; i++) + s.syncAsSint16LE(_carLocations[i]); +} + +void Scene505::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene505::enter() { + for (int i = 0; i < 9; i++) + _globals._spriteIndexes[i] = _scene->_sprites.addSprites(formAnimName('a', i + 1)); + + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('t', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('e', -1)); + + if (_scene->_priorSceneId != -2) + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 6, 1, 0, 0); + + _globals._sequenceIndexes[13] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[13], false, 6, 1, 120, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _scene->_sequences.addTimer(30, 62); + + _carLocations[0] = 501; + _carLocations[1] = 506; + _carLocations[2] = 511; + _carLocations[3] = 513; + _carLocations[4] = 601; + _carLocations[5] = 604; + _carLocations[6] = 607; + _carLocations[7] = 609; + _carLocations[8] = 612; + + _activeCars = false; + + for (int i = 0; i < 9; i++) { + if (_globals[kHoverCarLocation] == _carLocations[i]) { + _homeSelectedId = i; + if (_scene->_priorSceneId != -2) + _selectedId = i; + } + } + + _game._player._visible = false; + _game._player._stepEnabled = false; + _frame = -1; + _scene->loadAnimation(formAnimName('a', -1)); + _scene->_activeAnimation->setCurrentFrame(86); + + sceneEntrySound(); + _vm->_sound->command(16); +} + +void Scene505::step() { + if (_frame != _scene->_activeAnimation->getCurrentFrame()) { + _frame = _scene->_activeAnimation->getCurrentFrame(); + int resetFrame = -1; + + switch (_frame) { + case 4: + case 24: + case 33: + case 53: + case 62: + case 82: + if (_nextButtonId == 0x38A) + resetFrame = 4; + else if (_nextButtonId == 0x38B) + resetFrame = 33; + else if (_nextButtonId == 0x2DE) + resetFrame = 62; + + break; + + case 15: + case 44: + case 73: { + int this_button; + int old_select; + _vm->_sound->command(17); + old_select = _selectedId; + if (_frame == 15) { + this_button = 0x38A; + _selectedId = (_selectedId + 1) % 9; + } else if (_frame == 44) { + this_button = 0x38B; + _selectedId--; + if (_selectedId < 0) + _selectedId = 8; + } else { + this_button = 0x2DE; + if ((_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) && (_carLocations[_selectedId] == 501)) + _vm->_dialogs->show(431); + else if (_selectedId != _homeSelectedId) { + _nextButtonId = 0; + _activeCars = true; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _globals._sequenceIndexes[13] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[13], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[13], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + _vm->_sound->command(18); + } + } + + if (_nextButtonId == this_button) + _nextButtonId = 0; + + if (old_select != _selectedId) { + _scene->_sequences.remove(_globals._sequenceIndexes[11]); + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1); + if (old_select != _homeSelectedId) + _scene->_sequences.remove(_globals._sequenceIndexes[0]); + + if (_selectedId != _homeSelectedId) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1); + } + } + break; + } + + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + if (_nextButtonId == 0x38A) + resetFrame = 29 - _frame; + + break; + + case 26: + case 55: + case 84: + if (_nextButtonId != 0) + resetFrame = 3; + + break; + + case 27: + case 56: + case 85: + if (_nextButtonId != 0) + resetFrame = 2; + + break; + + case 29: + case 58: + case 87: + if (_activeCars) + _globals[kHoverCarDestination] = _carLocations[_selectedId]; + + if (_nextButtonId == 0x38A) + resetFrame = 0; + else if (_nextButtonId == 0x38B) + resetFrame = 29; + else if (_nextButtonId == 0x2DE) + resetFrame = 58; + else + resetFrame = 86; + break; + + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + if (_nextButtonId == 0x38B) + resetFrame = 87 - _frame; + + break; + + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + if (_nextButtonId == 0x2DE) + resetFrame = 145 - _frame; + + break; + + default: + break; + } + + if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(resetFrame); + _frame = resetFrame; + } + } + + switch (_game._trigger) { + case 60: { + _game._player._stepEnabled = true; + int syncIdx = _globals._sequenceIndexes[13]; + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[13], syncIdx); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[_homeSelectedId], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _globals._sequenceIndexes[11] = _scene->_sequences.startCycle(_globals._spriteIndexes[11], false, _selectedId + 1); + + if (_selectedId != _homeSelectedId) { + _globals._sequenceIndexes[0] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[0 + _selectedId], false, 24, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[0], 1); + } + break; + } + + case 61: + _globals._sequenceIndexes[10] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[10], false, 8, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 8); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[10], _globals._sequenceIndexes[9]); + break; + + case 62: + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 63: + _globals[kHoverCarDestination] = _carLocations[_selectedId]; + _scene->_nextSceneId = 504; + break; + + default: + break; + } +} + +void Scene505::actions() { + if (_action.isAction(VERB_PRESS)) + _nextButtonId = _action._activeAction._objectNameId; + else if (_action.isAction(VERB_RETURN_TO, NOUN_INSIDE_OF_CAR)) + _scene->_nextSceneId = 504; + else if (_action.isAction(VERB_LOOK, NOUN_VIEW_SCREEN)) + _vm->_dialogs->show(50510); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _vm->_dialogs->show(50511); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene506::Scene506(MADSEngine *vm) : Scene5xx(vm), _doorPos(0, 0) { + _heroFacing = FACING_DUMMY; + + _doorDepth = -1; + _doorSpriteIdx = -1; + _doorSequenceIdx = -1; + _doorWord = -1; + + _labDoorFl = false; + _firstDoorFl = false; + _actionFl = false; +} + +void Scene506::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_doorPos.x); + s.syncAsSint16LE(_doorPos.y); + + s.syncAsByte(_heroFacing); + + s.syncAsSint16LE(_doorDepth); + s.syncAsSint16LE(_doorSpriteIdx); + s.syncAsSint16LE(_doorSequenceIdx); + s.syncAsSint16LE(_doorWord); + + s.syncAsByte(_labDoorFl); + s.syncAsByte(_firstDoorFl); + s.syncAsByte(_actionFl); +} + +void Scene506::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALK_INTO); + _scene->addActiveVocab(NOUN_SOFTWARE_STORE); + _scene->addActiveVocab(NOUN_LABORATORY); +} + +void Scene506::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('q', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('q', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_3"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_LABORATORY, VERB_WALK_INTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(65, 125), FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + idx = _scene->_dynamicHotspots.add(NOUN_SOFTWARE_STORE, VERB_WALK_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + hotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(112, 102), FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _firstDoorFl = true; + _actionFl = false; + + if (_scene->_priorSceneId == 508) { + _game._player._playerPos = Common::Point(16, 111); + _game._player._facing = FACING_SOUTHEAST; + _scene->_sequences.addTimer(15, 80); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId == 507) { + _game._player._playerPos = Common::Point(80, 102); + _game._player._facing = FACING_SOUTHEAST; + _scene->_sequences.addTimer(60, 80); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(138, 116); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + sceneEntrySound(); +} + +void Scene506::step() { + if (_game._trigger >= 80) { + if (_firstDoorFl) { + _heroFacing = FACING_SOUTHEAST; + if (_scene->_priorSceneId == 507) { + _doorPos = Common::Point(112, 102); + _doorWord = 0x336; + } else { + _doorPos = Common::Point(65, 125); + _doorWord = 0x37D; + } + } + handleDoorSequences(); + } + + if (_game._trigger >= 70) { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } +} + +void Scene506::handleDoorSequences() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + + if (_firstDoorFl) { + if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE) || ((_scene->_priorSceneId == 507) && !_actionFl)) { + _doorDepth = 13; + _doorSpriteIdx = _globals._spriteIndexes[2]; + _doorSequenceIdx = _globals._sequenceIndexes[2]; + _labDoorFl = false; + } else { + _doorDepth = 10; + _doorSpriteIdx = _globals._spriteIndexes[1]; + _doorSequenceIdx = _globals._sequenceIndexes[1]; + _labDoorFl = true; + } + _firstDoorFl = false; + } + + switch (_game._trigger) { + case 0: + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_doorSequenceIdx); + _doorSequenceIdx = _scene->_sequences.addSpriteCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _scene->changeVariant(1); + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + + case 81: + _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, -2); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _game._player._walkAnywhere = true; + _game._player.walk(_doorPos, _heroFacing); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _scene->_sequences.remove(_doorSequenceIdx); + _doorSequenceIdx = _scene->_sequences.startReverseCycle(_doorSpriteIdx, false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + if (_actionFl) + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 84); + else + _scene->_sequences.addSubEntry(_doorSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 83); + + break; + + case 83: { + _doorSequenceIdx = _scene->_sequences.startCycle(_doorSpriteIdx, false, 1); + int idx = _scene->_dynamicHotspots.add(_doorWord, VERB_WALK_INTO, _doorSequenceIdx, Common::Rect(0, 0, 0, 0)); + int hotspotId = _scene->_dynamicHotspots.setPosition(idx, _doorPos, FACING_NORTHWEST); + _scene->_dynamicHotspots.setCursor(hotspotId, CURSOR_GO_LEFT); + _scene->_sequences.setDepth(_doorSequenceIdx, _doorDepth); + _firstDoorFl = true; + if (_labDoorFl) { + _globals._spriteIndexes[1] = _doorSpriteIdx; + _globals._sequenceIndexes[1] = _doorSequenceIdx; + } else { + _globals._spriteIndexes[2] = _doorSpriteIdx; + _globals._sequenceIndexes[2] = _doorSequenceIdx; + } + _game._player._stepEnabled = true; + + } + break; + + case 84: + _actionFl = false; + _game._player._stepEnabled = true; + if (_labDoorFl) + _scene->_nextSceneId = 508; + else + _scene->_nextSceneId = 507; + + break; + + default: + break; + } +} + +void Scene506::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_LABORATORY)) { + if (_firstDoorFl) { + _heroFacing = FACING_NORTHWEST; + _doorPos = Common::Point(16, 111); + } + _actionFl = true; + handleDoorSequences(); + } else if (_action.isAction(VERB_WALK_INTO, NOUN_SOFTWARE_STORE)) { + if (_firstDoorFl) { + _heroFacing = FACING_NORTHWEST; + _doorPos = Common::Point(80, 102); + } + _actionFl = true; + handleDoorSequences(); + } else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(50618); + else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT)) + _vm->_dialogs->show(50610); + else if (_action.isAction(VERB_LOOK, NOUN_MOTEL)) + _vm->_dialogs->show(50611); + else if (_action.isAction(VERB_LOOK, NOUN_CYCLE_SHOP)) + _vm->_dialogs->show(50612); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_BIKE)) + _vm->_dialogs->show(50613); + else if (_action.isAction(VERB_TAKE, NOUN_AIR_BIKE)) + _vm->_dialogs->show(50614); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE)) + _vm->_dialogs->show(50615); + else if (_action.isAction(VERB_LOOK, NOUN_LABORATORY)) + _vm->_dialogs->show(50616); + else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(50617); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_STORE_SIGN)) + _vm->_dialogs->show(50619); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(50620); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(50621); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene507::Scene507(MADSEngine *vm) : Scene5xx(vm) { + _penlightHotspotId = -1; +} + +void Scene507::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_penlightHotspotId); +} + +void Scene507::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PENLIGHT); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene507::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_3"); + + if ((_game._difficulty != DIFFICULTY_EASY) && (_game._objects[OBJ_PENLIGHT]._roomNumber == _scene->_currentSceneId)) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _penlightHotspotId = _scene->_dynamicHotspots.add(NOUN_PENLIGHT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_penlightHotspotId, Common::Point(233, 152), FACING_SOUTHEAST); + } + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(121, 147); + _game._player._facing = FACING_NORTH; + } + + sceneEntrySound(); +} +void Scene507::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE)) + _scene->_nextSceneId = 506; + else if (_action.isAction(VERB_TAKE, NOUN_PENLIGHT)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_PENLIGHT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_penlightHotspotId); + _vm->_sound->command(27); + _game._objects.addToInventory(OBJ_PENLIGHT); + _vm->_dialogs->showItem(OBJ_PENLIGHT, 50730); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(50722); + else if (_action.isAction(VERB_LOOK, NOUN_SWIRLING_LIGHT)) + _vm->_dialogs->show(50710); + else if (_action.isAction(VERB_TAKE, NOUN_SWIRLING_LIGHT)) + _vm->_dialogs->show(50711); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_SOFTWARE)) + _vm->_dialogs->show(50712); + else if (_action.isAction(VERB_TAKE, NOUN_OLD_SOFTWARE)) + _vm->_dialogs->show(50713); + else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISEMENT)) + _vm->_dialogs->show(50714); + else if (_action.isAction(VERB_LOOK, NOUN_ADVERTISING_POSTER)) + _vm->_dialogs->show(50715); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) { + if (_scene->_customDest.x < 100) + _vm->_dialogs->show(50726); + else + _vm->_dialogs->show(50716); + } else if (_action.isAction(VERB_LOOK, NOUN_HOTTEST_SOFTWARE)) + _vm->_dialogs->show(50717); + else if (_action.isAction(VERB_LOOK, NOUN_SOFTWARE_SHELF)) + _vm->_dialogs->show(50718); + else if (_action.isAction(VERB_LOOK, NOUN_SENSOR)) + _vm->_dialogs->show(50719); + else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER)) + _vm->_dialogs->show(50720); + else if (_action.isAction(VERB_LOOK, NOUN_PAD_OF_PAPER)) + _vm->_dialogs->show(50721); + else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER)) + _vm->_dialogs->show(50723); + else if (_action.isAction(VERB_LOOK, NOUN_BARGAIN_VAT)) + _vm->_dialogs->show(50724); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(50725); + else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) { + if (_game._objects.isInRoom(OBJ_PENLIGHT)) + _vm->_dialogs->show(50728); + else + _vm->_dialogs->show(50727); + } else if (_action.isAction(VERB_LOOK, NOUN_PENLIGHT) && !_game._objects.isInInventory(OBJ_PENLIGHT)) { + if (_game._objects.isInRoom(OBJ_PENLIGHT)) + _vm->_dialogs->show(50729); + } else if (_action.isAction(VERB_LOOK, NOUN_EMERGENCY_LIGHT)) + _vm->_dialogs->show(50731); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene508::Scene508(MADSEngine *vm) : Scene5xx(vm) { + _chosenObject = -1; +} + +void Scene508::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_chosenObject); +} + +void Scene508::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SPINACH_PATCH_DOLL); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene508::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('m', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 2)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('t', 0)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('l', 3)); + + if (!_game._visitedScenes._sceneRevisited) { + _globals[kLaserOn] = false; + _chosenObject = 0; + } + + if (!_globals[kLaserOn]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _scene->_hotspots.activate(NOUN_HOLE, false); + _scene->_hotspots.activate(NOUN_LASER_BEAM, false); + } else { + _scene->changeVariant(1); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_hotspots.activate(NOUN_HOLE, true); + _scene->_hotspots.activate(NOUN_LASER_BEAM, true); + } + _vm->_sound->command(21); + } + _vm->_sound->command(20); + + if (_scene->_priorSceneId == 515) { + _game._player._playerPos = Common::Point(57, 116); + _game._player._facing = FACING_NORTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(289, 139); + _game._player._facing = FACING_WEST; + } + + sceneEntrySound(); + _game.loadQuoteSet(0x273, 0); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_COMPACT_CASE); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + } +} + +void Scene508::preActions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _game._player._walkOffScreenSceneId = 506; +} + +void Scene508::handlePedestral() { + if (!_globals[kLaserOn]) + _vm->_dialogs->show(50835); + + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50836); + + if (_globals[kLaserOn] && !_globals[kLaserHoleIsThere]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[6]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + if (_chosenObject == 2) + _game._objects.removeFromInventory(OBJ_COMPACT_CASE, 1); + else + _game._objects.removeFromInventory(OBJ_REARVIEW_MIRROR, 1); + + _globals._sequenceIndexes[7] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[7], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[7], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_hotspots.activate(NOUN_HOLE, true); + _scene->_hotspots.activate(NOUN_LASER_BEAM, true); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[6]); + _game._player._visible = true; + _scene->_sequences.addTimer(120, 4); + break; + + case 4: + _vm->_dialogs->show(50834); + _globals[kLaserHoleIsThere] = true; + _scene->_nextSceneId = 515; + break; + + default: + break; + } + } +} + +void Scene508::actions() { + if (_action.isAction(VERB_PULL, NOUN_LEVER)) { + if (!_globals[kLaserOn]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 2, 120, _game.getQuote(0x273)); + break; + + case 2: + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 10, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], -1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _vm->_sound->command(19); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 15, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[1]); + _game._player._visible = true; + _scene->_sequences.addTimer(15, 5); + break; + + case 4: + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 15, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 6, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 6); + break; + + case 5: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _scene->loadAnimation(formAnimName('B', 1), 6); + break; + + case 6: { + _vm->_sound->command(22); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 11); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(57, 116), FACING_NORTHEAST); + _scene->_kernelMessages.reset(); + _scene->changeVariant(1); + _scene->_sequences.addTimer(30, 7); + } + break; + + case 7: + _globals[kLaserOn] = true; + _vm->_dialogs->show(50833); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else { + _vm->_dialogs->show(50837); + } + } else if (_action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) { + _chosenObject = 1; + handlePedestral(); + } else if (_action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_PEDESTAL) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM)) { + _chosenObject = 2; + handlePedestral(); + } else if (_action._lookFlag) + _vm->_dialogs->show(50822); + else if (_action.isAction(VERB_LOOK, NOUN_TARGET_AREA)) + _vm->_dialogs->show(50810); + else if (_action.isAction(VERB_LOOK, NOUN_SPINACH_PATCH_DOLL)) + _vm->_dialogs->show(50811); + else if (_action.isAction(VERB_TAKE, NOUN_SPINACH_PATCH_DOLL)) + _vm->_dialogs->show(50812); + else if (_action.isAction(VERB_LOOK, NOUN_SAND_BAGS)) + _vm->_dialogs->show(50816); + else if (_action.isAction(VERB_TAKE, NOUN_SAND_BAGS)) + _vm->_dialogs->show(50817); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_STATION)) + _vm->_dialogs->show(50818); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50820); + else + _vm->_dialogs->show(50819); + } else if (_action.isAction(VERB_LOOK, NOUN_LASER_CANNON)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50822); + else + _vm->_dialogs->show(50821); + } else if (_action.isAction(VERB_TAKE, NOUN_LASER_CANNON)) + _vm->_dialogs->show(50823); + else if (_action.isAction(VERB_LOOK, NOUN_LEVER)) { + if (_globals[kLaserOn]) + _vm->_dialogs->show(50825); + else + _vm->_dialogs->show(50824); + } else if (_action.isAction(VERB_PUSH, NOUN_LEVER)) + _vm->_dialogs->show(50826); + else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50828); + else + _vm->_dialogs->show(50827); + } else if (_action.isAction(VERB_TAKE, NOUN_LASER_BEAM)) + _vm->_dialogs->show(50829); + else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50831); + else + _vm->_dialogs->show(50830); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(50832); + else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) { + if (!_globals[kLaserOn]) + _vm->_dialogs->show(50813); + else if (!_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(50814); + else + _vm->_dialogs->show(50815); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene511::Scene511(MADSEngine *vm) : Scene5xx(vm) { + _handingLine = false; + _lineMoving = false; + + _lineAnimationMode = -1; + _lineFrame = -1; + _lineAnimationPosition = -1; +} + +void Scene511::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsByte(_handingLine); + s.syncAsByte(_lineMoving); + + s.syncAsSint16LE(_lineAnimationMode); + s.syncAsSint16LE(_lineFrame); + s.syncAsSint16LE(_lineAnimationPosition); +} + +void Scene511::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_BOAT); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene511::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_6"); + + if (_scene->_priorSceneId != -2) + _handingLine = false; + + if (_globals[kBoatRaised]) { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_hotspots.activate(NOUN_BOAT, false); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(75, 124), FACING_NORTH); + _scene->_hotspots.activate(NOUN_ROPE, false); + } else { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 2)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 3)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1)); + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 1, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 5); + + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6],5); + + _scene->_hotspots.activate(NOUN_ROPE, true); + _scene->_hotspots.activate(NOUN_BOAT, true); + _scene->changeVariant(1); + } + + int frame = 0; + if (_globals[kLineStatus] == 2) + frame = -1; + else if (_globals[kLineStatus] == 3) + frame = -2; + + if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('b', 4)); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, frame); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 3); + if (_globals[kBoatRaised]) + _scene->changeVariant(2); + } + + _lineFrame = -1; + _lineMoving = false; + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if (_scene->_priorSceneId == 512) { + _game._player._playerPos = Common::Point(60, 112); + _game._player._facing = FACING_SOUTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(55, 152); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + } else if (_handingLine) { + _game._player._visible = false; + _lineAnimationMode = 1; + _lineAnimationPosition = 1; + _scene->loadAnimation(formAnimName('R', -1)); + _lineFrame = 2; + } + sceneEntrySound(); +} + +void Scene511::step() { + if ((_lineAnimationMode == 1) && _scene->_activeAnimation) { + if (_lineFrame != _scene->_activeAnimation->getCurrentFrame()) { + _lineFrame = _scene->_activeAnimation->getCurrentFrame(); + int resetFrame = -1; + + if ((_lineAnimationPosition == 2) && (_lineFrame == 14)) + _lineMoving = false; + + if (_lineAnimationPosition == 1) { + if (_lineFrame == 3) { + _lineMoving = false; + resetFrame = 2; + } + + if (_handingLine) + resetFrame = 2; + } + + if ((resetFrame >= 0) && (resetFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(resetFrame); + _lineFrame = resetFrame; + } + } + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene511::preActions() { + if (!_handingLine) + return; + + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if ((!_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) && _game._player._needToWalk) { + if (_game._trigger == 0) { + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->freeAnimation (); + _lineAnimationMode = 2; + _scene->loadAnimation(formAnimName('R',2), 1); + } else if (_game._trigger == 1) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _game._objects.setRoom(OBJ_FISHING_LINE, 1); + _handingLine = false; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + } + } +} + +void Scene511::actions() { + if (_action.isAction(VERB_WALK_INTO, NOUN_RESTAURANT)) + _scene->_nextSceneId = 512; + else if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) { + if (!_globals[kBoatRaised]) { + if (_globals[kLineStatus] == 2) { + if (_globals[kLineStatus] != 3) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _lineAnimationMode = 1; + _lineAnimationPosition = 1; + _lineMoving = true; + _scene->loadAnimation(formAnimName('R', -1)); + _scene->_sequences.addTimer(1, 1); + } else if (_game._trigger == 1) { + if (_lineMoving) { + _scene->_sequences.addTimer(1, 1); + } else { + _game._objects.addToInventory(OBJ_FISHING_LINE); + _lineMoving = true; + _handingLine = true; + _game._player._stepEnabled = true; + } + } + } else + _vm->_dialogs->show(51129); + } else + return; + } else { + _vm->_dialogs->show(51130); + } + } else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_BOAT) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_BOAT)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51131); + else if (_globals[kLineStatus] == 1) + _vm->_dialogs->show(51130); + else if (!_globals[kBoatRaised] && _handingLine) { + if (_globals[kLineStatus] != 3) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _lineMoving = true; + _lineAnimationPosition = 2; + _scene->_sequences.addTimer(1, 1); + } else if (_game._trigger == 1) { + if (_lineMoving) + _scene->_sequences.addTimer(1, 1); + else { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(26, 153), FACING_NORTHEAST); + _game._objects.removeFromInventory(OBJ_FISHING_LINE, 1); + _handingLine = false; + _lineMoving = true; + _globals[kLineStatus] = 3; + _game._player._stepEnabled = true; + } + } + } + } + } else if (_action.isAction(VERB_LOOK, NOUN_STREET) || _action._lookFlag) { + if (_globals[kLineStatus] == 2) + _vm->_dialogs->show(51110); + else { + if (_globals[kLineStatus] == 3) + _vm->_dialogs->show(51111); + else + _vm->_dialogs->show(51112); + } + } else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(51113); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(51114); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_SIDEWALK_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_EAST)) + _vm->_dialogs->show(51115); + else if (_action.isAction(VERB_LOOK, NOUN_PLEASURE_DOME)) + _vm->_dialogs->show(51116); + else if (_action.isAction(VERB_LOOK, NOUN_TICKET_BOOTH)) + _vm->_dialogs->show(51117); + else if (_action.isAction(VERB_LOOK, NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51118); + else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_DOME_ENTRANCE) || _action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51119); + else if ( (_action.isAction(VERB_PUT) || _action.isAction(VERB_THROW)) + && (_action.isObject(NOUN_TIMEBOMB) || _action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS)) + && _action.isObject(NOUN_DOME_ENTRANCE)) + _vm->_dialogs->show(51120); + else if (_action.isAction(VERB_LOOK, NOUN_RESTAURANT)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51121); + else + _vm->_dialogs->show(51128); + } else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE)) + _vm->_dialogs->show(51122); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 2)) + _vm->_dialogs->show(51126); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_action._mainObjectSource == 4) && (_globals[kLineStatus] == 3)) + _vm->_dialogs->show(51133); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(51127); + else if (_action.isAction(VERB_LOOK, NOUN_BOAT)) + if (_globals[kBoatRaised]) + _vm->_dialogs->show(51123); + else if (_globals[kLineStatus] != 3) + _vm->_dialogs->show(51124); + else + _vm->_dialogs->show(51125); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3)) + _vm->_dialogs->show(51125); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene512::Scene512(MADSEngine *vm) : Scene5xx(vm) { + _fishingRodHotspotId = -1; + _keyHotspotId = -1; +} + +void Scene512::synchronize(Common::Serializer &s) { + Scene5xx::synchronize(s); + + s.syncAsSint16LE(_fishingRodHotspotId); + s.syncAsSint16LE(_keyHotspotId); +} + +void Scene512::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_ROD); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_PADLOCK_KEY); + _scene->addActiveVocab(NOUN_REGISTER_DRAWER); +} + +void Scene512::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 3)); + + if (_game._objects[OBJ_FISHING_ROD]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _fishingRodHotspotId = _scene->_dynamicHotspots.add(NOUN_FISHING_ROD, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_fishingRodHotspotId, Common::Point(199, 101), FACING_NORTHEAST); + } + + if (!_game._visitedScenes._sceneRevisited) + _globals[kRegisterOpen] = false; + + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + if (_game._difficulty == DIFFICULTY_EASY) { + if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 10, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 3); + _keyHotspotId = _scene->_dynamicHotspots.add(NOUN_PADLOCK_KEY, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_keyHotspotId, Common::Point(218, 152), FACING_NORTHEAST); + } + if (_globals[kRegisterOpen]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + } + } else if (_globals[kRegisterOpen]) { + if (_game._objects[OBJ_PADLOCK_KEY]._roomNumber == _scene->_currentSceneId) { + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3); + } else { + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + } + } else + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(144, 152); + _game._player._facing = FACING_NORTHEAST; + } + + sceneEntrySound(); +} + +void Scene512::actions() { + if (_action.isAction(VERB_WALK, NOUN_OUTSIDE)) + _scene->_nextSceneId = 511; + else if (_action.isAction(VERB_TAKE, NOUN_FISHING_ROD)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_FISHING_ROD)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_fishingRodHotspotId); + _game._objects.addToInventory(OBJ_FISHING_ROD); + _vm->_dialogs->showItem(OBJ_FISHING_ROD, 51217); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_OPEN, NOUN_CASH_REGISTER)) { + if (!_globals[kRegisterOpen]) { + switch (_game._trigger) { + case 0: + _vm->_dialogs->show(51236); + _game._player._stepEnabled = false; + _game._player._facing = FACING_NORTH; + _scene->_sequences.addTimer(15, 1); + break; + + case 1: + _game._player._visible = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[8], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[8], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[8]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[8]); + _game._player._visible = true; + _scene->_sequences.addTimer(30, 3); + break; + + case 3: + _game._player._facing = FACING_NORTHEAST; + if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || (_game._difficulty == DIFFICULTY_EASY)) { + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + } else { + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 5); + } + _vm->_sound->command(23); + break; + + case 4: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addTimer(60, 6); + break; + + case 5: + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 14, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, true); + _scene->_sequences.addTimer(60, 6); + break; + + case 6: + _globals[kRegisterOpen] = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else + _vm->_dialogs->show(51239); + } else if (_action.isAction(VERB_CLOSE, NOUN_CASH_REGISTER) && _globals[kRegisterOpen]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + if (!_game._objects.isInRoom(OBJ_PADLOCK_KEY) || _game._difficulty == DIFFICULTY_EASY) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: + _globals[kRegisterOpen] = false; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_PADLOCK_KEY)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_PADLOCK_KEY)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + + int endVal; + if (_game._player._playerPos == Common::Point(218, 152)) + endVal = 3; + else + endVal = 2; + + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, endVal); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, endVal, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + if (_game._player._playerPos == Common::Point(218, 152)) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_dynamicHotspots.remove(_keyHotspotId); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 3); + _scene->_hotspots.activate(NOUN_PADLOCK_KEY, false); + } + _vm->_sound->command(9); + _game._objects.addToInventory(OBJ_PADLOCK_KEY); + _vm->_dialogs->showItem(OBJ_PADLOCK_KEY, 51226); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(51225); + else if (_action.isAction(VERB_LOOK, NOUN_PADLOCK_KEY) && _game._objects.isInRoom(OBJ_PADLOCK_KEY)) + _vm->_dialogs->show(51215); + else if (_action.isAction(VERB_LOOK, NOUN_FISHING_ROD) && (_scene->_activeAnimation->getCurrentFrame() == 4)) + _vm->_dialogs->show(51216); + else if (_action.isAction(VERB_LOOK, NOUN_SHIPS_WHEEL)) + _vm->_dialogs->show(51218); + else if (_action.isAction(VERB_TAKE, NOUN_SHIPS_WHEEL)) + _vm->_dialogs->show(51219); + else if (_action.isAction(VERB_LOOK, NOUN_PORTHOLE) || _action.isAction(VERB_PEER_THROUGH, NOUN_PORTHOLE)) + _vm->_dialogs->show(51220); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(51221); + else if (_action.isAction(VERB_LOOK, NOUN_STARFISH)) + _vm->_dialogs->show(51222); + else if (_action.isAction(VERB_TAKE, NOUN_STARFISH)) + _vm->_dialogs->show(51223); + else if (_action.isAction(VERB_LOOK, NOUN_OUTSIDE)) + _vm->_dialogs->show(51224); + else if (_action.isAction(VERB_LOOK, NOUN_POSTER)) + _vm->_dialogs->show(51227); + else if (_action.isAction(VERB_TAKE, NOUN_POSTER)) + _vm->_dialogs->show(51228); + else if (_action.isAction(VERB_LOOK, NOUN_TROPHY)) { + if (_game._visitedScenes.exists(604)) + _vm->_dialogs->show(51229); + else + _vm->_dialogs->show(51230); + } if (_action.isAction(VERB_LOOK, NOUN_CHAIR)) + _vm->_dialogs->show(51231); + else if (_action.isAction(VERB_LOOK, NOUN_ROPE)) + _vm->_dialogs->show(51232); + else if (_action.isAction(VERB_TAKE, NOUN_ROPE)) + _vm->_dialogs->show(51233); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(51234); + else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) + _vm->_dialogs->show(51235); + else if (_action.isAction(VERB_LOOK, NOUN_ICE_CHESTS)) + _vm->_dialogs->show(51237); + else if (_action.isAction(VERB_OPEN, NOUN_ICE_CHESTS)) + _vm->_dialogs->show(51238); + else if (_action.isAction(VERB_LOOK, NOUN_CASH_REGISTER)) { + if (!_globals[kRegisterOpen]) + _vm->_dialogs->show(51212); + else if (_game._objects.isInRoom(OBJ_PADLOCK_KEY)) + _vm->_dialogs->show(51214); + else + _vm->_dialogs->show(51213); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene513::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_ELEVATOR_DOOR); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene513::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRC_9"); + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + + if ((_scene->_priorSceneId == 751) || (_scene->_priorSceneId == 701)) { + _game._player._playerPos = Common::Point(296, 147); + _game._player._facing = FACING_WEST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(15, 80); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(63, 149); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_SECURITY_CARD); + + _game.loadQuoteSet(0x278, 0); +} + +void Scene513::step() { + switch (_game._trigger) { + case 80: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(24); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _game._player.walk(Common::Point(265, 152), FACING_WEST); + _scene->_sequences.addTimer(120, 82); + break; + + case 82: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + break; + + case 83: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene513::actions() { + if (_action.isAction(VERB_GET_INTO, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_ID_CARD, NOUN_CARD_SLOT) || _action.isAction(VERB_PUT, NOUN_FAKE_ID, NOUN_CARD_SLOT)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(24); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x278)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 2: + _game._player.walk(Common::Point(296, 147), FACING_WEST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _vm->_sound->command(25); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _game._player._stepEnabled = true; + if (_globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + + break; + + default: + break; + } + } else if ((_action._lookFlag) || _action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(51318); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR)) + _vm->_dialogs->show(51310); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_DOOR)) + _vm->_dialogs->show(51311); + else if (_action.isAction(VERB_LOOK, NOUN_CARD_SLOT)) + _vm->_dialogs->show(51312); + else if (_action.isAction(VERB_LOOK, NOUN_HANDICAP_SIGN)) + _vm->_dialogs->show(51313); + else if (_action.isAction(VERB_LOOK, NOUN_BIKE_RACK)) + _vm->_dialogs->show(51314); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(51315); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(51316); + else if (_action.isAction(VERB_LOOK, NOUN_STREET_TO_WEST) || _action.isAction(VERB_WALK_DOWN, NOUN_STREET_TO_WEST)) + _vm->_dialogs->show(51317); + else if (_action.isAction(VERB_OPEN, NOUN_ELEVATOR_DOOR) || _action.isAction(VERB_OPEN, NOUN_ELEVATOR)) + _vm->_dialogs->show(51319); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(51321); + else if (_action.isAction(VERB_LOOK, NOUN_BRICK_WALL)) + _vm->_dialogs->show(51322); + else if (_action.isAction(VERB_PUT, NOUN_SECURITY_CARD, NOUN_CARD_SLOT)) + _vm->_dialogs->show(51320); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene515::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene515::enter() { + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(30, 70); + + sceneEntrySound(); +} + +void Scene515::step() { + if (_game._trigger == 70) + _scene->loadAnimation(formAnimName('A', -1), 71); + else if (_game._trigger == 71) + _scene->_nextSceneId = 508; +} + +/*------------------------------------------------------------------------*/ + +void Scene551::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene551::enter() { + if (_globals[kSexOfRex] == REX_MALE) + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + else + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + + if (_scene->_priorSceneId == 501) + _game._player._playerPos = Common::Point(18, 130); + else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(124, 119); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + char sepChar; + if (_globals[kSexOfRex] == REX_MALE) + sepChar = 'e'; + else + sepChar = 'u'; + + int suffixNum; + int trigger; + + switch (_globals[kTeleporterCommand]) { + case 1: + suffixNum = 3; + trigger = 75; + _globals[kTeleporterUnderstood] = true; + break; + + case 2: + suffixNum = 1; + trigger = 80; + break; + + case 4: + suffixNum = 2; + trigger = 90; + break; + + default: + trigger = 0; + suffixNum = 0; + } + + _globals[kTeleporterCommand] = 0; + + if (suffixNum > 0) + _scene->loadAnimation(formAnimName(sepChar, suffixNum), trigger); + else { + _game._player._visible = true; + _game._player._stepEnabled = true; + } + } + + sceneEntrySound(); +} + +void Scene551::step() { + switch (_game._trigger) { + case 75: + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + break; + + case 80: + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + break; + + case 90: + if (_globals[kSexOfRex] == REX_MALE) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + } else { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + } + _vm->_sound->command(28); + _scene->_sequences.addTimer(60, 91); + break; + + case 91: + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } +} + +void Scene551::preActions() { + if (_action.isAction(VERB_WALK_DOWN) && (_action.isObject(NOUN_STREET_TO_WEST) || _action.isObject(NOUN_SIDEWALK_TO_WEST))) + _game._player._walkOffScreenSceneId = 501; +} + +void Scene551::actions() { + if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) + _scene->_nextSceneId = 502; + else if ((_action._lookFlag)) + _vm->_dialogs->show(55117); + else if (_action.isAction(VERB_LOOK, NOUN_SKELETON)) + _vm->_dialogs->show(55110); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR_SHAFT)) + _vm->_dialogs->show(55111); + else if (_action.isAction(VERB_WALKTO, NOUN_ELEVATOR_SHAFT)) + _vm->_dialogs->show(55112); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(55113); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(55114); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(55115); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK_TO_WEST)) { + if (_game._visitedScenes.exists(505)) + _vm->_dialogs->show(55116); + else + _vm->_dialogs->show(55115); + } else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(55118); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT_OVERHEAD)) + _vm->_dialogs->show(55119); + else if (_action.isAction(VERB_LOOK, NOUN_RAILING)) + _vm->_dialogs->show(55120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes5.h b/engines/mads/nebular/nebular_scenes5.h new file mode 100644 index 0000000000..2face26508 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes5.h @@ -0,0 +1,254 @@ +/* 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 MADS_NEBULAR_SCENES5_H +#define MADS_NEBULAR_SCENES5_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene5xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene5xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene501 : public Scene5xx{ +private: + int _mainSequenceId; + int _mainSpriteId; + int _doorHotspotid; + bool _rexPunched; + + void handleSlotActions(); + +public: + Scene501(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene502 : public SceneTeleporter { +public: + Scene502(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene503 : public Scene5xx{ +private: + int _detonatorHotspotId; + +public: + Scene503(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene504 : public Scene5xx{ +private: + int _carAnimationMode; + int _carFrame; + +public: + Scene504(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene505 : public Scene5xx{ +private: + int _frame; + int _nextButtonId; + int _homeSelectedId; + int _selectedId; + int _activeCars; + + int _carLocations[9]; + +public: + Scene505(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene506 : public Scene5xx{ +private: + Common::Point _doorPos; + Facing _heroFacing; + + int _doorDepth; + int _doorSpriteIdx; + int _doorSequenceIdx; + int _doorWord; + + bool _labDoorFl; + bool _firstDoorFl; + bool _actionFl; + + void handleDoorSequences(); + +public: + Scene506(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene507 : public Scene5xx{ +private: + int _penlightHotspotId; + +public: + Scene507(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene508 : public Scene5xx{ +private: + int _chosenObject; + + void handlePedestral(); + +public: + Scene508(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene511 : public Scene5xx{ +private: + bool _handingLine; + bool _lineMoving; + + int _lineAnimationMode; + int _lineFrame; + int _lineAnimationPosition; + +public: + Scene511(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene512 : public Scene5xx{ +private: + int _fishingRodHotspotId; + int _keyHotspotId; + +public: + Scene512(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene513 : public Scene5xx{ +public: + Scene513(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene515 : public Scene5xx{ +public: + Scene515(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +class Scene551 : public Scene5xx{ +public: + Scene551(MADSEngine *vm) : Scene5xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES5_H */ diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp new file mode 100644 index 0000000000..eb85fa86e1 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -0,0 +1,4743 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes6.h" + +namespace MADS { + +namespace Nebular { + +void Scene6xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene6xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 605) || (_scene->_nextSceneId == 620)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _game._player._scalingVelocity = true; + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene6xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 601: + case 602: + case 603: + case 604: + case 605: + case 607: + case 608: + case 609: + case 610: + case 612: + case 620: + _vm->_sound->command(29); + break; + case 611: + _vm->_sound->command(24); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene601::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_LASER_BEAM); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene601::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_4"); + + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + } + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + + if (_scene->_priorSceneId == 504) { + _game._player._playerPos = Common::Point(73, 148); + _game._player._facing = FACING_WEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->loadAnimation(formAnimName('R', 1), 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(229, 129); + _game._player._facing = FACING_SOUTHWEST; + } + + sceneEntrySound(); +} + +void Scene601::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene601::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_ENTRANCE)) + _scene->_nextSceneId = 602; + else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) { + if (!_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(60110); + else + _vm->_dialogs->show(60111); + } else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60112); + else if (_action.isAction(VERB_LOOK, NOUN_PAPERS)) + _vm->_dialogs->show(60113); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(60114); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60115); + else if (_action.isAction(VERB_LOOK, NOUN_BALCONY)) + _vm->_dialogs->show(60116); + else if (_action.isAction(VERB_LOOK, NOUN_ENTRANCE)) + _vm->_dialogs->show(60117); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60118); + else if (_action.isAction(VERB_LOOK, NOUN_CITY)) + _vm->_dialogs->show(60119); + else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN)) + _vm->_dialogs->show(60120); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene602::Scene602(MADSEngine *vm) : Scene6xx(vm) { + _lastSpriteIdx = -1; + _lastSequenceIdx = -1; + _cycleIndex = -1; + _safeMode = -1; +} + +void Scene602::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_lastSpriteIdx); + s.syncAsSint16LE(_lastSequenceIdx); + s.syncAsSint16LE(_cycleIndex); + s.syncAsSint16LE(_safeMode); +} + +void Scene602::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_SAFE); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene602::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('h', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('l', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kSafeStatus] = 0; + + if (_globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 9); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST); + _scene->changeVariant(1); + } else + _scene->_hotspots.activate(NOUN_HOLE, false); + + if (_globals[kSafeStatus] == 0) { + _lastSpriteIdx = _globals._spriteIndexes[2]; + _cycleIndex = -1; + } else if (_globals[kSafeStatus] == 1) { + _lastSpriteIdx = _globals._spriteIndexes[2]; + _cycleIndex = -2; + } else if (_globals[kSafeStatus] == 3) { + _lastSpriteIdx = _globals._spriteIndexes[3]; + _cycleIndex = -2; + } else { + _lastSpriteIdx = _globals._spriteIndexes[3]; + _cycleIndex = -1; + } + + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + + if (_game._objects.isInRoom(OBJ_DOOR_KEY)) { + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('k', -1)); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 15); + if (_globals[kSafeStatus] == 0 || _globals[kSafeStatus] == 2) + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + } else + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + + if (_scene->_priorSceneId == 603) { + _game._player._playerPos = Common::Point(228, 126); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(50, 127); + _game._player._facing = FACING_EAST; + } + + sceneEntrySound(); + _game.loadQuoteSet(0x2F1, 0x2F2, 0x2F3, 0); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_NOTE); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + _game._objects.addToInventory(OBJ_COMPACT_CASE); + } +} + +void Scene602::handleSafeActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + if (_safeMode == 1 || _safeMode == 3) { + if (_globals[kSafeStatus] == 0 && _safeMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F1)); + _scene->_sequences.addTimer(120, 4); + } else { + _scene->_sequences.remove(_lastSequenceIdx); + if (_safeMode == 3) + _lastSpriteIdx = _globals._spriteIndexes[2]; + else + _lastSpriteIdx = _globals._spriteIndexes[3]; + + _lastSequenceIdx = _scene->_sequences.addSpriteCycle(_lastSpriteIdx, false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId) + _scene->_hotspots.activate(NOUN_DOOR_KEY, true); + + _scene->_sequences.addSubEntry(_lastSequenceIdx, + SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + } else { + _scene->_sequences.remove(_lastSequenceIdx); + if (_globals[kSafeStatus] == 1) + _lastSpriteIdx = _globals._spriteIndexes[2]; + else + _lastSpriteIdx = _globals._spriteIndexes[3]; + + _lastSequenceIdx = _scene->_sequences.startReverseCycle(_lastSpriteIdx, false, 12, 1, 0, 0); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + if (_game._objects[OBJ_DOOR_KEY]._roomNumber == _scene->_currentSceneId) + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + + _scene->_sequences.addSubEntry(_lastSequenceIdx, SEQUENCE_TRIGGER_EXPIRE, 0, 2); + } + break; + + case 2: { + int synxIdx = _lastSequenceIdx; + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, _cycleIndex); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + _scene->_sequences.updateTimeout(_lastSequenceIdx, synxIdx); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + if (_safeMode == 3) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F3)); + _scene->_sequences.addTimer(120, 4); + } else + _scene->_sequences.addTimer(60, 4); + break; + } + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + break; + + case 4: + if (_safeMode == 1) { + if (_globals[kSafeStatus] == 2) + _globals[kSafeStatus] = 3; + } else if (_safeMode == 2) { + if (_globals[kSafeStatus] == 3) + _globals[kSafeStatus] = 2; + else + _globals[kSafeStatus] = 0; + } else + _globals[kSafeStatus] = 1; + + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene602::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_HALLWAY)) + _scene->_nextSceneId = 601; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 603; + else if (_action.isAction(VERB_OPEN, NOUN_SAFE) && ((_globals[kSafeStatus] == 0) || (_globals[kSafeStatus] == 2))) { + _safeMode = 1; + _cycleIndex = -2; + handleSafeActions(); + } else if (_action.isAction(VERB_CLOSE, NOUN_SAFE) && ((_globals[kSafeStatus] == 1) || (_globals[kSafeStatus] == 3))) { + _safeMode = 2; + _cycleIndex = -1; + handleSafeActions(); + } else if (_action.isAction(VERB_UNLOCK, NOUN_COMBINATION, NOUN_SAFE)) { + if ((_globals[kSafeStatus] == 0) && (_game._difficulty != DIFFICULTY_HARD)) { + _safeMode = 3; + _cycleIndex = -2; + handleSafeActions(); + } + } else if ((_action.isAction(VERB_PUT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM) || _action.isAction(VERB_PUT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) + || _action.isAction(VERB_REFLECT, NOUN_COMPACT_CASE, NOUN_LASER_BEAM) || _action.isAction(VERB_REFLECT, NOUN_REARVIEW_MIRROR, NOUN_LASER_BEAM)) && (_globals[kSafeStatus] == 0)) { + switch (_game._trigger) { + case 0: + _vm->_dialogs->show(60230); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_lastSequenceIdx); + _scene->loadAnimation(formAnimName('L', 1), 1); + break; + + case 1: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _lastSpriteIdx = _globals._spriteIndexes[3]; + _lastSequenceIdx = _scene->_sequences.startCycle(_lastSpriteIdx, false, -1); + _scene->_sequences.setDepth(_lastSequenceIdx, 14); + int idx = _scene->_dynamicHotspots.add(NOUN_SAFE, VERB_WALKTO, _lastSequenceIdx, Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(185, 113), FACING_NORTHWEST); + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 9); + idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(80, 134), FACING_NORTHEAST); + _scene->_sequences.addTimer(60, 2); + } + break; + + case 2: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F2)); + _globals[kSafeStatus] = 2; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_DOOR_KEY) && (_game._trigger || _game._objects.isInRoom(OBJ_DOOR_KEY))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_hotspots.activate(NOUN_DOOR_KEY, false); + _vm->_sound->command(9); + _game._objects.addToInventory(OBJ_DOOR_KEY); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_DOOR_KEY, 835); + break; + + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60210); + else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(60211); + else if (_action.isAction(VERB_LOOK, NOUN_HALLWAY)) + _vm->_dialogs->show(60212); + else if (_action.isAction(VERB_LOOK, NOUN_TABLE)) + _vm->_dialogs->show(60213); + else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_LOUNGE_CHAIR)) + _vm->_dialogs->show(60214); + else if (_action.isAction(VERB_LOOK, NOUN_NEON_LIGHTS)) + _vm->_dialogs->show(60215); + else if (_action.isAction(VERB_LOOK, NOUN_FIREPLACE)) + _vm->_dialogs->show(60216); + else if (_action.isAction(VERB_LOOK, NOUN_PICTURE)) + _vm->_dialogs->show(60217); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(60218); + else if (_action.isAction(VERB_LOOK, NOUN_MASKS)) + _vm->_dialogs->show(60219); + else if (_action.isAction(VERB_LOOK, NOUN_GLASS_BLOCK_WALL)) + _vm->_dialogs->show(60220); + else if (_action.isAction(VERB_LOOK, NOUN_DOORWAY)) + _vm->_dialogs->show(60221); + else if (_action.isAction(VERB_LOOK, NOUN_SAFE)) { + if (_globals[kSafeStatus] == 0) + _vm->_dialogs->show(60222); + else if (_globals[kSafeStatus] == 1) { + if (!_game._objects.isInRoom(OBJ_DOOR_KEY)) + _vm->_dialogs->show(60223); + else + _vm->_dialogs->show(60224); + } else if (_globals[kSafeStatus] == 2) + _vm->_dialogs->show(60234); + else if (_game._objects.isInRoom(OBJ_DOOR_KEY)) + _vm->_dialogs->show(60235); + else + _vm->_dialogs->show(60236); + } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_SAFE) || _action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_SAFE)) + _vm->_dialogs->show(60225); + else if (_action.isAction(VERB_PULL, NOUN_SAFE)) + _vm->_dialogs->show(60226); + else if (_action.isAction(VERB_PUT, NOUN_FIREPLACE) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(60227); + else if (_action.isAction(VERB_LOOK, NOUN_HOLE)) + _vm->_dialogs->show(60228); + else if (_action.isAction(VERB_LOOK, NOUN_LASER_BEAM)) + _vm->_dialogs->show(60229); + else if (_action.isAction(VERB_LOOK, NOUN_FLOWER_BOX)) + _vm->_dialogs->show(60231); + else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SAFE) || _action.isAction(VERB_THROW, NOUN_BOMBS, NOUN_SAFE)) + _vm->_dialogs->show(60232); + else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB)) + _vm->_dialogs->show(60233); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene603::Scene603(MADSEngine *vm) : Scene6xx(vm) { + _compactCaseHotspotId = -1; + _noteHotspotId = -1; +} + +void Scene603::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_compactCaseHotspotId); + s.syncAsSint16LE(_noteHotspotId); +} + +void Scene603::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_COMPACT_CASE); + _scene->addActiveVocab(NOUN_NOTE); +} + +void Scene603::enter() { + if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXMRD_3"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _compactCaseHotspotId = _scene->_dynamicHotspots.add(NOUN_COMPACT_CASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_compactCaseHotspotId, Common::Point(250, 152), FACING_SOUTHEAST); + } + + if ((_game._difficulty != DIFFICULTY_HARD) && (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId)) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 14); + _noteHotspotId = _scene->_dynamicHotspots.add(NOUN_NOTE, VERB_WALKTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_noteHotspotId, Common::Point(242, 118), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId != -2) + _game._player._playerPos = Common::Point(113, 134); + + sceneEntrySound(); +} + +void Scene603::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_LIVINGROOM)) + _scene->_nextSceneId = 602; + else if (_action.isAction(VERB_TAKE, NOUN_COMPACT_CASE)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_COMPACT_CASE)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_compactCaseHotspotId); + _game._objects.addToInventory(OBJ_COMPACT_CASE); + _vm->_dialogs->showItem(OBJ_COMPACT_CASE, 60330); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_TAKE, NOUN_NOTE)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_NOTE)) { + if (_game._trigger == 0) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addTimer(15, 1); + } else if (_game._trigger == 1) { + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _scene->_dynamicHotspots.remove(_noteHotspotId); + _game._objects.addToInventory(OBJ_NOTE); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + } + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60310); + else if (_action.isAction(VERB_LOOK, NOUN_BED)) + _vm->_dialogs->show(60311); + else if (_action.isAction(VERB_LOOK, NOUN_WIG_STAND)) + _vm->_dialogs->show(60312); + else if (_action.isAction(VERB_TAKE, NOUN_WIG_STAND)) + _vm->_dialogs->show(60313); + else if (_action.isAction(VERB_LOOK, NOUN_REVIEW)) + _vm->_dialogs->show(60314); + else if (_action.isAction(VERB_LOOK, NOUN_SOUVENIR_TICKETS)) + _vm->_dialogs->show(60315); + else if (_action.isAction(VERB_LOOK, NOUN_PHOTOGRAPH)) + _vm->_dialogs->show(60316); + else if (_action.isAction(VERB_LOOK, NOUN_LAMP)) + _vm->_dialogs->show(60317); + else if (_action.isAction(VERB_LOOK, NOUN_DIRECTORS_SLATE) || _action.isAction(VERB_LOOK, NOUN_CROP) || _action.isAction(VERB_LOOK, NOUN_MEGAPHONE)) + _vm->_dialogs->show(60318); + else if (_action.isAction(VERB_LOOK, NOUN_SNAPSHOT)) + _vm->_dialogs->show(60319); + else if (_action.isAction(VERB_TAKE, NOUN_SNAPSHOT)) + _vm->_dialogs->show(60320); + else if (_action.isAction(VERB_LOOK, NOUN_PERFUME)) + _vm->_dialogs->show(60321); + else if (_action.isAction(VERB_TAKE, NOUN_PERFUME)) + _vm->_dialogs->show(60322); + else if (_action.isAction(VERB_TAKE, NOUN_NOTE)) + _vm->_dialogs->show(60323); + else if (_action.isAction(VERB_LOOK, NOUN_NOTE)) { + if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60324); + } else if (_action.isAction(VERB_LOOK, NOUN_CORNER_TABLE)) { + if (_game._objects[OBJ_NOTE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60326); + else + _vm->_dialogs->show(60325); + } else if (_action.isAction(VERB_LOOK, NOUN_VANITY)) { + if (_game._objects[OBJ_COMPACT_CASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60327); + else + _vm->_dialogs->show(60328); + } else if (_action.isAction(VERB_LOOK, NOUN_COMPACT_CASE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(60329); + // For the next two checks, the second part of the check wasn't surrounded par parenthesis, which was obviously wrong + else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP))) + _vm->_dialogs->show(60331); + else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_BRA) || _action.isObject(NOUN_BOA) || _action.isObject(NOUN_SLIP))) + _vm->_dialogs->show(60332); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene604::Scene604(MADSEngine *vm) : Scene6xx(vm) { + _timebombHotspotId = -1; + _bombMode = -1; + _monsterFrame = -1; + + _monsterTimer = 0; + + _monsterActive = false; + _animationActiveFl = false; +} + +void Scene604::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_timebombHotspotId); + s.syncAsSint16LE(_bombMode); + s.syncAsSint16LE(_monsterFrame); + + s.syncAsUint32LE(_monsterTimer); + + s.syncAsByte(_monsterActive); + s.syncAsByte(_animationActiveFl); +} + +void Scene604::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SEA_MONSTER); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_TIMEBOMB); +} + +void Scene604::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(Resources::formatName(620, 'b', 0, EXT_SS, "")); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + if (_globals[kTimebombStatus] == 1) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST); + } + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_TIMEBOMB); + + _vm->_palette->setEntry(252, 63, 37, 26); + _vm->_palette->setEntry(253, 45, 24, 17); + _animationActiveFl = false; + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(72, 149); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->loadAnimation(formAnimName('R', 1), 70); + _animationActiveFl = true; + } else { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + } + + _monsterTimer = _scene->_frameStartTime; + _monsterActive = false; + + sceneEntrySound(); + _game.loadQuoteSet(0x2E7, 0x2E8, 0x2E9, 0x2EA, 0x2EB, 0x2EC, 0x2ED, 0x2EE, 0x2EF, 0x2F0, 0); +} + +void Scene604::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(30, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _game._player._stepEnabled = true; + _animationActiveFl = false; + break; + + default: + break; + } + + if (_monsterActive && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _monsterFrame) { + _monsterFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextMonsterFrame = -1; + + switch (_monsterFrame) { + case 50: + case 137: + case 174: { + int randVal = _vm->getRandomNumber(1, 1000); + if ((randVal <= 450) && (_game._player._special)) { + if (_game._player._special == 1) + nextMonsterFrame = 50; + else if (_game._player._special == 2) + nextMonsterFrame = 84; + else + nextMonsterFrame = 137; + } else if (randVal <= 150) + nextMonsterFrame = 50; + else if (randVal <= 300) + nextMonsterFrame = 84; + else if (randVal <= 450) + nextMonsterFrame = 137; + else if (randVal < 750) + nextMonsterFrame = 13; + else + nextMonsterFrame = 114; + + } + break; + + case 84: + nextMonsterFrame = 14; + break; + + default: + break; + } + + if ((nextMonsterFrame >= 0) && (nextMonsterFrame != _monsterFrame)) { + _scene->_activeAnimation->setCurrentFrame(nextMonsterFrame); + _monsterFrame = nextMonsterFrame; + } + } + } + + if ((!_monsterActive && !_animationActiveFl) && (_scene->_frameStartTime > (_monsterTimer + 4))) { + _monsterTimer = _scene->_frameStartTime; + if ((_vm->getRandomNumber(1, 1000) < 25) || !_game._visitedScenes._sceneRevisited) { + _monsterActive = true; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('m', -1)); + } + } +} + +void Scene604::handleBombActions() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + if (_bombMode == 1) + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 1); + else + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 3, 2); + + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 1: + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, -1); + _timebombHotspotId = _scene->_dynamicHotspots.add(NOUN_TIMEBOMB, VERB_WALKTO, _globals._sequenceIndexes[6], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_timebombHotspotId, Common::Point(166, 118), FACING_NORTHEAST); + _game._objects.setRoom(OBJ_TIMEBOMB, _scene->_currentSceneId); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_dynamicHotspots.remove(_timebombHotspotId); + _game._objects.addToInventory(OBJ_TIMEBOMB); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + if (_bombMode == 1) { + _vm->_dialogs->show(60421); + _globals[kTimebombStatus] = TIMEBOMB_ACTIVATED; + _globals[kTimebombTimer] = 0; + } else { + _vm->_dialogs->show(60423); + _globals[kTimebombStatus] = TIMEBOMB_DEACTIVATED; + _globals[kTimebombTimer] = 0; + } + break; + + default: + break; + } +} + +void Scene604::actions() { + if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if ((_action.isAction(VERB_PUT, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_VIEWPORT) || _action.isAction(VERB_THROW, NOUN_VIEWPORT)) + && (_action.isObject(NOUN_BOMB) || _action.isObject(NOUN_BOMBS))) + _vm->_dialogs->show(60420); + else if (_action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_LEDGE) || _action.isAction(VERB_PUT, NOUN_TIMEBOMB, NOUN_VIEWPORT)) { + _bombMode = 1; + if ((_game._difficulty == DIFFICULTY_HARD) || _globals[kWarnedFloodCity]) + handleBombActions(); + else if ((_game._objects.isInInventory(OBJ_POLYCEMENT) && _game._objects.isInInventory(OBJ_CHICKEN)) + && ((_globals[kLineStatus] == LINE_TIED) || ((_game._difficulty == DIFFICULTY_EASY) && (!_globals[kBoatRaised])))) + handleBombActions(); + else if (_game._difficulty == DIFFICULTY_EASY) + _vm->_dialogs->show(60424); + else { + _vm->_dialogs->show(60425); + _globals[kWarnedFloodCity] = true; + } + } else if (_action.isAction(VERB_TAKE, NOUN_TIMEBOMB)) { + if (_game._trigger || !_game._objects.isInInventory(OBJ_TIMEBOMB)) { + _bombMode = 2; + handleBombActions(); + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60411); + else if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) { + if (_monsterActive) { + _vm->_dialogs->show(60413); + } else { + _vm->_dialogs->show(60412); + } + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60414); + else if (_action.isAction(VERB_LOOK, NOUN_VENT)) + _vm->_dialogs->show(60415); + else if (_action.isAction(VERB_LOOK, NOUN_INDICATOR)) + _vm->_dialogs->show(60416); + else if (_action.isAction(VERB_LOOK, NOUN_SCULPTURE)) + _vm->_dialogs->show(60417); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60418); + else if (_action.isAction(VERB_LOOK, NOUN_FOUNTAIN)) + _vm->_dialogs->show(60419); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene605::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene605::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('r', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('l', -1)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('n', -1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('f', -1)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 15, 0, 0, 0); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 0, 0, 0); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 14, 0, 0, 0); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 13, 0, 0, 0); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 17, 0, 0, 0); + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 18, 0, 0, 0); + + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(600, 70); + _scene->_userInterface.setup(kInputLimitedSentences); + sceneEntrySound(); + _vm->_sound->command(22); +} + +void Scene605::step() { + if (_game._trigger == 70) { + _vm->_sound->command(23); + if (_globals[kResurrectRoom] >= 700) + _vm->_dialogs->show(60598); + else + _vm->_dialogs->show(60599); + + _scene->_nextSceneId = _globals[kResurrectRoom]; + } +} + +void Scene605::actions() { + return; +} + +/*------------------------------------------------------------------------*/ + +Scene607::Scene607(MADSEngine *vm) : Scene6xx(vm) { + _dogTimer = 0; + _lastFrameTime = 0; + + _dogLoop = false; + _dogEatsRex = false; + _dogBarking = false; + _shopAvailable = false; + + _animationMode = -1; + _animationActive = -1; + _counter = -1; +} + +void Scene607::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsUint32LE(_dogTimer); + s.syncAsUint32LE(_lastFrameTime); + + s.syncAsByte(_dogLoop); + s.syncAsByte(_dogEatsRex); + s.syncAsByte(_dogBarking); + s.syncAsByte(_shopAvailable); + + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_animationActive); + s.syncAsSint16LE(_counter); +} + +void Scene607::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene607::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3"); + + if (!_game._visitedScenes._sceneRevisited && (_scene->_priorSceneId != 608)) + _globals[kDogStatus] = 1; + + if ((_scene->_priorSceneId == 608) && (_globals[kDogStatus] < 3)) + _globals[kDogStatus] = 3; + + _animationActive = 0; + + if ((_globals[kDogStatus] == 1) && (_game._difficulty != DIFFICULTY_EASY)) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0)); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _dogBarking = false; + _dogLoop = false; + _shopAvailable = false; + _dogEatsRex = false; + _dogTimer = 0; + } else + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false); + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + + if (_scene->_priorSceneId == 608) { + _game._player._playerPos = Common::Point(297, 50); + _game._player._facing = FACING_SOUTHEAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(40, 104); + _game._player._facing = FACING_SOUTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->loadAnimation(formAnimName('R', 1), 80); + } else if (_globals[kDogStatus] == 2) { + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 7)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', 0)); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BONES); + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + _game.loadQuoteSet(0x2F8, 0x2F7, 0x2F6, 0x2F9, 0x2FA, 0); +} + +void Scene607::step() { + if (_globals[kDogStatus] == 2) { + int32 diff = _scene->_frameStartTime - _lastFrameTime; + if ((diff >= 0) && (diff <= 4)) + _dogTimer += diff; + else + _dogTimer++; + + _lastFrameTime = _scene->_frameStartTime; + } + + if ((_dogTimer >= 480) && !_dogLoop && !_shopAvailable && (_globals[kDogStatus] == 2) && !_game._player._special) { + _vm->_sound->command(14); + _dogLoop = true; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 10, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + _dogLoop = false; + _dogTimer = 0; + } + + if (_game._trigger == 91) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _dogBarking = false; + _globals[kDogStatus] = 1; + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, true); + } + + if (!_dogEatsRex && (_game._difficulty != DIFFICULTY_EASY) && !_animationActive && (_globals[kDogStatus] == 1) + && !_dogBarking && (_vm->getRandomNumber(1, 50) == 10)) { + _dogBarking = true; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 8, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _scene->_kernelMessages.reset(); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_SPRITE, 2, 100); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _counter = 0; + } + + if ((_game._trigger == 70) && !_dogEatsRex && (_globals[kDogStatus] == 1) && !_animationActive) { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_kernelMessages.reset(); + _dogBarking = false; + } + + if (_game._trigger == 100) { + _counter++; + _vm->_sound->command(12); + + if ((_counter >= 1) && (_counter <= 4)) { + Common::Point pos(0, 0); + switch (_counter) { + case 1: + pos = Common::Point(237, 5); + break; + + case 2: + pos = Common::Point(270, 15); + break; + + case 3: + pos = Common::Point(237, 25); + break; + + case 4: + pos = Common::Point(270, 36); + break; + + default: + break; + } + _scene->_kernelMessages.add(pos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2F9)); + } + } + + if (_game._player._moving && (_game._difficulty != DIFFICULTY_EASY) && !_shopAvailable && (_globals[kDogStatus] == 1) && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(268, 72), FACING_NORTHEAST); + _scene->_rails.resetNext(); + } + + if ((_game._player._special > 0) && (_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == 1) && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if ((_game._difficulty != DIFFICULTY_EASY) && (_globals[kDogStatus] == 1) && (_game._player._playerPos == Common::Point(268, 72)) + && (_game._trigger || !_dogEatsRex)) { + _dogEatsRex = true; + switch (_game._trigger) { + case 91: + case 0: + _animationActive = 1; + _game._player._visible = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FA)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + _scene->_sequences.addTimer(10, 64); + break; + + case 60: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 5, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 8, 45); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + } + break; + + case 61: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 46, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 62); + } + break; + + case 62: { + int syncIdx = _globals._sequenceIndexes[4]; + _animationActive = 2; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addTimer(60, 63); + } + break; + + case 63: + _vm->_dialogs->show(60729); + _animationActive = 0; + _dogEatsRex = false; + _scene->_reloadSceneFlag = true; + _game._player._stepEnabled = true; + break; + + case 64: + if (_dogEatsRex && (_animationActive == 1)) { + _vm->_sound->command(12); + _scene->_sequences.addTimer(10, 64); + } + break; + + default: + break; + } + } + + switch (_game._trigger) { + case 80: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 81); + break; + + case 81: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + break; + + case 82: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene607::handleThrowingBone() { + _animationActive = -1; + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('D', _animationMode), 1); + break; + + case 1: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + + if (_animationMode != 1) + _scene->_hotspots.activate(NOUN_OBNOXIOUS_DOG, false); + else { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + } + + _dogBarking = false; + if (_game._objects.isInInventory(OBJ_BONE)) { + _game._objects.setRoom(OBJ_BONE, 1); + if (_animationMode == 1) + _globals[kBone202Status] = 0; + } else { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } + + _scene->_sequences.addTimer(60, 2); + break; + + case 2: { + int quoteId = 0x2F8; + if (_animationMode == 1) + quoteId = 0x2F7; + + if (_animationMode == 2) { + _globals[kDogStatus] = 2; + _dogTimer = 0; + } + + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + _game._player._stepEnabled = true; + _animationActive = 0; + break; + + default: + break; + } +} + +void Scene607::preActions() { + if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG)) + _game._player._needToWalk = false; + + if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE) && (_globals[kDogStatus] == 2) && (_game._difficulty != DIFFICULTY_EASY)) { + _shopAvailable = true; + _dogTimer = 0; + } + + if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) + _game._player.walk(Common::Point(193, 100), FACING_NORTHEAST); + + if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE)) + _game._player.walk(Common::Point(201, 107), FACING_SOUTHEAST); +} + +void Scene607::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_SIDE_ENTRANCE)) + _scene->_nextSceneId = 608; + else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) { + if (_game._difficulty != DIFFICULTY_EASY) { + _animationMode = 1; + _scene->_kernelMessages.reset(); + if (_game._trigger == 0) + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6)); + + handleThrowingBone(); + } + } else if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_FENCE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FENCE)) && (_game._difficulty != DIFFICULTY_EASY) + && ((_globals[kDogStatus] == 1) || _game._trigger)) { + _animationMode = 2; + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F6)); + } + handleThrowingBone(); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_STREET)) { + if ((_globals[kDogStatus] == 1) || (_game._difficulty == DIFFICULTY_EASY)) + _vm->_dialogs->show(60710); + else + _vm->_dialogs->show(60711); + } else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(60712); + else if (_action.isAction(VERB_LOOK, NOUN_FENCE)) + _vm->_dialogs->show(60713); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60714); + else if (_action.isAction(VERB_LOOK, NOUN_MANHOLE)) + _vm->_dialogs->show(60715); + else if (_action.isAction(VERB_LOOK, NOUN_FIRE_HYDRANT) && (_globals[kDogStatus] == 1)) + _vm->_dialogs->show(60716); + else if (_action.isAction(VERB_LOOK, NOUN_SIGN)) + _vm->_dialogs->show(60717); + else if (_action.isAction(VERB_LOOK, NOUN_BROKEN_WINDOW)) + _vm->_dialogs->show(60718); + else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_DOOR)) + _vm->_dialogs->show(60719); + else if (_action.isAction(VERB_LOOK, NOUN_SIDEWALK)) + _vm->_dialogs->show(60720); + else if (_action.isAction(VERB_LOOK, NOUN_AIR_HOSE)) + _vm->_dialogs->show(60721); + else if (_action.isAction(VERB_LOOK, NOUN_AUTO_SHOP)) { + if (_globals[kDogStatus] == 1) + _vm->_dialogs->show(60723); + else + _vm->_dialogs->show(60722); + } else if (_action.isAction(VERB_LOOK, NOUN_SIDE_ENTRANCE)) { + if (_globals[kDogStatus] == 1) + _vm->_dialogs->show(60725); + else + _vm->_dialogs->show(60724); + } else if (_action.isAction(VERB_LOOK, NOUN_OBNOXIOUS_DOG)) + _vm->_dialogs->show(60726); + else if (_action.isAction(VERB_TALKTO, NOUN_OBNOXIOUS_DOG)) + _vm->_dialogs->show(60727); + else if (_action.isAction(VERB_LOOK, NOUN_BARRICADE)) + _vm->_dialogs->show(60728); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60730); + else if (_action.isObject(NOUN_GARAGE_DOOR) && (_action.isAction(VERB_OPEN) || _action.isAction(VERB_PUSH) || _action.isAction(VERB_PULL))) + _vm->_dialogs->show(60731); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene608::Scene608(MADSEngine *vm) : Scene6xx(vm) { + _carMode = -1; + _carFrame = -1; + _carMoveMode = -1; + _dogDeathMode = -1; + _carHotspotId = -1; + _barkCount = -1; + _polycementHotspotId = -1; + _animationMode = -1; + _nextTrigger = -1; + _throwMode = -1; + + _resetPositionsFl = false; + _dogActiveFl = false; + _dogBarkingFl = false; + _dogFirstEncounter = false; + _rexBeingEaten = false; + _dogHitWindow = false; + _checkFl = false; + _dogSquashFl = false; + _dogSafeFl = false; + _buttonPressedonTimeFl = false; + _dogUnderCar = false; + _dogYelping = false; + + _dogWindowTimer = -1; + _dogRunTimer = -1; + + _dogTimer1 = 0; + _dogTimer2 = 0; +} + +void Scene608::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_carMode); + s.syncAsSint16LE(_carFrame); + s.syncAsSint16LE(_carMoveMode); + s.syncAsSint16LE(_dogDeathMode); + s.syncAsSint16LE(_carHotspotId); + s.syncAsSint16LE(_barkCount); + s.syncAsSint16LE(_polycementHotspotId); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_nextTrigger); + s.syncAsSint16LE(_throwMode); + + s.syncAsByte(_resetPositionsFl); + s.syncAsByte(_dogActiveFl); + s.syncAsByte(_dogBarkingFl); + s.syncAsByte(_dogFirstEncounter); + s.syncAsByte(_rexBeingEaten); + s.syncAsByte(_dogHitWindow); + s.syncAsByte(_checkFl); + s.syncAsByte(_dogSquashFl); + s.syncAsByte(_dogSafeFl); + s.syncAsByte(_buttonPressedonTimeFl); + s.syncAsByte(_dogUnderCar); + s.syncAsByte(_dogYelping); + + s.syncAsSint32LE(_dogWindowTimer); + s.syncAsSint32LE(_dogRunTimer); + + s.syncAsUint32LE(_dogTimer1); + s.syncAsUint32LE(_dogTimer2); +} + +void Scene608::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_POLYCEMENT); + _scene->addActiveVocab(NOUN_CAR); + _scene->addActiveVocab(NOUN_OBNOXIOUS_DOG); +} + +void Scene608::resetDogVariables() { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + _dogBarkingFl = false; + _dogFirstEncounter = false; +} + +void Scene608::restoreAnimations() { + _scene->freeAnimation(); + _carMode = 0; + _game._player._stepEnabled = true; + if (_throwMode == 6) + _dogSquashFl = true; + + if (_globals[kCarStatus] == 0) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->loadAnimation(formAnimName('A', -1)); + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[8]); + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(6); + } +} + +void Scene608::setCarAnimations() { + _scene->freeAnimation(); + if (_globals[kCarStatus] == 0) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 98)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 67)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + } else { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[6], Common::Point(143, 128)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 6); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[7], Common::Point(141, 97)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[7], 15); + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[8], Common::Point(144, 126)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 5); + } +} + +void Scene608::handleThrowingBone() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + setCarAnimations(); + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _animationMode = -1; + _game._player._visible = false; + _carMode = _throwMode; + if (_throwMode == 4) + _scene->loadAnimation(formAnimName('X', 2), 1); + else if (_throwMode == 5) + _scene->loadAnimation(formAnimName('X', 1), 1); + else + _scene->loadAnimation(formAnimName('X', 3), 1); + break; + + case 1: + _nextTrigger = 1; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: + if (_nextTrigger != 2) + _scene->_sequences.addTimer(1, 2); + else { + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + else { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } + _scene->_sequences.addTimer(60, 3); + } + break; + + case 3: + if (_throwMode != 6) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x304)); + _scene->_sequences.addTimer(120, 4); + } else + restoreAnimations(); + break; + + case 4: + restoreAnimations(); + break; + + default: + break; + } +} + +void Scene608::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRD_7"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('c', 2)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1)); + + if (_game._objects.isInRoom(OBJ_POLYCEMENT)) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_POLYCEMENT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _polycementHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(249, 129), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 6); + } + + if (_game._objects.isInRoom(OBJ_REARVIEW_MIRROR)) { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites(formAnimName('m', -1)); + _globals._sequenceIndexes[12] = _scene->_sequences.startCycle(_globals._spriteIndexes[12], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_REARVIEW_MIRROR, VERB_WALKTO, _globals._sequenceIndexes[12], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(71, 113), FACING_NORTHEAST); + _scene->_sequences.setDepth(_globals._sequenceIndexes[12], 15); + } + + if (_game._difficulty == DIFFICULTY_HARD) { + _globals._spriteIndexes[9] = _scene->_sprites.addSprites(formAnimName('g', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('g', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('g', 2)); + _globals._spriteIndexes[10] = _scene->_sprites.addSprites(formAnimName('h', 2)); + _globals._spriteIndexes[11] = _scene->_sprites.addSprites(formAnimName('h', 3)); + _rexBeingEaten = false; + + if (!_game._visitedScenes._sceneRevisited) { + _globals[kDogStatus] = 3; + _dogActiveFl = true; + } else + _dogActiveFl = (_globals[kDogStatus] != 4); + } else { + _globals[kDogStatus] = 4; + _dogActiveFl = false; + } + + _dogSquashFl = false; + _buttonPressedonTimeFl = false; + _dogWindowTimer = 0; + _dogRunTimer = 0; + _dogHitWindow = false; + _checkFl = false; + _dogUnderCar = false; + _dogYelping = false; + + + if (!_game._visitedScenes._sceneRevisited) + _globals[kCarStatus] = 0; + + _animationMode = 0; + _carMoveMode = 0; + _carFrame = -1; + + if (_globals[kCarStatus] == 0) { + _carMode = 0; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('A', -1)); + } else if (_globals[kCarStatus] == 3) { + _carMode = 0; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(6); + } else if (_globals[kCarStatus] == 1) { + _carMode = 2; + _dogDeathMode = 0; + _resetPositionsFl = false; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_globals[kCarStatus] == 2) { + _carMode = 1; + _dogDeathMode = 2; + _resetPositionsFl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('B', -1)); + } else { + _carMode = 3; + _dogDeathMode = 2; + _resetPositionsFl = true; + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _scene->loadAnimation(formAnimName('D', -1)); + } + + _vm->_palette->setEntry(252, 63, 44, 30); + _vm->_palette->setEntry(253, 63, 20, 22); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(46, 132); + _game._player._facing = FACING_EAST; + if (_game._difficulty == DIFFICULTY_HARD) { + if (!_game._visitedScenes._sceneRevisited) + _dogFirstEncounter = true; + else if (_dogActiveFl) + resetDogVariables(); + } + } else if ((_game._difficulty == DIFFICULTY_HARD) && !_dogFirstEncounter && _dogActiveFl) { + if (!_dogUnderCar) + resetDogVariables(); + else { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); + } + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BONES); + + _game.loadQuoteSet(0x2FB, 0x2FC, 0x2FE, 0x2FD, 0x2FF, 0x300, 0x301, 0x302, 0x303, 0x304, 0); +} + +void Scene608::step() { + if (_dogFirstEncounter) { + long diff = _scene->_frameStartTime - _dogTimer1; + if ((diff >= 0) && (diff <= 1)) + _dogWindowTimer += diff; + else + _dogWindowTimer++; + + _dogTimer1 = _scene->_frameStartTime; + } + + if (_dogActiveFl && (_dogWindowTimer >= 2) && !_dogHitWindow) { + _dogHitWindow = true; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 11, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 1); + _vm->_sound->command(14); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _dogWindowTimer = 0; + } + + if (_game._trigger == 70) + resetDogVariables(); + + if ((_game._difficulty == DIFFICULTY_HARD) && !_animationMode && _dogActiveFl && !_dogFirstEncounter && !_dogUnderCar) { + if (!_dogBarkingFl) { + if (_vm->getRandomNumber(1, 50) == 10) { + _dogBarkingFl = true; + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 5, 8, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_OBNOXIOUS_DOG, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(194, 142), FACING_EAST); + _barkCount = 0; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 2, 100); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 60); + } + } else if (_game._trigger == 60) { + int syncIdx = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], syncIdx); + _scene->_kernelMessages.reset(); + _dogBarkingFl = false; + } + } + + if ((_game._trigger == 100) && _dogBarkingFl) { + _vm->_sound->command(12); + _barkCount++; + + if ((_barkCount >= 1) && (_barkCount <= 4)) { + Common::Point _barkPos(0, 0); + switch (_barkCount) { + case 1: + _barkPos = Common::Point(197, 66); + break; + + case 2: + _barkPos = Common::Point(230, 76); + break; + + case 3: + _barkPos = Common::Point(197, 86); + break; + + case 4: + _barkPos = Common::Point(230, 97); + break; + + default: + break; + } + _scene->_kernelMessages.add(_barkPos, 0xFDFC, 0, 0, 120, _game.getQuote(0x2FB)); + } + } + + if (_dogSquashFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) { + long diff = _scene->_frameStartTime - _dogTimer2; + if ((diff >= 0) && (diff <= 4)) + _dogRunTimer += diff; + else + _dogRunTimer++; + + _dogTimer2 = _scene->_frameStartTime; + } + + if (_dogRunTimer >= 480 && !_checkFl && !_buttonPressedonTimeFl && !_dogFirstEncounter && _dogUnderCar && _dogActiveFl) { + _checkFl = true; + _dogSquashFl = false; + _dogSafeFl = true; + _checkFl = false; + _dogRunTimer = 0; + } else { + _dogSafeFl = false; + if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0) && _dogUnderCar) + _dogSafeFl = true; + } + + if (_dogActiveFl && _dogSafeFl && !_buttonPressedonTimeFl) { + _dogDeathMode = 0; + _globals[kCarStatus] = 0; + _carMode = 0; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _dogUnderCar = false; + _dogYelping = false; + _scene->_kernelMessages.reset(); + _globals._sequenceIndexes[11] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[11], false, 6, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[11], SEQUENCE_TRIGGER_EXPIRE, 0, 92); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FF)); + } + + if (_game._trigger == 92) { + resetDogVariables(); + _animationMode = 0; + } + + if ((_carMode == 4) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_carFrame == 10) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 56) { + resetDogVariables(); + _animationMode = 0; + _nextTrigger = 2; + } + } + } + + if ((_carMode == 5) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + if (_carFrame == 10) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 52) { + resetDogVariables(); + _animationMode = 0; + _nextTrigger = 2; + } + } + } + + if ((_carMode == 6) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_carFrame == 11) { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + } else if (_carFrame == 41) { + _globals._sequenceIndexes[10] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[10], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[10], 10, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[10], 6); + _dogUnderCar = true; + _nextTrigger = 2; + } + } + } + + if (_dogUnderCar) { + if (!_dogYelping) { + if (_vm->getRandomNumber(1, 50) == 10) { + _dogYelping = true; + _barkCount = 0; + _scene->_sequences.addTimer(12, 110); + _scene->_sequences.addTimer(22, 111); + _scene->_sequences.addTimer(120, 112); + } + _scene->_kernelMessages.reset(); + } + } else + _dogYelping = false; + + if (_game._trigger == 110) { + _vm->_sound->command(12); + _scene->_kernelMessages.add(Common::Point(150, 97), 0xFDFC, 0, 0, 60, _game.getQuote(0x303)); + } + + if (_game._trigger == 111) { + _vm->_sound->command(12); + _scene->_kernelMessages.add(Common::Point(183, 93), 0xFDFC, 0, 0, 60, _game.getQuote(0x303)); + } + + if (_game._trigger == 112) + _dogYelping = false; + + if ((_carMode == 0) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if ((_globals[kCarStatus] == 0) || (_globals[kCarStatus] == 3)) { + switch (_carMoveMode) { + case 0: + if (_globals[kCarStatus] == 0) + nextFrame = 0; + else + nextFrame = 6; + break; + + case 1: + if (_scene->_activeAnimation->getCurrentFrame() >= 12) { + nextFrame = 0; + _carMoveMode = 0; + _globals[kCarStatus] = 0; + } + break; + + case 2: + if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + _globals[kCarStatus] = 3; + } + break; + + default: + break; + } + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if ((_carMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_carMoveMode == 0) + nextFrame = 28; + else if (_scene->_activeAnimation->getCurrentFrame() >= 28) { + nextFrame = 28; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if ((_carMode == 3) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_resetPositionsFl) { + nextFrame = 0; + _carMoveMode = 0; + } else if (_carMoveMode == 0) + nextFrame = 6; + else if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + + if ((_carMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _carFrame) { + _carFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + if (_resetPositionsFl) { + nextFrame = 0; + _carMoveMode = 0; + } else if (_carMoveMode == 0) + nextFrame = 6; + else if (_scene->_activeAnimation->getCurrentFrame() >= 6) { + nextFrame = 6; + _carMoveMode = 0; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _carFrame = nextFrame; + } + } + } + + if (_game._player._moving && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_scene->_rails.getNext() > 0)) { + _game._player.cancelCommand(); + _game._player.startWalking(Common::Point(194, 142), FACING_EAST); + _scene->_rails.resetNext(); + if (_dogUnderCar) + _dogSafeFl = true; + } + + if (_game._player._special > 0 && (_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && _game._player._stepEnabled) + _game._player._stepEnabled = false; + + if ((_game._difficulty == DIFFICULTY_HARD) && _dogActiveFl && (_game._player._playerPos == Common::Point(194, 142)) + && (_game._trigger || !_rexBeingEaten)) { + _rexBeingEaten = true; + switch (_game._trigger) { + case 0: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _animationMode = 1; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _scene->_sequences.addTimer(10, 85); + break; + + case 80: + _game._player._visible = false; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 3, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], -1); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FC)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], false, 5, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 6, 38); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 82); + } + break; + + case 82: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], false, 15, 5, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 39, 40); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 83); + } + break; + + case 83: { + _animationMode = 2; + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[9], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.addTimer(60, 84); + } + break; + + case 84: + _rexBeingEaten = false; + _animationMode = 0; + _scene->_reloadSceneFlag = true; + _game._player._stepEnabled = true; + break; + + case 85: + if (_rexBeingEaten && (_animationMode == 1)) { + _vm->_sound->command(12); + _scene->_sequences.addTimer(10, 85); + } + break; + + default: + break; + } + } +} + +void Scene608::preActions() { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + + if ((_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) && _dogActiveFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(56, 146), FACING_EAST); + } + + if ((_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) && _dogActiveFl) { + _game._player._stepEnabled = false; + _game._player.walk(Common::Point(75, 136), FACING_EAST); + } + + if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON) && _dogUnderCar) { + _buttonPressedonTimeFl = true; + _dogDeathMode = 1; + } else + _buttonPressedonTimeFl = false; +} + +void Scene608::actions() { + if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOORWAY)) + _scene->_nextSceneId = 607; + else if (_action.isAction(VERB_PUSH, NOUN_DOWN_BUTTON)) { + _game._player._stepEnabled = true; + switch (_game._trigger) { + case 0: + if ((_globals[kCarStatus] == 0) || (_globals[kCarStatus] == 1) || (_globals[kCarStatus] == 2)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else + _vm->_dialogs->show(60839); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + if (_dogDeathMode == 0) + _carMode = 0; + else if (_dogDeathMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x300)); + _globals[kCarStatus] = 1; + _carMode = 2; + _globals[kDogStatus] = 4; + _dogActiveFl = false; + _dogUnderCar = false; + _scene->_sequences.remove(_globals._sequenceIndexes[10]); + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('C', -1)); + } else { + _resetPositionsFl = false; + _carMode = 1; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('B', -1)); + } + + _carMoveMode = 2; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: + if (_carMoveMode != 0) + _scene->_sequences.addTimer(1, 2); + else { + _scene->_dynamicHotspots.remove(_carHotspotId); + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(100, 100, 100 + 82, 100 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + if (_globals[kCarStatus] == 1) + _scene->_sequences.addTimer(120, 3); + else { + if (_dogDeathMode == 0) + _globals[kCarStatus] = 3; + else { + _globals[kCarStatus] = 4; + _carMode = 3; + _dogDeathMode = 2; + } + _game._player._stepEnabled = true; + } + } + break; + + case 3: + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x302)); + _globals[kCarStatus] = 4; + _carMode = 3; + _dogDeathMode = 2; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUSH, NOUN_UP_BUTTON)) { + switch (_game._trigger) { + case 0: + if ((_globals[kCarStatus] == 3) || (_globals[kCarStatus] == 4)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 3); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + } else + _vm->_dialogs->show(60840); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + if (_dogDeathMode == 0) + _carMode = 0; + else { + _carMode = 3; + _resetPositionsFl = false; + _scene->freeAnimation(); + _scene->loadAnimation(formAnimName('D', -1)); + } + _carMoveMode = 1; + _scene->_sequences.addTimer(1, 2); + break; + + case 2: { + if (_carMoveMode != 0) + _scene->_sequences.addTimer(1, 2); + else if (_dogDeathMode == 0) + _globals[kCarStatus] = 0; + else if (_dogDeathMode == 2) { + _globals[kCarStatus] = 2; + _carMode = 3; + _dogDeathMode = 2; + } + _scene->_dynamicHotspots.remove(_carHotspotId); + int idx = _scene->_dynamicHotspots.add(NOUN_CAR, VERB_WALKTO, -1, Common::Rect(99, 69, 99 + 82, 69 + 25)); + _carHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(96, 132), FACING_NORTHEAST); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_REAR_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_REAR_OF_GARAGE) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_OBNOXIOUS_DOG) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_OBNOXIOUS_DOG)) { + _game._player._stepEnabled = true; + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FE)); + } + _throwMode = 4; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_FRONT_OF_GARAGE)) { + _game._player._stepEnabled = true; + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2FD)); + } + _throwMode = 5; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else if (_action.isAction(VERB_THROW, NOUN_BONES, NOUN_AREA_BEHIND_CAR) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_AREA_BEHIND_CAR) + || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_DANGER_ZONE) || _action.isAction(VERB_THROW, NOUN_BONE, NOUN_DANGER_ZONE)) { + _game._player._stepEnabled = true; + if ((_globals[kCarStatus] == 0) && _dogActiveFl) { + if (_dogActiveFl) { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x301)); + } + _throwMode = 6; + handleThrowingBone(); + } else + _vm->_dialogs->show(60841); + } else + _vm->_dialogs->show(60842); + } else if (_action.isAction(VERB_TAKE, NOUN_POLYCEMENT) && (_game._trigger || !_game._objects.isInInventory(OBJ_POLYCEMENT))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_polycementHotspotId); + break; + + case 2: + _game._objects.addToInventory(OBJ_POLYCEMENT); + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + _vm->_dialogs->showItem(OBJ_POLYCEMENT, 60833); + break; + + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_REARVIEW_MIRROR) && (_game._trigger || !_game._objects.isInInventory(OBJ_REARVIEW_MIRROR))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 6, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[12]); + _game._objects.addToInventory(OBJ_REARVIEW_MIRROR); + _vm->_dialogs->showItem(OBJ_REARVIEW_MIRROR, 60827); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_game._difficulty != DIFFICULTY_HARD) + _vm->_dialogs->show(60810); + else if (_globals[kDogStatus] == 4) + _vm->_dialogs->show(60812); + else + _vm->_dialogs->show(60811); + } else if (_action.isAction(VERB_LOOK) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP) + || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL))) + _vm->_dialogs->show(60813); + else if (_action.isAction(VERB_TAKE) && (_action.isObject(NOUN_MUFFLER) || _action.isObject(NOUN_CAR_SEAT) || _action.isObject(NOUN_HUBCAP) + || _action.isObject(NOUN_COILS) || _action.isObject(NOUN_QUARTER_PANEL))) + _vm->_dialogs->show(60814); + else if (_action.isAction(VERB_LOOK, NOUN_GARAGE_FLOOR) || _action.isAction(VERB_LOOK, NOUN_FRONT_OF_GARAGE) || _action.isAction(VERB_LOOK, NOUN_REAR_OF_GARAGE)) { + if (_dogActiveFl) + _vm->_dialogs->show(60815); + else + _vm->_dialogs->show(60816); + } else if (_action.isAction(VERB_LOOK, NOUN_SPARE_RIBS)) + _vm->_dialogs->show(60817); + else if (_action.isAction(VERB_TAKE, NOUN_SPARE_RIBS)) { + if (_game._difficulty == DIFFICULTY_HARD) + _vm->_dialogs->show(60818); + else + _vm->_dialogs->show(60819); + } else if (_action.isAction(VERB_LOOK, NOUN_UP_BUTTON)) + _vm->_dialogs->show(60820); + else if (_action.isAction(VERB_LOOK, NOUN_DOWN_BUTTON)) + _vm->_dialogs->show(60821); + else if (_action.isAction(VERB_LOOK, NOUN_TRASH_CAN)) + _vm->_dialogs->show(60822); + else if (_action.isAction(VERB_LOOK, NOUN_CALENDAR)) + _vm->_dialogs->show(60823); + else if (_action.isAction(VERB_LOOK, NOUN_STORAGE_BOX)) { + if (_game._objects[OBJ_REARVIEW_MIRROR]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60825); + else + _vm->_dialogs->show(60824); + } else if (_action.isAction(VERB_OPEN, NOUN_STORAGE_BOX)) + _vm->_dialogs->show(60826); + else if (_action.isAction(VERB_LOOK, NOUN_REARVIEW_MIRROR) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(60828); + else if (_action.isAction(VERB_LOOK, NOUN_TOOL_BOX)) { + if (_game._objects[OBJ_POLYCEMENT]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(60829); + else + _vm->_dialogs->show(60830); + } else if (_action.isAction(VERB_OPEN, NOUN_TOOL_BOX)) + _vm->_dialogs->show(60831); + else if ((_action.isAction(VERB_LOOK, NOUN_POLYCEMENT)) && (_game._objects.isInRoom(OBJ_POLYCEMENT))) + _vm->_dialogs->show(60832); + else if (_action.isAction(VERB_LOOK, NOUN_GREASE_CAN) || _action.isAction(VERB_LOOK, NOUN_OIL_CAN)) + _vm->_dialogs->show(60834); + else if (_action.isAction(VERB_LOOK, NOUN_CAR_LIFT)) + _vm->_dialogs->show(60835); + else if (_action.isAction(VERB_LOOK, NOUN_CHAIR) || _action.isAction(VERB_LOOK, NOUN_HAT)) + _vm->_dialogs->show(60836); + else if (_action.isAction(VERB_LOOK, NOUN_DANGER_ZONE)) + _vm->_dialogs->show(60838); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene609::Scene609(MADSEngine *vm) : Scene6xx(vm) { + _videoDoorMode = -1; +} + +void Scene609::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_videoDoorMode); +} + +void Scene609::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene609::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('h', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXCD_9"); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMRC_9"); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + + if (!_game._visitedScenes._sceneRevisited) + _globals[kBeenInVideoStore] = false; + + if (_scene->_priorSceneId == 611) { + _game._player._playerPos = Common::Point(264, 69); + _game._player._facing = FACING_SOUTHWEST; + } else if (_scene->_priorSceneId == 610) { + _game._player._playerPos = Common::Point(23, 90); + _game._player._facing = FACING_EAST; + _scene->_sequences.addTimer(60, 60); + _game._player._stepEnabled = false; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(86, 136); + _game._player._facing = FACING_NORTHEAST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_DOOR_KEY); + if (_game._difficulty != DIFFICULTY_EASY) + _game._objects.addToInventory(OBJ_PENLIGHT); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x305, 0x306, 0x307, 0x308, 0x309, 0); +} + +void Scene609::step() { + switch (_game._trigger) { + case 60: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false); + _game._player.walk(Common::Point(101, 100), FACING_EAST); + _scene->_sequences.addTimer(180, 62); + break; + + case 62: + _scene->_sequences.remove( _globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + break; + + case 63: + if (!_globals[kHasTalkedToHermit] && (_game._difficulty != DIFFICULTY_HARD)) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); + } + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _game._player._stepEnabled = true; + break; + + default: + break; + } + + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + if (!_globals[kHasTalkedToHermit]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 26, 2, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + _scene->_sequences.setPosition(_globals._sequenceIndexes[3], Common::Point(287, 73)); + _scene->_sequences.setScale(_globals._sequenceIndexes[3], 47); + } + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene609::enterStore() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + if (_videoDoorMode == 2) + _scene->_sequences.addTimer(1, 4); + else { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x305)); + _scene->_sequences.addTimer(120, 1); + } + break; + + case 1: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x306)); + _scene->_sequences.addTimer(60, 2); + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 11, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._objects.setRoom(OBJ_DOOR_KEY, 1); + _scene->_sequences.addTimer(15, 4); + break; + + case 4: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(15, 5); + break; + + case 5: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 6); + break; + + case 6: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, false); + if (_videoDoorMode == 1) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 180, _game.getQuote(0x307)); + } + _game._player.walk(Common::Point(23, 90), FACING_WEST); + _scene->_sequences.addTimer(180, 7); + break; + + case 7: + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 8); + break; + + case 8: + _scene->_hotspots.activate(NOUN_VIDEO_STORE_DOOR, true); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + _globals[kBeenInVideoStore] = true; + _game._player._stepEnabled = true; + _scene->_nextSceneId = 610; + break; + + default: + break; + } +} + +void Scene609::preActions() { + if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR)) + _game._player.walk(Common::Point(78, 99), FACING_NORTHWEST); +} + +void Scene609::actions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_ALLEY)) + _scene->_nextSceneId = 611; + else if (_action.isAction(VERB_WALK_THROUGH, NOUN_VIDEO_STORE_DOOR)) { + if (!_globals[kBeenInVideoStore]) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x308)); + _scene->_sequences.addTimer(120, 1); + break; + + case 1: + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], true, 1); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addTimer(30, 2); + break; + + case 2: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(60, 3); + break; + + case 3: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x309)); + _scene->_sequences.addTimer(120, 4); + break; + + case 4: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else { + _videoDoorMode = 2; + enterStore(); + } + } else if (_action.isAction(VERB_UNLOCK, NOUN_DOOR_KEY, NOUN_VIDEO_STORE_DOOR)) { + _videoDoorMode = 1; + enterStore(); + } else if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 5); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(60910); + else if (_action.isAction(VERB_LOOK, NOUN_STREET)) + _vm->_dialogs->show(60911); + else if (_action.isAction(VERB_LOOK, NOUN_SPOT_A_POT)) + _vm->_dialogs->show(60912); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE)) + _vm->_dialogs->show(60913); + else if (_action.isAction(VERB_LOOK, NOUN_BILLBOARD)) + _vm->_dialogs->show(60914); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(60915); + else if (_action.isAction(VERB_LOOK, NOUN_CAR)) + _vm->_dialogs->show(60916); + else if (_action.isAction(VERB_LOOK, NOUN_NEWSSTAND)) + _vm->_dialogs->show(60917); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE_DOOR)) { + if (!_globals[kBeenInVideoStore]) + _vm->_dialogs->show(60918); + else + _vm->_dialogs->show(60919); + } else if (_action.isAction(VERB_WALK_DOWN, NOUN_STREET)) + _vm->_dialogs->show(60730); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene610::Scene610(MADSEngine *vm) : Scene6xx(vm) { + _handsetHotspotId = -1; + _checkVal = -1; + + _cellCharging = false; + + _cellChargingTimer = -1; + _lastFrameTimer = 0; +} + +void Scene610::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_handsetHotspotId); + s.syncAsSint16LE(_checkVal); + + s.syncAsByte(_cellCharging); + + s.syncAsSint32LE(_cellChargingTimer); + s.syncAsUint32LE(_lastFrameTimer); +} + +void Scene610::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_PHONE_HANDSET); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene610::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_9"); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 1)); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 60, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 13); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 30, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 9); + + if (!_game._visitedScenes._sceneRevisited) + _cellCharging = false; + + if (_game._objects[OBJ_PHONE_HANDSET]._roomNumber == _scene->_currentSceneId) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST); + if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged]) + _globals[kHandsetCellStatus] = 1; + } + + if (_scene->_roomChanged && _game._difficulty != DIFFICULTY_EASY) + _game._objects.addToInventory(OBJ_PENLIGHT); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(175, 152); + _game._player._facing = FACING_NORTHWEST; + } + + sceneEntrySound(); +} + +void Scene610::step() { + if (_cellCharging) { + long diff = _scene->_frameStartTime - _lastFrameTimer; + if ((diff >= 0) && (diff <= 60)) + _cellChargingTimer += diff; + else + _cellChargingTimer++; + + _lastFrameTimer = _scene->_frameStartTime; + } + + // CHECKME: _checkVal is always false, could be removed + if ((_cellChargingTimer >= 60) && !_checkVal) { + _checkVal = true; + _globals[kHandsetCellStatus] = 1; + _cellCharging = false; + _checkVal = false; + _cellChargingTimer = 0; + } +} + +void Scene610::actions() { + if (_action.isAction(VERB_EXIT_FROM, NOUN_VIDEO_STORE)) + _scene->_nextSceneId = 609; + else if (_action.isAction(VERB_TAKE, NOUN_PHONE_HANDSET)) { + if ( _game._trigger || !_game._objects.isInInventory(OBJ_PHONE_HANDSET)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_handsetHotspotId); + _game._objects.addToInventory(OBJ_PHONE_HANDSET); + _vm->_dialogs->showItem(OBJ_PHONE_HANDSET, 61017); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } + } else if (_action.isAction(VERB_PUT, NOUN_PHONE_HANDSET, NOUN_PHONE_CRADLE)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 0, 0, 0); + _handsetHotspotId = _scene->_dynamicHotspots.add(NOUN_PHONE_HANDSET, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(_handsetHotspotId, Common::Point(132, 121), FACING_NORTHWEST); + _game._objects.setRoom(OBJ_PHONE_HANDSET, _scene->_currentSceneId); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _game._player._stepEnabled = true; + if ((_globals[kHandsetCellStatus] == 2) && (_game._difficulty == DIFFICULTY_HARD) && !_globals[kDurafailRecharged]) + _cellCharging = true; + + _vm->_dialogs->show(61032); + break; + + default: + break; + } + } else if (_action.isAction(VERB_LOOK, NOUN_PIPPY_BILLBOARD)) + _vm->_dialogs->show(61010); + else if (_action.isAction(VERB_LOOK, NOUN_CIVILIZATION_AD)) + _vm->_dialogs->show(61011); + else if (_action.isAction(VERB_LOOK, NOUN_MARX_BROS_POSTER)) + _vm->_dialogs->show(61012); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_MONITOR)) + _vm->_dialogs->show(61013); + else if (_action.isAction(VERB_LOOK, NOUN_VIDEO_STORE)) + _vm->_dialogs->show(61014); + else if (_action._lookFlag) + _vm->_dialogs->show(61015); + else if (_action.isAction(VERB_LOOK, NOUN_LOGO)) + _vm->_dialogs->show(61018); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT)) { + if (_game._visitedScenes.exists(601)) + _vm->_dialogs->show(61020); + else + _vm->_dialogs->show(61019); + } else if (_action.isAction(VERB_LOOK, NOUN_COUNTER)) + _vm->_dialogs->show(61021); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_ANTENNA)) + _vm->_dialogs->show(61022); + else if (_action.isAction(VERB_LOOK, NOUN_SMELLY_SNEAKER)) + _vm->_dialogs->show(61023); + else if (_action.isAction(VERB_TAKE, NOUN_SMELLY_SNEAKER)) + _vm->_dialogs->show(61024); + else if (_action.isAction(VERB_LOOK, NOUN_SPOTLIGHT)) + _vm->_dialogs->show(61025); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_HANDSET) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(61026); + else if (_action.isAction(VERB_LOOK, NOUN_PHONE_CRADLE)) + _vm->_dialogs->show(61027); + else if (_action.isAction(VERB_LOOK, NOUN_RETURN_SLOT)) + _vm->_dialogs->show(61028); + else if (_action.isAction(VERB_PUT, NOUN_RETURN_SLOT) + && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) + _vm->_dialogs->show(61029); + else if ( _action.isObject(NOUN_CLASSIC_VIDEOS) || _action.isObject(NOUN_MORE_CLASSIC_VIDEOS) || _action.isObject(NOUN_DRAMA_VIDEOS) + || _action.isObject(NOUN_NEW_RELEASE_VIDEOS) || _action.isObject(NOUN_PORNO_VIDEOS) || _action.isObject(NOUN_EDUCATIONAL_VIDEOS) + || _action.isObject(NOUN_INSTRUCTIONAL_VIDEOS) || _action.isObject(NOUN_WORKOUT_VIDEOS) || _action.isObject(NOUN_FOREIGN_VIDEOS) + || _action.isObject(NOUN_ADVENTURE_VIDEOS) || _action.isObject(NOUN_COMEDY_VIDEOS)) { + if (_action.isAction(VERB_LOOK)) + _vm->_dialogs->show(61030); + else if (_action.isAction(VERB_TAKE)) + _vm->_dialogs->show(61031); + else + return; + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene611::Scene611(MADSEngine *vm) : Scene6xx(vm), _defaultDialogPos(0, 0) { + _seenRatFl = false; + _eyesRunningFl = false; + _shouldRemoveEyes = false; + _ratPresentFl = false; + _duringDialogFl = false; + _resetBatterieText = false; + _hermitTalkingFl = false; + _hermitMovingFl = false; + _alreadyTalkingFl = false; + _giveBatteriesFl = false; + _startTradingFl = false; + _check1Fl = false; + _stickFingerFl = false; + + _randVal = -1; + _ratHotspotId = -1; + _hermitDialogNode = -1; + _hermitDisplayedQuestion = -1; + _nextFrame = -1; + _hermitMode = -1; + + _ratTimer = 0; +} + +void Scene611::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsByte(_seenRatFl); + s.syncAsByte(_eyesRunningFl); + s.syncAsByte(_shouldRemoveEyes); + s.syncAsByte(_ratPresentFl); + s.syncAsByte(_duringDialogFl); + s.syncAsByte(_resetBatterieText); + s.syncAsByte(_hermitTalkingFl); + s.syncAsByte(_hermitMovingFl); + s.syncAsByte(_alreadyTalkingFl); + s.syncAsByte(_giveBatteriesFl); + s.syncAsByte(_startTradingFl); + s.syncAsByte(_check1Fl); + s.syncAsByte(_stickFingerFl); + + s.syncAsSint16LE(_randVal); + s.syncAsSint16LE(_ratHotspotId); + s.syncAsSint16LE(_hermitDialogNode); + s.syncAsSint16LE(_hermitDisplayedQuestion); + s.syncAsSint16LE(_nextFrame); + s.syncAsSint16LE(_hermitMode); + + s.syncAsUint32LE(_ratTimer); + + s.syncAsSint16LE(_defaultDialogPos.x); + s.syncAsSint16LE(_defaultDialogPos.y); +} + +void Scene611::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_RAT); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene611::handleRatMoves() { + _ratPresentFl = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 11, -2); + _ratTimer = _game._player._priorTimer; + _scene->_dynamicHotspots.remove(_ratHotspotId); +} + +void Scene611::handleTrading() { + if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) + _game._objects.setRoom(OBJ_DURAFAIL_CELLS, 1); + + if (_game._objects.isInInventory(OBJ_PHONE_CELLS)) + _game._objects.setRoom(OBJ_PHONE_CELLS, 1); + + _game._objects.addToInventory(OBJ_FAKE_ID); +} + +void Scene611::setDialogNode(int node) { + if (node > 0) + _hermitDialogNode = node; + + _game._player._stepEnabled = true; + + switch (node) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _duringDialogFl = false; + _hermitDialogNode = 0; + break; + + case 1: + _dialog1.start(); + _duringDialogFl = true; + _hermitDialogNode = 1; + break; + + case 2: + _dialog2.start(); + _duringDialogFl = true; + _hermitDialogNode = 2; + break; + + default: + break; + } +} + +bool Scene611::check2ChargedBatteries() { + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) + || (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS))) + return true; + + return false; +} + +bool Scene611::check4ChargedBatteries() { + if (_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS) && _globals[136]) + return true; + + return false; +} + +void Scene611::handleTalking(int delay) { + if (_hermitTalkingFl) + _alreadyTalkingFl = true; + + _hermitTalkingFl = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(delay, 100); +} + +void Scene611::handleSubDialog1() { + switch (_action._activeAction._verbId) { + case 0x287: + _stickFingerFl = true; + _nextFrame = 34; + _hermitMovingFl = false; + _hermitMode = 5; + displayHermitQuestions(5); + _dialog1.write(0x287, false); + if (!_dialog1.read(0x288)) + _dialog1.write(0x28E, true); + + _dialog2.write(0x29C, true); + _dialog2.write(0x29D, true); + _dialog2.write(0x29E, true); + setDialogNode(2); + break; + + case 0x288: + handleTalking(500); + displayHermitQuestions(6); + _dialog1.write(0x288, false); + _dialog1.write(0x289, true); + if (!_dialog1.read(0x287)) + _dialog1.write(0x28E, true); + + setDialogNode(1); + break; + + case 0x289: + handleTalking(500); + displayHermitQuestions(10); + _dialog1.write(0x289, false); + _dialog1.write(0x28A, true); + _dialog1.write(0x28B, true); + setDialogNode(1); + break; + + case 0x28A: + handleTalking(500); + displayHermitQuestions(11); + _dialog1.write(0x28A, false); + setDialogNode(1); + break; + + case 0x28B: + handleTalking(500); + displayHermitQuestions(12); + _dialog1.write(0x28C, true); + _dialog1.write(0x28D, true); + _dialog1.write(0x28B, false); + setDialogNode(1); + break; + + case 0x28C: + handleTalking(500); + displayHermitQuestions(13); + _dialog1.write(0x28C, false); + setDialogNode(1); + break; + + case 0x28D: + handleTalking(500); + displayHermitQuestions(14); + _dialog1.write(0x290, true); + _dialog1.write(0x28D, false); + _dialog1.write(0x28F, true); + setDialogNode(1); + break; + + case 0x28E: + handleTalking(500); + displayHermitQuestions(15); + _dialog1.write(0x295, true); + _dialog1.write(0x28E, false); + setDialogNode(1); + break; + + case 0x290: + handleTalking(500); + displayHermitQuestions(17); + _dialog1.write(0x290, false); + _dialog1.write(0x28E, false); + if (!_dialog1.read(0x28F)) + _dialog1.write(0x291, true); + + setDialogNode(1); + break; + + case 0x291: + handleTalking(500); + displayHermitQuestions(18); + _dialog1.write(0x291, false); + if ((!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) && (!_game._objects.isInInventory(OBJ_PHONE_CELLS))) { + _dialog1.write(0x292, true); + _dialog1.write(0x293, true); + } + + if ((_game._objects.isInInventory(OBJ_DURAFAIL_CELLS)) || (_game._objects.isInInventory(OBJ_PHONE_CELLS))) + _dialog1.write(0x294, true); + + if (!_game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && !_game._objects.isInInventory(OBJ_PHONE_CELLS)) + _globals[kExecuted_1_11] = true; + + setDialogNode(1); + break; + + case 0x28F: + handleTalking(500); + displayHermitQuestions(16); + _dialog1.write(0x28F, false); + if (!_dialog1.read(0x290)) + _dialog1.write(0x291, true); + + setDialogNode(1); + break; + + case 0x295: + handleTalking(500); + displayHermitQuestions(20); + _dialog1.write(0x295, false); + setDialogNode(1); + break; + + case 0x292: + handleTalking(500); + displayHermitQuestions(19); + _dialog1.write(0x292, false); + _dialog1.write(0x293, false); + setDialogNode(1); + break; + + case 0x293: { + handleTalking(200); + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x2D1); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote); + + curQuote = _game.getQuote(0x2D2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + + _dialog1.write(0x293, false); + setDialogNode(0); + } + break; + + case 0x294: { + bool hermitPleasedFl = false; + + switch (_game._difficulty) { + case DIFFICULTY_EASY: + hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) || _game._objects.isInInventory(OBJ_PHONE_CELLS); + break; + + case DIFFICULTY_MEDIUM: + hermitPleasedFl = _game._objects.isInInventory(OBJ_DURAFAIL_CELLS) && _game._objects.isInInventory(OBJ_PHONE_CELLS); + break; + + default: // HARD + hermitPleasedFl = check4ChargedBatteries(); + break; + } + + if (hermitPleasedFl) { + _hermitDisplayedQuestion = 21; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } else if (((_game._difficulty == DIFFICULTY_MEDIUM) || (_game._difficulty == DIFFICULTY_HARD)) && check2ChargedBatteries()) { + _hermitDisplayedQuestion = 22; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } else { + _hermitDisplayedQuestion = 23; + if (!_giveBatteriesFl) + setDialogNode(0); + else + _giveBatteriesFl = false; + } + _startTradingFl = true; + } + break; + + case 0x296: { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x2E6); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + + setDialogNode(0); + handleTalking(200); + } + break; + + default: + break; + } +} + +void Scene611::handleSubDialog2() { + switch (_action._activeAction._verbId) { + case 0x29C: + displayHermitQuestions(7); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29D: + displayHermitQuestions(8); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29E: + displayHermitQuestions(9); + setDialogNode(1); + handleTalking(500); + break; + + case 0x29F: { + _scene->_kernelMessages.reset(); + Common::String curQuote = _game.getQuote(0x2A7); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + setDialogNode(0); + _dialog2.write(0x29F, false); + } + break; + + default: + break; + } +} + +void Scene611::handleDialog() { + if (_game._trigger == 0) { + _scene->_kernelMessages.reset(); + _game._player._stepEnabled = false; + + Common::String curQuote = _game.getQuote(_action._activeAction._verbId); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + + if (width > 200) { + Common::String subQuote1, subQuote2; + _game.splitQuote(curQuote, subQuote1, subQuote2); + _scene->_kernelMessages.add(Common::Point(0, -14), 0x1110, 34, 0, 150, subQuote1); + + if (_action._activeAction._verbId == 0x29D) + _scene->_kernelMessages.add(Common::Point(-18, 0), 0x1110, 34, 1, 150, subQuote2); + else if (_action._activeAction._verbId == 0x28A) + _scene->_kernelMessages.add(Common::Point(-10, 0), 0x1110, 34, 1, 150, subQuote2); + else + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 150, subQuote2); + + _scene->_sequences.addTimer(170, 50); + } else { + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 1, 120, curQuote); + _scene->_sequences.addTimer(140, 50); + } + } else if (_game._trigger == 50) { + if (_hermitDialogNode == 1) + handleSubDialog1(); + else if (_hermitDialogNode == 2) + handleSubDialog2(); + } +} + +void Scene611::displayHermitQuestions(int question) { + _scene->_kernelMessages.reset(); + _hermitDisplayedQuestion = question; + + switch (question) { + case 1: { + Common::String curQuote = _game.getQuote(0x281); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x282); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 2: { + Common::String curQuote = _game.getQuote(0x283); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x284); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 3: { + Common::String curQuote = _game.getQuote(0x285); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 4: { + Common::String curQuote = _game.getQuote(0x286); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 5: { + Common::String curQuote = _game.getQuote(0x297); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y - 14), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x298); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x299); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 6: { + Common::String curQuote = _game.getQuote(0x29A); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x29B); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 7: { + Common::String curQuote = _game.getQuote(0x2A0); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 8: { + Common::String curQuote = _game.getQuote(0x2A2); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 9: { + Common::String curQuote = _game.getQuote(0x2A5); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 10: { + Common::String curQuote = _game.getQuote(0x2A8); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2A9); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 11: { + Common::String curQuote = _game.getQuote(0x2AB); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2AE); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 12: { + Common::String curQuote = _game.getQuote(0x2AF); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 13: { + Common::String curQuote = _game.getQuote(0x2B3); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2B6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B7)); + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 73), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B8)); + _scene->_kernelMessages.add(Common::Point(11, _defaultDialogPos.y + 87), 0xFDFC, 0, 0, 9999999, _game.getQuote(0x2B9)); + } + break; + + case 14: { + Common::String curQuote = _game.getQuote(0x2BA); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BB); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 15: { + Common::String curQuote = _game.getQuote(0x2BE); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2BF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C1); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 16: { + Common::String curQuote = _game.getQuote(0x2C2); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 17: { + Common::String curQuote = _game.getQuote(0x2C7); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C8); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2C0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 18: { + Common::String curQuote = _game.getQuote(0x2CB); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CC); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 19: { + Common::String curQuote = _game.getQuote(0x2CE); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2CF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 20: { + Common::String curQuote = _game.getQuote(0x2E1); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E2); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E3); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2E5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 21: { + Common::String curQuote = _game.getQuote(0x2D3); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D4); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D5); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D6); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 9999999, curQuote); + + curQuote = _game.getQuote(0x2D7); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 9999999, curQuote); + } + break; + + case 22: { + Common::String curQuote = _game.getQuote(0x2D8); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2D9); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DA); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DB); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote); + } + break; + + case 23: { + Common::String curQuote = _game.getQuote(0x2DC); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 3), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DD); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 17), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DE); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 31), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2DF); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 45), 0xFDFC, 0, 0, 700, curQuote); + + curQuote = _game.getQuote(0x2E0); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 59), 0xFDFC, 0, 0, 700, curQuote); + } + break; + + default: + break; + } +} + +void Scene611::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_9"); + + _game.loadQuoteSet(0x279, 0x27A, 0x27B, 0x27C, 0x27D, 0x27E, 0x27F, 0x280, 0x281, 0x282, 0x283, 0x284, + 0x285, 0x286, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, 0x291, 0x292, + 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299, 0x29A, 0x29B, 0x29C, 0x29D, 0x29E, 0x29F, 0x2A0, + 0x2A1, 0x2A2, 0x2A3, 0x2A4, 0x2A5, 0x2A6, 0x2A7, 0x2A8, 0x2A9, 0x2AA, 0x2AB, 0x2AC, 0x2AD, 0x2AE, + 0x2AF, 0x2B0, 0x2B1, 0x2B2, 0x2B3, 0x2B4, 0x2B5, 0x2B6, 0x2B7, 0x2B8, 0x2B9, 0x2BA, 0x2BB, 0x2BC, + 0x2BD, 0x2BE, 0x2BF, 0x2C0, 0x2C1, 0x2C2, 0x2C3, 0x2C4, 0x2C5, 0x2C6, 0x2C7, 0x2C8, 0x2C9, 0x2CA, + 0x2CB, 0x2CC, 0x2CD, 0x2CE, 0x2CF, 0x2D0, 0x2D1, 0x2D2, 0x2D3, 0x2D4, 0x2D5, 0x2D6, 0x2D7, 0x2D8, + 0x2D9, 0x2DA, 0x2DB, 0x2DC, 0x2DD, 0x2DE, 0x2DF, 0x2E0, 0x2E1, 0x2E2, 0x2E3, 0x2E4, 0x2E5, 0x2E6, + 0x323, 0x324, 0); + + _dialog1.setup(0x82, 0x287, 0x288, 0x289, 0x28A, 0x28B, 0x28C, 0x28D, 0x28E, 0x28F, 0x290, + 0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0); + + _dialog2.setup(0x83, 0x29C, 0x29D, 0x29E, 0x29F, 0); + + if (!_game._visitedScenes._sceneRevisited) { + _dialog1.set(0x82, 0x287, 0x288, 0x296, 0); + _dialog2.set(0x83, 0x29F, 0); + } + + _vm->_palette->setEntry(252, 51, 51, 47); + _vm->_palette->setEntry(253, 37, 37, 37); + + _ratPresentFl = false; + _seenRatFl = true; + _eyesRunningFl = false; + _shouldRemoveEyes = false; + _randVal = 0; + _defaultDialogPos = Common::Point(264, 43); + _giveBatteriesFl = false; + _resetBatterieText = false; + _alreadyTalkingFl = false; + _startTradingFl = false; + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(22, 132); + _game._player._facing = FACING_EAST; + _duringDialogFl = false; + } + + if (!_globals[kHasTalkedToHermit]) { + _scene->loadAnimation(Resources::formatName(611, 'h', -1, EXT_AA, ""), 0); + _scene->loadAnimation(Resources::formatName(203, 'a', -1, EXT_AA, ""), 81); + _nextFrame = 47; + _hermitMode = 1; + _hermitTalkingFl = false; + _hermitMovingFl = true; + _check1Fl = true; + _stickFingerFl = false; + } else { + _hermitMode = 0; + _scene->_hotspots.activate(NOUN_HERMIT, false); + } + + // CHECKME: The last line of the block looks extremely useless + if (_globals[kExecuted_1_11]) { + _dialog1.write(0x294, true); + _dialog1.write(0x292, false); + _globals[kExecuted_1_11] = true; + } + + if (_duringDialogFl) { + _game._player._playerPos = Common::Point(237, 129); + _game._player._facing = FACING_NORTHEAST; + + switch (_hermitDialogNode) { + case 0: + _scene->_userInterface.setup(kInputBuildingSentences); + _hermitDialogNode = 1; + break; + + case 1: + _dialog1.start(); + break; + + case 2: + _dialog2.start(); + break; + + default: + break; + } + displayHermitQuestions(_hermitDisplayedQuestion); + } + + sceneEntrySound(); +} + +void Scene611::step() { + if (_seenRatFl && (_vm->getRandomNumber(1, 100) == 10)) { + _seenRatFl = false; + _scene->_sequences.addTimer(1, 80); + } + + if (_game._trigger == 80) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _ratPresentFl = true; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + } else if (_game._trigger == 81) { + int syncId = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 20, 0, 0, 0); + int idx = _scene->_dynamicHotspots.add(NOUN_RAT, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _ratHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(272, 154), FACING_SOUTHEAST); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 9, 10); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncId); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + _ratTimer = _game._player._priorTimer; + } + + if (_ratPresentFl && ((_game._player._priorTimer - _ratTimer) > 1200)) + handleRatMoves(); + + if (!_eyesRunningFl) { + _randVal = _vm->getRandomNumber(1, 30); + _eyesRunningFl = true; + _scene->_sequences.addTimer(1, 70); + } + + if (_game._trigger == 70) { + switch (_randVal) { + case 2: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 6: + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 12, 3, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 2, 4); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 7: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 9: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 13: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 14: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 15: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 24, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 5, 8); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 17: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 9, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 21: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 9); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 25: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 10); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 27: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 11); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _shouldRemoveEyes = true; + _scene->_sequences.addTimer(60, 71); + break; + + case 29: + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 20, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + default: + _scene->_sequences.addTimer(1, 71); + break; + } + } + + if (_game._trigger == 71) { + if (_shouldRemoveEyes) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _shouldRemoveEyes = false; + } + _eyesRunningFl = false; + _randVal = 0; + } + + if (_game._trigger == 100) { + if (_alreadyTalkingFl) + _alreadyTalkingFl = false; + else + _hermitMovingFl = true; + } + + if (_stickFingerFl && (_scene->_activeAnimation->getCurrentFrame() == 47)) { + _stickFingerFl = false; + _hermitMovingFl = true; + _hermitMode = 1; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 240) && _check1Fl) { + _check1Fl = false; + _scene->_kernelMessages.add(Common::Point(33, 88), 0xFDFC, 0, 0, 90, _game.getQuote(0x27E)); + _scene->_sequences.addTimer(120, 120); + } + + if (_game._trigger == 120) { + int msgIdx = _scene->_kernelMessages.add(Common::Point(28, 102), 0xFDFC, 0, 0, 90, _game.getQuote(0x27F)); + _scene->_kernelMessages.setQuoted(msgIdx, 4, true); + _scene->_sequences.addTimer(100, 121); + } + + if (_game._trigger == 121) { + int msgIdx = _scene->_kernelMessages.add(Common::Point(23, 116), 0xFDFC, 0, 0, 90, _game.getQuote(0x280)); + _scene->_kernelMessages.setQuoted(msgIdx, 4, true); + } + + if (_hermitMode == 1) { + if (_startTradingFl) { + _hermitMode = 6; + _hermitMovingFl = false; + _hermitTalkingFl = false; + _scene->_sequences.addTimer(1, 110); + } else if (_hermitTalkingFl) { + _hermitMode = 2; + _nextFrame = 18; + _hermitMovingFl = false; + } else { + switch (_vm->getRandomNumber(1, 5)) { + case 1: + _nextFrame = 46; + break; + + case 2: + _nextFrame = 47; + break; + + case 3: + _nextFrame = 48; + break; + + case 4: + _nextFrame = 49; + break; + + case 5: + _nextFrame = 50; + break; + + default: + break; + } + } + } + + if (_hermitMode == 2) { + if (_startTradingFl) { + _hermitMode = 6; + _hermitMovingFl = false; + _hermitTalkingFl = false; + _scene->_sequences.addTimer(1, 110); + } else if (_hermitMovingFl) { + _hermitMode = 1; + _nextFrame = 47; + _hermitTalkingFl = false; + } else { + switch (_vm->getRandomNumber(1, 4)) { + case 1: + _nextFrame = 18; + break; + + case 2: + _nextFrame = 20; + break; + + case 3: + _nextFrame = 22; + break; + + case 4: + _nextFrame = 24; + break; + + default: + break; + } + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 254) + _game._player._stepEnabled = true; + + if (_game._trigger == 110) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 111); + } + + if (_game._trigger == 111) { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _nextFrame = 1; + } + + if (_game._trigger == 112) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + } + + if (_hermitMode == 6) { + if ((_scene->_activeAnimation->getCurrentFrame() == 9) && _check1Fl) { + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 112); + _check1Fl = false; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 17) && !_check1Fl) { + _nextFrame = 26; + _hermitMode = 4; + _check1Fl = true; + } + } + + if (_hermitMode == 4) { + if ((_scene->_activeAnimation->getCurrentFrame() == 33) && _check1Fl) { + displayHermitQuestions(_hermitDisplayedQuestion); + _nextFrame = 1; + _check1Fl = false; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 9) && !_check1Fl) { + _nextFrame = 8; + _scene->_sequences.addTimer(1, 113); + _check1Fl = true; + } + } + + if (_game._trigger == 113) { + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 114); + } + + if (_game._trigger == 114) { + _resetBatterieText = true; + int syncIdx = _globals._sequenceIndexes[3]; + _nextFrame = 10; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 115); + } + + if ((_nextFrame >= 0) && (_nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(_nextFrame); + _nextFrame = -1; + } + + if (_game._trigger == 115) { + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player._visible = true; + if (_hermitDisplayedQuestion == 21) { + _game._player._stepEnabled = false; + handleTrading(); + _hermitMode = 0; + _startTradingFl = false; + _nextFrame = 52; + _globals[kHasTalkedToHermit] = true; + _scene->_hotspots.activate(NOUN_HERMIT, false); + } else { + _game._player._stepEnabled = true; + _hermitMode = 1; + _nextFrame = 47; + _hermitTalkingFl = false; + _startTradingFl = false; + _check1Fl = true; + } + } +} + +void Scene611::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_ALLEY)) + _game._player._walkOffScreenSceneId = 609; + + if (_resetBatterieText) + _scene->_kernelMessages.reset(); +} + +void Scene611::actions() { + if (_game._screenObjects._inputMode == 1) + handleDialog(); + else if ((_action.isAction(VERB_GIVE, NOUN_PHONE_CELLS, NOUN_HERMIT)) || (_action.isAction(VERB_GIVE, NOUN_DURAFAIL_CELLS, NOUN_HERMIT))) { + _action._activeAction._verbId = 0x294; + _giveBatteriesFl = true; + handleSubDialog1(); + } else if (_action.isAction(VERB_GIVE, NOUN_HERMIT)) { + _scene->_kernelMessages.reset(); + + Common::String curQuote = _game.getQuote(0x323); + int width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + int quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y), 0xFDFC, 0, 0, 120, curQuote); + + curQuote = _game.getQuote(0x324); + width = _vm->_font->getWidth(curQuote, _scene->_textSpacing); + quotePosX = _defaultDialogPos.x - (width / 2); + _scene->_kernelMessages.add(Common::Point(quotePosX, _defaultDialogPos.y + 14), 0xFDFC, 0, 0, 120, curQuote); + } else if (_game._trigger == 90) { + if (_dialog2.read(0x29C) && _dialog2.read(0x29D) && _dialog2.read(0x29E)) { + handleTalking(180); + if (_vm->getRandomNumber(1, 2) == 1) + displayHermitQuestions(1); + else + displayHermitQuestions(2); + } else { + handleTalking(180); + if (_vm->getRandomNumber(1, 2) == 1) + displayHermitQuestions(3); + else + displayHermitQuestions(4); + } + + _duringDialogFl = true; + if (_dialog2.read(0x29F)) { + _hermitDialogNode = 1; + _dialog1.start(); + _duringDialogFl = true; + } else { + _hermitDialogNode = 2; + _dialog2.write(0x29F, true); + _dialog2.start(); + _duringDialogFl = true; + } + } else if (_action.isAction(VERB_TALKTO, NOUN_HERMIT)) { + if (!_dialog1.read(0x287)) { + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x27A)); + _scene->_sequences.addTimer(120, 90); + } else { + int nextQuote = 0; + switch (_vm->getRandomNumber(1, 3)) { + case 1: + nextQuote = 0x27B; + break; + + case 2: + nextQuote = 0x27C; + break; + + case 3: + nextQuote = 0x27D; + break; + } + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(nextQuote)); + _scene->_sequences.addTimer(120, 90); + } + } else if ((_action.isAction(VERB_WALKTO) || _action.isAction(VERB_LOOK)) && _action.isObject(NOUN_RAT)) { + switch (_game._trigger) { + case 0: + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x279)); + _scene->_sequences.addTimer(60, 1); + break; + + case 1: + handleRatMoves(); + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_globals[kHasTalkedToHermit]) + _vm->_dialogs->show(61111); + else + _vm->_dialogs->show(61110); + } else if (_action.isAction(VERB_LOOK, NOUN_HERMIT)) + _vm->_dialogs->show(61112); + else if (_action.isAction(VERB_LOOK, NOUN_TRASH)) + _vm->_dialogs->show(61113); + else if (_action.isAction(VERB_TAKE, NOUN_TRASH)) + _vm->_dialogs->show(61114); + else if (_action.isAction(VERB_LOOK, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61115); + else if (_action.isAction(VERB_TAKE, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61116); + else if (_action.isAction(VERB_OPEN, NOUN_CARDBOARD_BOX)) + _vm->_dialogs->show(61117); + else if (_action.isAction(VERB_LOOK, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61118); + else if (_action.isAction(VERB_OPEN, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61119); + else if (_action.isAction(VERB_TAKE, NOUN_REFRIGERATOR)) + _vm->_dialogs->show(61120); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(61121); + else if (_action.isAction(VERB_LOOK, NOUN_GRAFFITI)) + _vm->_dialogs->show(61122); + else if (_action.isAction(VERB_LOOK, NOUN_METAL_PIPE)) + _vm->_dialogs->show(61123); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene612::Scene612(MADSEngine *vm) : Scene6xx(vm) { + _actionMode = -1; + _cycleIndex = -1; +} + +void Scene612::synchronize(Common::Serializer &s) { + Scene6xx::synchronize(s); + + s.syncAsSint16LE(_actionMode); + s.syncAsSint16LE(_cycleIndex); +} + +void Scene612::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene612::handleWinchMovement() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 10, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 5); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[4]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_SPRITE, 5, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + // CHECKME: Is the "else" block useful as action is always equal to 1 at this point? + // Or is it a missing bit of code we could fix? + if (_actionMode == 1) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 17, 7, 0, 0); + _vm->_sound->command(19); + _game._objects.setRoom(OBJ_PADLOCK_KEY, 1); + _globals[kBoatRaised] = false; + } else { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 17, 9, 0, 0); + _vm->_sound->command(18); + } + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x2F4)); + _game._player._stepEnabled = true; + + _vm->_dialogs->show(61217); + } + break; + + default: + break; + } +} + +void Scene612::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('c', -1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('p', -1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXCD_3"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RXRC_6"); + + if ((_globals[kLineStatus] == 2) || (_globals[kLineStatus] == 3)) { + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('f', -1)); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(34, 117), FACING_SOUTHEAST); + } + + if (_globals[kBoatRaised]) + _cycleIndex = -2; + else + _cycleIndex = -1; + + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, _cycleIndex); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 1); + + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(280, 75); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3); + _scene->loadAnimation(formAnimName('R', 1), 70); + } + + sceneEntrySound(); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_PADLOCK_KEY); + + _game.loadQuoteSet(0x2F5, 0x2F4, 0); +} + +void Scene612::step() { + switch (_game._trigger) { + case 70: + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _scene->_sequences.addTimer(6, 71); + break; + + case 71: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 72); + break; + + case 72: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene612::actions() { + if (_action.isAction(VERB_GET_INSIDE, NOUN_CAR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 3); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[1], syncIdx); + _scene->_sequences.addTimer(6, 2); + } + break; + + case 2: + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], true, 10, 1, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], true, -2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 504; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_UNLOCK, NOUN_PADLOCK_KEY, NOUN_CONTROL_BOX)) { + _cycleIndex = -2; + _actionMode = 1; + handleWinchMovement(); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_EXPRESSWAY)) + _vm->_dialogs->show(61210); + else if (_action.isAction(VERB_LOOK, NOUN_ROPE) || _action.isAction(VERB_LOOK, NOUN_ARMATURE)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(61211); + else + _vm->_dialogs->show(61212); + } else if (_action.isAction(VERB_TAKE, NOUN_ROPE)) + _vm->_dialogs->show(61213); + else if (_action.isAction(VERB_LOOK, NOUN_CONTROL_BOX)) { + if (_globals[kBoatRaised]) + _vm->_dialogs->show(61214); + else + _vm->_dialogs->show(61216); + } else if (_action.isAction(VERB_OPEN, NOUN_CONTROL_BOX)) + _vm->_dialogs->show(61215); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDINGS)) + _vm->_dialogs->show(61218); + else if (_action.isAction(VERB_LOOK, NOUN_DOME)) + _vm->_dialogs->show(61219); + else if (_action.isAction(VERB_LOOK, NOUN_STATUE)) + _vm->_dialogs->show(61220); + else if (_action.isAction(VERB_LOOK, NOUN_MAINTENANCE_BUILDING)) + _vm->_dialogs->show(61221); + else if (_action.isAction(VERB_OPEN, NOUN_MAINTENANCE_BUILDING)) + _vm->_dialogs->show(61222); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(61223); + else if (_action.isAction(VERB_LOOK, NOUN_SUPPORT)) + _vm->_dialogs->show(61224); + else if (_action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_EAST) || _action.isAction(VERB_WALK_DOWN, NOUN_EXPRESSWAY_TO_WEST)) + _vm->_dialogs->show(61225); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene620::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene620::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_sequences.addTimer(30, 70); + _scene->_userInterface.setup(kInputLimitedSentences); + sceneEntrySound(); +} + +void Scene620::step() { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->loadAnimation(formAnimName('E', -1), 71); + break; + + case 71: + if (_scene->_priorSceneId == 751) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = 701; + } else if (_scene->_priorSceneId == 752) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = 702; + } else if (_scene->_priorSceneId < 501 || _scene->_priorSceneId > 752) { + _globals[kCityFlooded] = true; + _globals[kTeleporterRoom + 5] = 0; + _scene->_nextSceneId = _scene->_priorSceneId; + } else if (_scene->_priorSceneId >= 501 && _scene->_priorSceneId <= 612) { + _globals[kResurrectRoom] = _globals[kHoverCarLocation]; + _game._objects.addToInventory(OBJ_TIMEBOMB); + _globals[kTimebombStatus] = 0; + _globals[kTimebombTimer] = 0; + _scene->_nextSceneId = 605; + } + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes6.h b/engines/mads/nebular/nebular_scenes6.h new file mode 100644 index 0000000000..c5cac56626 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes6.h @@ -0,0 +1,322 @@ +/* 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 MADS_NEBULAR_SCENES6_H +#define MADS_NEBULAR_SCENES6_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene6xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene6xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene601 : public Scene6xx{ +public: + Scene601(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene602 : public Scene6xx{ +private: + int _lastSpriteIdx; + int _lastSequenceIdx; + int _cycleIndex; + int _safeMode; + + void handleSafeActions(); + +public: + Scene602(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene603 : public Scene6xx{ +private: + int _compactCaseHotspotId; + int _noteHotspotId; + +public: + Scene603(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene604 : public Scene6xx{ +private: + int _timebombHotspotId; + int _bombMode; + int _monsterFrame; + + uint32 _monsterTimer; + + bool _monsterActive; + bool _animationActiveFl; + + void handleBombActions(); + +public: + Scene604(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene605 : public Scene6xx{ +public: + Scene605(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene607 : public Scene6xx{ +private: + uint32 _dogTimer; + uint32 _lastFrameTime; + + bool _dogLoop; + bool _dogEatsRex; + bool _dogBarking; + bool _shopAvailable; + + int _animationMode; + int _animationActive; + int _counter; + + void handleThrowingBone(); + +public: + Scene607(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene608 : public Scene6xx{ +private: + int _carMode; + int _carFrame; + int _carMoveMode; + int _dogDeathMode; + int _carHotspotId; + int _barkCount; + int _polycementHotspotId; + int _animationMode; + int _nextTrigger; + int _throwMode; + + bool _resetPositionsFl; + bool _dogActiveFl; + bool _dogBarkingFl; + bool _dogFirstEncounter; + bool _rexBeingEaten; + bool _dogHitWindow; + bool _checkFl; + bool _dogSquashFl; + bool _dogSafeFl; + bool _buttonPressedonTimeFl; + bool _dogUnderCar; + bool _dogYelping; + + long _dogWindowTimer; + long _dogRunTimer; + + uint32 _dogTimer1; + uint32 _dogTimer2; + + void resetDogVariables(); + void restoreAnimations(); + void setCarAnimations(); + void handleThrowingBone(); + +public: + Scene608(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene609 : public Scene6xx{ +private: + int _videoDoorMode; + + void enterStore(); + +public: + Scene609(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene610 : public Scene6xx{ +private: + int _handsetHotspotId; + int _checkVal; + + bool _cellCharging; + + long _cellChargingTimer; + uint32 _lastFrameTimer; + +public: + Scene610(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene611 : public Scene6xx{ +private: + bool _seenRatFl; + bool _eyesRunningFl; + bool _shouldRemoveEyes; + bool _ratPresentFl; + bool _duringDialogFl; + bool _resetBatterieText; + bool _hermitTalkingFl; + bool _hermitMovingFl; + bool _alreadyTalkingFl; + bool _giveBatteriesFl; + bool _startTradingFl; + bool _check1Fl; + bool _stickFingerFl; + + int _randVal; + int _ratHotspotId; + int _hermitDialogNode; + int _hermitDisplayedQuestion; + int _nextFrame; + int _hermitMode; + + uint32 _ratTimer; + + Conversation _dialog1; + Conversation _dialog2; + + Common::Point _defaultDialogPos; + + void handleTrading(); + void handleRatMoves(); + void handleDialog(); + void handleSubDialog1(); + void handleSubDialog2(); + void handleTalking(int delay); + void setDialogNode(int node); + void displayHermitQuestions(int question); + + bool check2ChargedBatteries(); + bool check4ChargedBatteries(); + +public: + Scene611(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene612 : public Scene6xx{ +private: + int _actionMode; + int _cycleIndex; + + void handleWinchMovement(); + +public: + Scene612(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene620 : public Scene6xx{ +public: + Scene620(MADSEngine *vm) : Scene6xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES6_H */ diff --git a/engines/mads/nebular/nebular_scenes7.cpp b/engines/mads/nebular/nebular_scenes7.cpp new file mode 100644 index 0000000000..d59f7ff5f3 --- /dev/null +++ b/engines/mads/nebular/nebular_scenes7.cpp @@ -0,0 +1,2678 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes7.h" + +namespace MADS { + +namespace Nebular { + +void Scene7xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene7xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + + Common::String oldName = _game._player._spritesPrefix; + + if ((_scene->_nextSceneId == 703) || (_scene->_nextSceneId == 704) || (_scene->_nextSceneId == 705) + || (_scene->_nextSceneId == 707) || (_scene->_nextSceneId == 710) || (_scene->_nextSceneId == 711)) + _game._player._spritesPrefix = ""; + else if (_globals[kSexOfRex] == REX_MALE) + _game._player._spritesPrefix = "RXM"; + else + _game._player._spritesPrefix = "ROX"; + + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); +} + +void Scene7xx::sceneEntrySound() { + if (!_vm->_musicFlag) { + _vm->_sound->command(2); + return; + } + + switch (_scene->_nextSceneId) { + case 701: + case 702: + case 704: + case 705: + case 751: + _vm->_sound->command(38); + break; + case 703: + if (_globals[kMonsterAlive] == 0) + _vm->_sound->command(24); + else + _vm->_sound->command(27); + break; + case 706: + case 707: + case 710: + case 711: + _vm->_sound->command(25); + break; + default: + break; + } +} + +/*------------------------------------------------------------------------*/ + +Scene701::Scene701(MADSEngine *vm) : Scene7xx(vm) { + _fishingLineId = -1; +} + +void Scene701::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_fishingLineId); +} + +void Scene701::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_BOAT); + _scene->addActiveVocab(VERB_CLIMB_INTO); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene701::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 5)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RM202A1"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('b', 8)); + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_BINOCULARS); + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _game._objects.addToInventory(OBJ_BOMB); + _game._objects.addToInventory(OBJ_CHICKEN); + _game._objects.addToInventory(OBJ_BONES); + + _globals[kCityFlooded] = true; + _globals[kLineStatus] = LINE_TIED; + _globals[kBoatRaised] = false; + } + + if (_globals[kBoatStatus] == BOAT_UNFLOODED) { + if (_globals[kBoatRaised]) + _globals[kBoatStatus] = BOAT_GONE; + else if (_globals[kLineStatus] == LINE_TIED) + _globals[kBoatStatus] = BOAT_TIED_FLOATING; + else if (_game._difficulty == DIFFICULTY_HARD) + _globals[kBoatStatus] = BOAT_ADRIFT; + else + _globals[kBoatStatus] = BOAT_TIED; + } + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + + int boatStatus = (_scene->_priorSceneId == 703) ? BOAT_GONE : _globals[kBoatStatus]; + + switch (boatStatus) { + case BOAT_TIED_FLOATING: + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 20, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 10); + break; + case BOAT_ADRIFT: + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 20, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 10); + break; + case BOAT_TIED: + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + break; + case BOAT_GONE: + _scene->_hotspots.activate(NOUN_BOAT, false); + break; + default: + break; + } + + if (_globals[kLineStatus] == LINE_DROPPED || _globals[kLineStatus] == LINE_TIED) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _fishingLineId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTHEAST); + } + + if (_scene->_priorSceneId == 702) { + _game._player._playerPos = Common::Point(309, 138); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 710) { + _game._player._playerPos = Common::Point(154, 129); + _game._player._facing = FACING_NORTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addTimer(15, 60); + } else if (_scene->_priorSceneId == 703) { + _game._player._playerPos = Common::Point(231, 127); + _game._player._facing = FACING_SOUTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(formAnimName('B', 1), 80); + _vm->_sound->command(28); + } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + _game._player._playerPos = Common::Point(22, 131); + _game._player._facing = FACING_EAST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(60, 70); + } + + _game.loadQuoteSet(0x310, 0x30F, 0); + sceneEntrySound(); +} + +void Scene701::step() { + switch(_game._trigger) { + case 60: + _scene->_sequences.remove(_globals._sequenceIndexes[5]); + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[5]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + case 70: + _vm->_sound->command(16); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _game._player.walk(Common::Point(61, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 72); + break; + + case 72: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 73); + break; + + case 73: + _game._player._stepEnabled = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + break; + + case 80: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 129), FACING_NORTH); + _globals[kBoatStatus] = BOAT_TIED; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } +} + +void Scene701::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 702; + + if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST); + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTH); +} + +void Scene701::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + return; + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_BUILDING) && _game._objects[OBJ_VASE]._roomNumber == 706) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int temp = _globals._sequenceIndexes[5]; + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[5], Common::Point(155, 129)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[5], temp); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _scene->_nextSceneId = 710; + break; + + default: + break; + } + } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(16); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x310, 34, 0, 120, _game.getQuote(0x30D)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player.walk(Common::Point(22, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _globals[kResurrectRoom] = 701; + _scene->_nextSceneId = 605; + break; + + default: + break; + } + } else if ((_action.isAction(VERB_PULL, NOUN_BOAT) || _action.isAction(VERB_TAKE, NOUN_BOAT) || + _action.isAction(VERB_PULL, NOUN_FISHING_LINE) || _action.isAction(VERB_TAKE, NOUN_FISHING_LINE)) && + !_game._objects.isInInventory(OBJ_FISHING_LINE)) { + if (_globals[kBoatStatus] == BOAT_TIED_FLOATING) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _scene->_dynamicHotspots.remove(_fishingLineId); + _scene->_hotspots.activate(NOUN_BOAT, false); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('E', -1), 1); + break; + + case 1: { + _game._player._visible = true; + _game._player._priorTimer = _scene->_activeAnimation->getNextFrameTimer() - _game._player._ticksAmount; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -1); + _scene->_sequences.setDepth (_globals._sequenceIndexes[2], 9); + int idx = _scene->_dynamicHotspots.add(NOUN_BOAT, VERB_CLIMB_INTO, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(231, 127), FACING_NORTH); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _globals[kBoatStatus] = BOAT_TIED; + _globals[kLineStatus] = LINE_NOW_UNTIED; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_globals[kBoatStatus] == BOAT_TIED) { + _vm->_dialogs->show(70125); + } else if (_globals[kLineStatus] == LINE_DROPPED) { + _globals[kLineStatus] = LINE_NOW_UNTIED; + _game._objects.addToInventory(OBJ_FISHING_LINE); + _vm->_sound->command(15); + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _vm->_dialogs->showItem(OBJ_FISHING_LINE, 70126); + } else { + _vm->_dialogs->show(70127); + } + } else if (_action.isAction(VERB_CLIMB_INTO, NOUN_BOAT) && _globals[kBoatStatus] == BOAT_TIED) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._player._visible = false; + _scene->loadAnimation(formAnimName('B', 0), 1); + break; + + case 1: + _scene->_nextSceneId = 703; + break; + + default: + break; + } + } else if (_action._lookFlag) { + if (_globals[kBoatStatus] != BOAT_GONE) { + if (_globals[kBoatStatus] == BOAT_TIED) + _vm->_dialogs->show(70128); + else + _vm->_dialogs->show(70110); + } else + _vm->_dialogs->show(70111); + } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY)) + _vm->_dialogs->show(70112); + else if (_action.isAction(VERB_LOOK, 0)) + _vm->_dialogs->show(70113); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(70114); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(70115); + else if (_action.isAction(VERB_LOOK, NOUN_HOOK)) { + if (_globals[kLineStatus] == LINE_NOT_DROPPED || _globals[kLineStatus] == LINE_NOW_UNTIED) + _vm->_dialogs->show(70116); + else + _vm->_dialogs->show(70117); + } else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(70118); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(70119); + else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM)) + _vm->_dialogs->show(70120); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(70121); + else if (_action.isAction(VERB_LOOK, NOUN_BOAT)) { + if (_globals[kBoatStatus] == BOAT_ADRIFT || _globals[kBoatStatus] == BOAT_TIED_FLOATING) + _vm->_dialogs->show(70122); + else + _vm->_dialogs->show(70123); + } else if (_action.isAction(VERB_CAST, NOUN_FISHING_ROD, NOUN_BOAT) && _game._objects.isInInventory(OBJ_FISHING_LINE)) + _vm->_dialogs->show(70124); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene702::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene702::enter() { + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8"); + + if (_scene->_priorSceneId == 701) { + _game._player._playerPos = Common::Point(13, 145); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2 && _scene->_priorSceneId != 620) { + _game._player._playerPos = Common::Point(289, 138); + _game._player.walk(Common::Point(262, 148), FACING_WEST); + _game._player._facing = FACING_WEST; + _game._player._visible = true; + } + + if (_game._globals[kTeleporterCommand]) { + switch(_game._globals[kTeleporterCommand]) { + case TELEPORTER_BEAM_OUT: + case TELEPORTER_WRONG: + case TELEPORTER_STEP_OUT: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + + _game._globals[kTeleporterCommand] = TELEPORTER_NONE; + } + + sceneEntrySound(); +} + +void Scene702::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 701; +} + +void Scene702::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; // Only set the action as finished + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 711; + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->show(OBJ_BONES, 70218); + break; + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action._lookFlag) + _vm->_dialogs->show(70210); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(70211); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK)) + _vm->_dialogs->show(70212); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(70213); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(70214); + else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM)) + _vm->_dialogs->show(70215); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(70216); + else if (_action.isAction(VERB_LOOK, NOUN_BONES) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70217); + else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) { + if (_game._objects.isInInventory(OBJ_BONES)) + _vm->_dialogs->show(70219); + } else if (_action.isAction(VERB_LOOK, NOUN_SUBMERGED_CITY)) + _vm->_dialogs->show(70220); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene703::Scene703(MADSEngine *vm) : Scene7xx(vm) { + _monsterMode = -1; + _boatFrame = -1; + _curSequence = -1; + _boatDir = -1; + + _useBomb = false; + _startMonsterTimer = false; + _rexDeathFl = false; + _restartTrigger70Fl = false; + + _lastFrameTime = 0; + _monsterTime = 0; +} + +void Scene703::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_monsterMode); + s.syncAsSint16LE(_boatFrame); + s.syncAsSint16LE(_curSequence); + s.syncAsSint16LE(_boatDir); + + s.syncAsByte(_useBomb); + s.syncAsByte(_startMonsterTimer); + s.syncAsByte(_rexDeathFl); + s.syncAsByte(_restartTrigger70Fl); + + s.syncAsUint32LE(_lastFrameTime); + s.syncAsUint32LE(_monsterTime); +} + +void Scene703::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene703::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene703::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + if (_boatDir == 2) + _curSequence = 6; + else + _curSequence = 7; +} + +void Scene703::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene703::enter() { + _game._player._visible = false; + + if (!_game._visitedScenes._sceneRevisited) { + if (_scene->_priorSceneId == 704) + _globals[kMonsterAlive] = false; + else + _globals[kMonsterAlive] = true; + } + + _startMonsterTimer = true; + _rexDeathFl = true; + _monsterTime = 0; + _restartTrigger70Fl = true; + _useBomb = false; + _boatFrame = -1; + + if (!_globals[kMonsterAlive]) + _scene->_hotspots.activate(NOUN_SEA_MONSTER, false); + + if (_scene->_priorSceneId == 704) { + _game._player._stepEnabled = false; + _curSequence = 2; + _boatDir = 2; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(34); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _boatDir = 1; + if (_globals[kMonsterAlive]) { + _monsterMode = 1; + _curSequence = 0; + _scene->loadAnimation(formAnimName('B', -1)); + } else { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + } + } else if (_globals[kMonsterAlive]) { + _curSequence = 0; + _boatDir = 1; + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + } else if (_boatDir == 1) { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(9); + } else if (_boatDir == 2) { + _curSequence = 0; + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(56); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_TWINKIFRUIT); + _game._objects.addToInventory(OBJ_BOMB); + _game._objects.addToInventory(OBJ_CHICKEN); + _game._objects.addToInventory(OBJ_BONES); + } + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + sceneEntrySound(); + _vm->_sound->command(28); +} + +void Scene703::step() { + if (_startMonsterTimer) { + long diff = _scene->_frameStartTime - _lastFrameTime; + if ((diff >= 0) && (diff <= 12)) + _monsterTime += diff; + else + _monsterTime++; + + _lastFrameTime = _scene->_frameStartTime; + } + + if ((_monsterTime >= 2400) && !_rexDeathFl && !_useBomb) { + _startMonsterTimer = false; + _rexDeathFl = true; + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 3; + _scene->loadAnimation(formAnimName('D', -1)); + _rexDeathFl = false; + _monsterTime = 0; + } + + + if (_game._trigger == 70) + _scene->_reloadSceneFlag = true; + + if ((_monsterMode == 3) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + if (_boatFrame == 62) { + nextBoatFrame = 61; + if (_restartTrigger70Fl) { + _restartTrigger70Fl = false; + _scene->_sequences.addTimer(15, 70); + } + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if (_game._trigger == 70) + _scene->_reloadSceneFlag = true; + + if ((_monsterMode == 0) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 11: + if (_curSequence == 7) { + _curSequence = 0; + nextBoatFrame = 100; + } else if (_curSequence == 5) + nextBoatFrame = 82; + else if (_curSequence == 1) + nextBoatFrame = 11; + else { + nextBoatFrame = 9; + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + } + break; + + case 34: + if (_curSequence != 2) + _scene->_nextSceneId = 704; + break; + + case 57: + if (_curSequence == 6) { + _curSequence = 0; + nextBoatFrame = 91; + } else if (_curSequence == 4) + nextBoatFrame = 73; + else if (_curSequence == 3) + nextBoatFrame = 57; + else { + nextBoatFrame = 56; + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + } + break; + + case 73: + _scene->_nextSceneId = 701; + break; + + case 82: + nextBoatFrame = 11; + break; + + case 91: + nextBoatFrame = 57; + break; + + case 100: + nextBoatFrame = 56; + if (!_game._player._stepEnabled) { + _scene->_sequences.addTimer(30, 80); + _game._player._stepEnabled = true; + } + break; + + case 110: + nextBoatFrame = 9; + if (!_game._player._stepEnabled) { + _scene->_sequences.addTimer(30, 80); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if (_game._trigger == 80) { + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + } + + + if ((_monsterMode == 1) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 39: + _game._player._stepEnabled = true; + _startMonsterTimer = true; + _rexDeathFl = false; + break; + + case 40: + case 49: + case 54: + case 67: + case 78: + case 87: + case 96: + case 105: + case 114: + case 123: + if (_curSequence == 8) + nextBoatFrame = 129; + + break; + + case 129: + nextBoatFrame = 39; + break; + + case 151: + _scene->_nextSceneId = 701; + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } + + if ((_monsterMode == 2) && (_scene->_activeAnimation != nullptr)) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatFrame) { + _boatFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextBoatFrame = -1; + + switch (_boatFrame) { + case 14: + if (!_useBomb) { + if (_game._difficulty == DIFFICULTY_HARD) + _game._objects.setRoom(OBJ_CHICKEN, 1); + else + _vm->_dialogs->show(70319); + } + nextBoatFrame = 80; + break; + + case 33: + if (_game._objects.isInInventory(OBJ_BONES)) { + _game._objects.setRoom(OBJ_BONES, 1); + _game._objects.addToInventory(OBJ_BONE); + } else + _game._objects.setRoom(OBJ_BONE, 1); + + nextBoatFrame = 80; + break; + + case 53: + _game._objects.setRoom(OBJ_TWINKIFRUIT, 1); + nextBoatFrame = 80; + _curSequence = 9; + break; + + case 80: + if (_game._difficulty == DIFFICULTY_HARD) { + _game._objects.setRoom(OBJ_BOMB, 1); + _vm->_dialogs->show(70318); + } else + _vm->_dialogs->show(70317); + + _scene->freeAnimation(); + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + _game._player._stepEnabled = true; + break; + + case 91: + if (!_useBomb) { + _scene->freeAnimation(); + _monsterMode = 1; + _scene->loadAnimation(formAnimName('B', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + _game._player._stepEnabled = true; + } else + _game._objects.setRoom(OBJ_CHICKEN_BOMB, 1); + + break; + + case 126: + _scene->_hotspots.activate(NOUN_SEA_MONSTER, false); + _globals[kMonsterAlive] = false; + _scene->freeAnimation(); + _monsterMode = 0; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(9); + _game._player._stepEnabled = true; + if (_game._storyMode == STORYMODE_NAUGHTY) + _vm->_dialogs->show(70321); + else + _vm->_dialogs->show(70322); + + break; + + default: + break; + } + + if ((nextBoatFrame >= 0) && (nextBoatFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextBoatFrame); + _boatFrame = nextBoatFrame; + } + } + } +} + +void Scene703::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_DOCK_TO_SOUTH)) { + _game._player._stepEnabled = false; + if (_globals[kMonsterAlive]) + _curSequence = 8; + else if (_boatDir == 1) + _curSequence = 5; + else + _curSequence = 3; + } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) { + _game._player._stepEnabled = false; + if (_globals[kMonsterAlive]) { + _startMonsterTimer = false; + _rexDeathFl = true; + _monsterTime = 0; + _scene->freeAnimation(); + _monsterMode = 3; + _scene->loadAnimation(formAnimName('D', -1)); + } else if (_boatDir == 2) + _curSequence = 4; + else + _curSequence = 1; + } else if (_action.isAction(VERB_THROW, NOUN_BONE, NOUN_SEA_MONSTER) || _action.isAction(VERB_THROW, NOUN_BONES, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(19); + } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_action.isAction(VERB_THROW, NOUN_TWINKIFRUIT, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(39); + } else if (_action.isAction(VERB_THROW, NOUN_BOMB, NOUN_SEA_MONSTER)) { + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + _scene->_activeAnimation->setCurrentFrame(59); + } else if (_action.isAction(VERB_THROW, NOUN_CHICKEN_BOMB, NOUN_SEA_MONSTER)) { + _useBomb = true; + _game._player._stepEnabled = false; + _scene->freeAnimation(); + _monsterMode = 2; + _scene->loadAnimation(formAnimName('C', -1)); + } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) { + if (_globals[kBottleStatus] != 4) { + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_SEA_MONSTER)) { + if (_globals[kMonsterAlive]) + _vm->_dialogs->show(70310); + } else if (_action.isAction(VERB_LOOK, NOUN_WATER)) { + if (!_globals[kMonsterAlive]) + _vm->_dialogs->show(70311); + else + _vm->_dialogs->show(70312); + } else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) { + if (_globals[kMonsterAlive]) + _vm->_dialogs->show(70313); + else if (_game._visitedScenes.exists(710)) + _vm->_dialogs->show(70314); + else + _vm->_dialogs->show(70315); + } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70316); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene704::Scene704(MADSEngine *vm) : Scene7xx(vm) { + _bottleHotspotId = -1; + _boatCurrentFrame = -1; + _animationMode = -1; + _boatDirection = -1; + + _takeBottleFl = false; +} + +void Scene704::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_bottleHotspotId); + s.syncAsSint16LE(_boatCurrentFrame); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_boatDirection); + + s.syncAsByte(_takeBottleFl); +} + +void Scene704::setup() { + _game._player._spritesPrefix = ""; + setAAName(); + _scene->addActiveVocab(NOUN_BOTTLE); + _scene->addActiveVocab(VERB_LOOK_AT); +} + +void Scene704::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene704::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + if (_boatDirection == 2) + _animationMode = 6; + else + _animationMode = 7; +} + +void Scene704::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene704::enter() { + if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + if (_scene->_priorSceneId == 705) { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } else { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(190, 122)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + } + int idx = _scene->_dynamicHotspots.add(NOUN_BONES, VERB_LOOK_AT, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _bottleHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(-2, 0), FACING_NONE); + } + + _game._player._visible = false; + _takeBottleFl = false; + _boatCurrentFrame = -1; + + if (_scene->_priorSceneId == 705) { + _game._player._stepEnabled = false; + _animationMode = 2; + _boatDirection = 2; + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(36); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _boatDirection = 1; + _scene->loadAnimation(formAnimName('A', -1)); + } else if (_boatDirection == 1) { + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(8); + } else if (_boatDirection == 2) { + if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) { + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(123, 125)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } + _scene->loadAnimation(formAnimName('A', -1)); + _scene->_activeAnimation->setCurrentFrame(57); + } + + if (_scene->_roomChanged) + _globals[kMonsterAlive] = false; + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + + sceneEntrySound(); + _vm->_sound->command(28); +} + +void Scene704::step() { + if (_scene->_activeAnimation != nullptr) { + if (_scene->_activeAnimation->getCurrentFrame() != _boatCurrentFrame) { + _boatCurrentFrame = _scene->_activeAnimation->getCurrentFrame(); + int nextFrame = -1; + + switch (_boatCurrentFrame) { + case 10: + switch (_animationMode) { + case 1: + nextFrame = 10; + break; + case 5: + nextFrame = 74; + break; + case 7: + _animationMode = 0; + nextFrame = 92; + break; + default: + if (!_game._player._stepEnabled) + _game._player._stepEnabled = true; + + nextFrame = 8; + break; + } + break; + + case 36: + if (_animationMode != 2) + _scene->_nextSceneId = 705; + break; + + case 59: + switch (_animationMode) { + case 3: + nextFrame = 59; + break; + + case 4: + nextFrame = 65; + break; + + case 6: + _animationMode = 0; + nextFrame = 83; + break; + + default: + if (!_game._player._stepEnabled) { + _game._player._stepEnabled = true; + } + nextFrame = 57; + break; + } + break; + + case 65: + _scene->_nextSceneId = 703; + break; + + case 74: + nextFrame = 10; + break; + + case 83: + nextFrame = 59; + break; + + case 90: + if (_takeBottleFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_bottleHotspotId); + _game._objects.addToInventory(OBJ_BOTTLE); + _vm->_sound->command(15); + _vm->_dialogs->showItem(OBJ_BOTTLE, 70415); + } + break; + + case 92: + nextFrame = 57; + if (!_game._player._stepEnabled && !_takeBottleFl) { + _scene->_sequences.addTimer(30, 70); + _game._player._stepEnabled = true; + } + break; + + case 98: + if (_takeBottleFl) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_bottleHotspotId); + _game._objects.addToInventory(OBJ_BOTTLE); + _vm->_sound->command(15); + _vm->_dialogs->showItem(OBJ_BOTTLE, 70415); + } + break; + + case 101: + nextFrame = 8; + if (!_game._player._stepEnabled && !_takeBottleFl) { + _scene->_sequences.addTimer(30, 70); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + if ((nextFrame >= 0) && (nextFrame != _scene->_activeAnimation->getCurrentFrame())) { + _scene->_activeAnimation->setCurrentFrame(nextFrame); + _boatCurrentFrame = nextFrame; + } + } + } + + if (_game._trigger == 70) { + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + } +} + +void Scene704::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) { + _game._player._stepEnabled = false; + if (_boatDirection == 1) + _animationMode = 5; + else + _animationMode = 3; + } else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_BUILDING_TO_NORTH)) { + _game._player._stepEnabled = false; + if (_boatDirection == 2) + _animationMode = 4; + else + _animationMode = 1; + } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE)) { + if (!_game._objects.isInInventory(OBJ_BOTTLE)) { + _game._player._stepEnabled = false; + _takeBottleFl = true; + if (_boatDirection == 2) { + _animationMode = 6; + } else { + _animationMode = 7; + } + } + } else if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER)) { + if (_game._objects.isInInventory(OBJ_BOTTLE)) { + if (_globals[kBottleStatus] != 4) { + _takeBottleFl = false; + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER)) + _vm->_dialogs->show(70410); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_NORTH)) { + if (_game._visitedScenes.exists(710)) + _vm->_dialogs->show(70411); + else + _vm->_dialogs->show(70412); + } else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70413); + else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70414); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH)) + _vm->_dialogs->show(70416); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(70417); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene705::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene705::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); +} + +void Scene705::handleBottleInterface() { + switch (_globals[kBottleStatus]) { + case 0: + _dialog1.write(0x311, true); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 1: + _dialog1.write(0x311, false); + _dialog1.write(0x312, true); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 2: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, true); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + case 3: + _dialog1.write(0x311, false); + _dialog1.write(0x312, false); + _dialog1.write(0x313, false); + _dialog1.write(0x314, true); + _dialog1.write(0x315, true); + break; + + default: + break; + } +} + +void Scene705::setBottleSequence() { + _scene->_userInterface.setup(kInputBuildingSentences); + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->loadAnimation(formAnimName('F', -1), 90); +} + +void Scene705::handleFillBottle(int quote) { + switch (quote) { + case 0x311: + _globals[kBottleStatus] = 1; + setBottleSequence(); + break; + + case 0x312: + _globals[kBottleStatus] = 2; + setBottleSequence(); + break; + + case 0x313: + _globals[kBottleStatus] = 3; + setBottleSequence(); + break; + + case 0x314: + _globals[kBottleStatus] = 4; + setBottleSequence(); + break; + + case 0x315: + _scene->_userInterface.setup(kInputBuildingSentences); + break; + + default: + break; + } +} + +void Scene705::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 0)); + + _game._player._visible = false; + + if (_scene->_priorSceneId == 706) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + } else if (_scene->_priorSceneId != -2) { + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(1, 80); + _vm->_sound->command(28); + } else + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + + if (_scene->_roomChanged) + _game._objects.addToInventory(OBJ_BOTTLE); + + _game.loadQuoteSet(0x311, 0x312, 0x313, 0x314, 0x315, 0); + _dialog1.setup(0x98, 0x311, 0x312, 0x313, 0x314, 0x315, 0); + sceneEntrySound(); +} + +void Scene705::step() { + switch (_game._trigger) { + case 70: + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 9, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + switch (_game._trigger) { + case 80: + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 9, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: { + _vm->_sound->command(19); + int syncIdx = _globals._sequenceIndexes[1]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + + switch (_game._trigger) { + case 90: + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.addTimer(30, 91); + break; + + case 91: + switch (_globals[kBottleStatus]) { + case 0: + _vm->_dialogs->show(432); + break; + + case 1: + _vm->_dialogs->show(70324); + break; + + case 2: + _vm->_dialogs->show(70325); + break; + + case 3: + _vm->_dialogs->show(70326); + break; + + case 4: + _vm->_dialogs->show(70327); + break; + + default: + break; + } + _game._player._stepEnabled = true; + break; + + default: + break; + } +} + +void Scene705::actions() { + if (_game._screenObjects._inputMode == 1) + handleFillBottle(_action._activeAction._verbId); + else if (_action.isAction(VERB_STEER_TOWARDS, NOUN_OPEN_WATER_TO_SOUTH)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 6, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + _vm->_sound->command(18); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 2); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_nextSceneId = 704; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_CLIMB_THROUGH, NOUN_WINDOW)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[3]); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 16); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[3]; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 16); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[3], syncIdx); + _scene->_nextSceneId = 706; + _game._player._stepEnabled = true; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_FILL, NOUN_BOTTLE, NOUN_WATER) || _action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_WATER)) { + if (_globals[kBottleStatus] != 4) { + handleBottleInterface(); + _dialog1.start(); + } else + _vm->_dialogs->show(70323); + } if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_WATER)) + _vm->_dialogs->show(70511); + else if (_action.isAction(VERB_LOOK, NOUN_VOLCANO_RIM)) + _vm->_dialogs->show(70512); + else if (_action.isAction(VERB_LOOK, NOUN_OPEN_WATER_TO_SOUTH)) + _vm->_dialogs->show(70513); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(70514); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING)) + _vm->_dialogs->show(70515); + else if (_action.isAction(VERB_LOOK, NOUN_WINDOW)) + _vm->_dialogs->show(70516); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene706::Scene706(MADSEngine *vm) : Scene7xx(vm) { + _vaseHotspotId = -1; + _vaseMode = -1; + _animationMode = -1; + _animationFrame = -1; + + _emptyPedestral = false; +} + +void Scene706::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_vaseHotspotId); + s.syncAsSint16LE(_vaseMode); + s.syncAsSint16LE(_animationMode); + s.syncAsSint16LE(_animationFrame); + + s.syncAsByte(_emptyPedestral); +} + +void Scene706::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_BOTTLE); + _scene->addActiveVocab(NOUN_VASE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene706::handleRexDeath() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->loadAnimation(formAnimName('a', -1), 2); + break; + + case 2: + if (_animationMode == 1) + _vm->_dialogs->show(70625); + else if (_globals[kBottleStatus] < 2) + _vm->_dialogs->show(70628); + else + _vm->_dialogs->show(70629); + + _game._objects.setRoom(OBJ_VASE, _scene->_currentSceneId); + if (_animationMode == 2) + _game._objects.setRoom(OBJ_BOTTLE, 2); + + _animationMode = 0; + _scene->_reloadSceneFlag = true; + break; + + default: + break; + } +} + +void Scene706::handleTakeVase() { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[3], false, 4, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[3]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 7, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _vm->_sound->command(9); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _scene->_dynamicHotspots.remove(_vaseHotspotId); + _game._objects.addToInventory(OBJ_VASE); + if (_vaseMode == 1) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + _game._objects.setRoom(OBJ_BOTTLE, _scene->_currentSceneId); + } + break; + + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[3]); + _game._player._visible = true; + _vm->_dialogs->showItem(OBJ_VASE, 70630); + _game._player._stepEnabled = true; + break; + } +} + +void Scene706::enter() { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites("*RXMRC_3"); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('b', -1)); + + if (!_game._visitedScenes._sceneRevisited) + _emptyPedestral = false; + + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('v', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 4); + int idx = _scene->_dynamicHotspots.add(NOUN_VASE, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _vaseHotspotId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } else if (_game._objects.isInRoom(OBJ_BOTTLE)) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } + + _game._player._visible = true; + + if (_scene->_priorSceneId == 707) { + _game._player._playerPos = Common::Point(277, 103); + _game._player._facing = FACING_SOUTHWEST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(167, 152); + _game._player._facing = FACING_NORTH; + } + + if (_globals[kTeleporterCommand]) { + _game._player._visible = false; + _game._player._stepEnabled = false; + + switch (_globals[kTeleporterCommand]) { + case 1: + _scene->loadAnimation(formAnimName('E', 1), 75); + break; + + case 2: + _scene->loadAnimation(formAnimName('E', -1), 80); + break; + + default: + _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + } + _globals[kTeleporterCommand] = 0; + } + + _animationMode = 0; + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_BOTTLE); + _globals[kBottleStatus] = 2; + } + + sceneEntrySound(); +} + +void Scene706::step() { + if (_game._trigger == 75) { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._priorTimer = _scene->_frameStartTime - _game._player._ticksAmount; + _game._player.walk(Common::Point(264, 116), FACING_SOUTHWEST); + } + + if (_game._trigger == 80) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_scene->_activeAnimation != nullptr) { + if ((_animationMode != 0) && (_scene->_activeAnimation->getCurrentFrame() != _animationFrame)) { + _animationFrame = _scene->_activeAnimation->getCurrentFrame(); + + if (_animationFrame == 6) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._objects.setRoom(OBJ_VASE, 2); + + if (_animationMode == 2) { + _game._objects.setRoom(OBJ_BOTTLE, 1); + + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 4); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(195, 99)); + int idx = _scene->_dynamicHotspots.add(NOUN_BOTTLE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(175, 124), FACING_SOUTHEAST); + } + } + } + } +} + +void Scene706::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT)) + _game._player._needToWalk = true; +} + +void Scene706::actions() { + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 707; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_EXIT, NOUN_ROOM)) { + _scene->_nextSceneId = 705; + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_TAKE, NOUN_VASE)) { + if (_game._difficulty != DIFFICULTY_EASY) { + _animationMode = 1; + handleRexDeath(); + } else if (_game._trigger || !_game._objects.isInInventory(OBJ_VASE)) { + handleTakeVase(); + _emptyPedestral = true; + } + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_PUT, NOUN_BOTTLE, NOUN_PEDESTAL)) { + if ((_globals[kBottleStatus] == 2 && _game._difficulty == DIFFICULTY_HARD) || + (_globals[kBottleStatus] != 0 && _game._difficulty != DIFFICULTY_HARD)) { + if (!_game._objects.isInInventory(OBJ_VASE) || _game._trigger) { + _vaseMode = 1; + handleTakeVase(); + _action._inProgress = false; + return; + } + } else if (_game._objects.isInRoom(OBJ_VASE) || _game._trigger) { + _animationMode = 2; + handleRexDeath(); + _action._inProgress = false; + return; + } + } + + if (_action.isAction(VERB_PUT, NOUN_PEDESTAL) && _game._objects.isInInventory(_game._objects.getIdFromDesc(_action._activeAction._objectNameId))) { + int objectId = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); + if (_game._objects[objectId].hasQuality(10)) + _vm->_dialogs->show(70626); + else + _vm->_dialogs->show(70627); + } else if (_action.isAction(VERB_TAKE, NOUN_BOTTLE) && _game._objects.isInInventory(OBJ_VASE)) + _vm->_dialogs->show(70631); + else if (_action._lookFlag) { + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70610); + else + _vm->_dialogs->show(70611); + } else if (_action.isAction(VERB_LOOK, NOUN_FLOOR)) + _vm->_dialogs->show(70612); + else if (_action.isAction(VERB_LOOK, NOUN_PILLAR)) + _vm->_dialogs->show(70613); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_TEA_CUP)) + _vm->_dialogs->show(70614); + else if (_action.isAction(VERB_TAKE, NOUN_OLD_TEA_CUP)) + _vm->_dialogs->show(70615); + else if (_action.isAction(VERB_LOOK, NOUN_OLD_VASE)) + _vm->_dialogs->show(70616); + else if (_action.isAction(VERB_LOOK, NOUN_PORTRAIT)) + _vm->_dialogs->show(70617); + else if (_action.isAction(VERB_LOOK, NOUN_NAME_PLATE)) + _vm->_dialogs->show(70618); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(70619); + else if (_action.isAction(VERB_LOOK, NOUN_PEDESTAL)) { + if (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70620); + else if (_game._objects[OBJ_BOTTLE]._roomNumber == _scene->_currentSceneId) + _vm->_dialogs->show(70622); + else + _vm->_dialogs->show(70621); + } else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(70623); + else if (_action.isAction(VERB_LOOK, NOUN_VASE) && (_game._objects[OBJ_VASE]._roomNumber == _scene->_currentSceneId)) + _vm->_dialogs->show(70624); + else if (_action.isAction(VERB_LOOK, NOUN_BOTTLE) && (_action._mainObjectSource == 4)) + _vm->_dialogs->show(70632); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene707::setup() { + _game._player._spritesPrefix = ""; + // The original calls Scene7xx::setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene707::enter() { + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + teleporterEnter(); + + // The original uses Scene7xx_sceneEntrySound + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(25); +} + +void Scene707::step() { + teleporterStep(); +} + +void Scene707::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT) || _action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(70710); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD)) + _vm->_dialogs->show(70711); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(70712); + else if (_action.isAction(VERB_LOOK, NOUN_0_KEY) || _action.isAction(VERB_LOOK, NOUN_1_KEY) + || _action.isAction(VERB_LOOK, NOUN_2_KEY) || _action.isAction(VERB_LOOK, NOUN_3_KEY) + || _action.isAction(VERB_LOOK, NOUN_4_KEY) || _action.isAction(VERB_LOOK, NOUN_5_KEY) + || _action.isAction(VERB_LOOK, NOUN_6_KEY) || _action.isAction(VERB_LOOK, NOUN_7_KEY) + || _action.isAction(VERB_LOOK, NOUN_8_KEY) || _action.isAction(VERB_LOOK, NOUN_9_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_ENTER_KEY) + || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(70713); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) || _action._lookFlag) + _vm->_dialogs->show(70714); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene710::setup() { + _game._player._spritesPrefix = ""; + setAAName(); +} + +void Scene710::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + if (_game._objects[OBJ_VASE]._roomNumber == 706) { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('g', -1)); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 6, 0, 0, 0); + } + + _game._player._visible = false; + _scene->_sequences.addTimer(600, 70); + + sceneEntrySound(); +} + +void Scene710::step() { + if (_game._trigger == 70) { + if (_game._globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + } +} + +void Scene710::actions() { + if (_action.isAction(VERB_PUT_DOWN, NOUN_BINOCULARS)) { + _game._player._stepEnabled = false; + + if (_game._globals[kCityFlooded]) + _scene->_nextSceneId = 701; + else + _scene->_nextSceneId = 751; + + _action._inProgress = false; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene711::setup() { + // The original was calling Scene7xx::setPlayerSpreitesPrefix() + _vm->_sound->command(5); + Common::String oldName = _game._player._spritesPrefix; + _game._player._spritesPrefix = ""; + _game._player._scalingVelocity = true; + + if (oldName != _game._player._spritesPrefix) + _game._player._spritesChanged = true; + + _vm->_palette->setEntry(16, 10, 63, 63); + _vm->_palette->setEntry(17, 10, 45, 45); + + // The original was calling Scene7xx::setAAName() + _game._aaName = Resources::formatAAName(5); + + _game._player._spritesPrefix = ""; +} + +void Scene711::enter() { + if (_globals[kSexOfRex] == REX_FEMALE) + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + + teleporterEnter(); + + // The original was using Scene7xx_SceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(25); +} + +void Scene711::step() { + teleporterStep(); +} + +void Scene711::actions() { + if (teleporterActions()) + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene751::Scene751(MADSEngine *vm) : Scene7xx(vm) { + _rexHandingLine = false; +} + +void Scene751::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsByte(_rexHandingLine); +} + +void Scene751::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_FISHING_LINE); + _scene->addActiveVocab(VERB_WALKTO); +} + +void Scene751::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites("*RM701X0"); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites("*RM202A1"); + + if (!_game._visitedScenes._sceneRevisited) + _rexHandingLine = false; + + if (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + } + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + + if (_scene->_priorSceneId == 752) { + _game._player._playerPos = Common::Point(309, 138); + _game._player._facing = FACING_WEST; + } else if (_scene->_priorSceneId == 710) { + _game._player._playerPos = Common::Point(154, 129); + _game._player._facing = FACING_NORTH; + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addTimer(15, 70); + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(22, 131); + _game._player._facing = FACING_EAST; + _game._player._stepEnabled = false; + _scene->_sequences.addTimer(60, 60); + } else if (_rexHandingLine) { + _game._player._visible = false; + _game._player._playerPos = Common::Point(268, 140); + _game._player._facing = FACING_NORTHWEST; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + } else if (_globals[kLineStatus] == 2) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + } + + if (_scene->_roomChanged) { + _game._objects.addToInventory(OBJ_FISHING_LINE); + _game._objects.addToInventory(OBJ_BINOCULARS); + } + + sceneEntrySound(); + _game.loadQuoteSet(0x30A, 0x30B, 0x30C, 0x30D, 0x30E, 0); + + if (_globals[kTimebombTimer] > 0) + _globals[kTimebombTimer] = 10200; +} + +void Scene751::step() { + switch (_game._trigger) { + case 70: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[4]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + + if ((_globals[kTimebombTimer] >= 10800) && (_globals[kTimebombStatus] == 1)) { + _globals[kTimebombStatus] = 3; + _globals[kTimebombTimer] = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } + + switch (_game._trigger) { + case 60: + _vm->_sound->command(16); + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 61); + break; + + case 61: + _game._player.walk(Common::Point(61, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 62); + break; + + case 62: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 63); + break; + + case 63: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _game._player._stepEnabled = true; + _scene->_kernelMessages.reset(); + break; + + default: + break; + } +} + +void Scene751::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTHEAST); + + if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING)) + _game._player.walk(Common::Point(154, 129), FACING_NORTH); + + if (_action.isAction(VERB_WALKTO, NOUN_EAST_END_OF_PLATFORM)) + _game._player._walkOffScreenSceneId = 752; + + if (!_rexHandingLine) + return; + + if (_action.isAction(VERB_LOOK) || _action.isObject(NOUN_FISHING_LINE) || _action.isAction(VERB_TALKTO)) + _game._player._needToWalk = false; + + if ((!_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || !_action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK)) + && (_game._player._needToWalk)) { + switch (_game._trigger) { + case 0: + _game._player._readyToWalk = false; + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 11, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 7); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _rexHandingLine = false; + _game._player._stepEnabled = true; + _game._player._readyToWalk = true; + break; + + default: + break; + } + } +} + +void Scene751::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; // Nothing + else if (_action.isAction(VERB_LOOK, NOUN_BINOCULARS, NOUN_TALL_BUILDING)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 6, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, -2); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(155, 129)); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.addTimer(15, 2); + } + break; + + case 2: + _scene->_nextSceneId = 710; + break; + + default: + break; + } + } else if (_action.isAction(VERB_STEP_INTO, NOUN_ELEVATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(16); + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_kernelMessages.reset(); + _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 0, 120, _game.getQuote(0x30D)); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: + _game._player.walk(Common::Point(22, 131), FACING_EAST); + _scene->_sequences.addTimer(120, 3); + break; + + case 3: + _vm->_sound->command(17); + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 5, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 4); + break; + + case 4: + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, -1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(48, 136)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 10); + _scene->_sequences.addTimer(60, 5); + break; + + case 5: + _game._player._stepEnabled = true; + _scene->_nextSceneId = 513; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PUT, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_HOOK) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_HOOK)) { + if (_globals[kLineStatus] == 1) { + switch (_game._trigger) { + case 0: + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, 6); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], -1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 1); + break; + + case 1: { + int syncIdx = _globals._sequenceIndexes[2]; + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 7); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[2], syncIdx); + _scene->_sequences.addTimer(30, 2); + } + break; + + case 2: + _rexHandingLine = true; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 8, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 3); + break; + + case 3: { + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[2]); + _game._player._visible = true; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, -1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 7); + int idx = _scene->_dynamicHotspots.add(NOUN_FISHING_LINE, VERB_WALKTO, _globals._sequenceIndexes[3], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(268, 140), FACING_NORTHWEST); + _scene->_kernelMessages.reset(); + _game._objects.setRoom(OBJ_FISHING_LINE, _scene->_currentSceneId); + _rexHandingLine = false; + _globals[kLineStatus] = 2; + _game._player._stepEnabled = true; + _vm->_dialogs->show(75120); + } + break; + + default: + break; + } + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY)) + _vm->_dialogs->show(75110); + else if (_action.isAction(VERB_LOOK, NOUN_ELEVATOR)) + _vm->_dialogs->show(75112); + else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(75113); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(75114); + else if ((_action.isAction(VERB_LOOK, NOUN_HOOK) || _action.isAction(VERB_LOOK, NOUN_FISHING_LINE)) + && (_globals[kLineStatus] == 2 || _globals[kLineStatus] == 3)) + _vm->_dialogs->show(75116); + else if (_action.isAction(VERB_LOOK, NOUN_HOOK)) + _vm->_dialogs->show(75115); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(75117); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(75118); + else if (_action.isAction(VERB_LOOK, NOUN_EAST_END_OF_PLATFORM)) + _vm->_dialogs->show(75119); + else if (_action.isAction(VERB_TAKE, NOUN_FISHING_LINE) && (_globals[kLineStatus] == 3 || _globals[kLineStatus] == 2)) + _vm->_dialogs->show(75121); + else if (_action.isAction(VERB_LOOK, NOUN_TALL_BUILDING)) + _vm->_dialogs->show(75122); + else if (_action.isAction(VERB_TIE, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON) || _action.isAction(VERB_ATTACH, NOUN_FISHING_LINE, NOUN_CEMENT_PYLON)) + _vm->_dialogs->show(75123); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene752::Scene752(MADSEngine *vm) : Scene7xx(vm) { + _cardId = -1; +} + +void Scene752::synchronize(Common::Serializer &s) { + Scene7xx::synchronize(s); + + s.syncAsSint16LE(_cardId); +} + +void Scene752::setup() { + setPlayerSpritesPrefix(); + setAAName(); + + _scene->addActiveVocab(NOUN_ID_CARD); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(VERB_LOOK_AT); + _scene->addActiveVocab(NOUN_LASER_BEAM); +} + +void Scene752::enter() { + _globals._spriteIndexes[14] = _scene->_sprites.addSprites(formAnimName('l', -1)); + _globals._spriteIndexes[12] = _scene->_sprites.addSprites("*RXMBD_8"); + + if (_scene->_priorSceneId == 751) { + _game._player._playerPos = Common::Point(13, 145); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(289, 138); + _game._player.walk(Common::Point(262, 148), FACING_WEST); + _game._player._facing = FACING_WEST; + _game._player._visible = true; + } + + if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) { + _globals._spriteIndexes[13] = _scene->_sprites.addSprites(formAnimName('i', -1)); + _globals._sequenceIndexes[13] = _scene->_sequences.startCycle(_globals._spriteIndexes[13], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[13], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_ID_CARD, VERB_WALKTO, _globals._sequenceIndexes[13], Common::Rect(0, 0, 0, 0)); + _cardId = _scene->_dynamicHotspots.setPosition(idx, Common::Point(234, 135), FACING_NORTH); + } + + if (_game._globals[kLaserHoleIsThere]) { + _globals._sequenceIndexes[14] = _scene->_sequences.startCycle(_globals._spriteIndexes[14], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[14], 13); + int idx = _scene->_dynamicHotspots.add(NOUN_LASER_BEAM, VERB_LOOK_AT, _globals._sequenceIndexes[14], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(215, 130), FACING_NORTHWEST); + } + + if (_game._globals[kTeleporterCommand]) { + switch(_game._globals[kTeleporterCommand]) { + case TELEPORTER_BEAM_OUT: + case TELEPORTER_WRONG: + case TELEPORTER_STEP_OUT: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + + _game._globals[kTeleporterCommand] = TELEPORTER_NONE; + } + + if (_globals._timebombTimer > 0) + _globals._timebombTimer = 10800 - 600; + + sceneEntrySound(); +} + +void Scene752::step() { + if (_globals._timebombTimer >= 10800 && _game._globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) { + _globals[kTimebombStatus] = TIMEBOMB_DEAD; + _globals._timebombTimer = 0; + _globals[kCheckDaemonTimebomb] = false; + _scene->_nextSceneId = 620; + } +} + +void Scene752::preActions() { + if (_action.isAction(VERB_WALKTO, NOUN_WEST_END_OF_PLATFORM)) { + _game._player._walkOffScreenSceneId = 751; + } +} + +void Scene752::actions() { + if (_action.isAction(VERB_WALK_ALONG, NOUN_PLATFORM)) + ; + else if (_action.isAction(VERB_STEP_INTO, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 711; + } else if (_action.isAction(VERB_TAKE, NOUN_ID_CARD) && (!_game._objects.isInInventory(OBJ_ID_CARD) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + _scene->_sequences.remove(_globals._sequenceIndexes[13]); + _game._objects.addToInventory(OBJ_ID_CARD); + _scene->_dynamicHotspots.remove(_cardId); + _vm->_dialogs->show(OBJ_ID_CARD, 830); + break; + case 2: + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4) && (!_game._objects.isInInventory(OBJ_BONES) || _game._trigger)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[12] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[12], false, 5, 2, 0, 0); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + case 1: + _vm->_sound->command(0xF); + if (_game._objects.isInInventory(OBJ_BONE)) + _game._objects.setRoom(OBJ_BONE, 1); + _game._objects.addToInventory(OBJ_BONES); + _vm->_dialogs->show(OBJ_BONES, 75221); + break; + case 2: + _scene->_sequences.updateTimeout(-1, _globals._sequenceIndexes[12]); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + default: + break; + } + } else if (_action._lookFlag || _action.isAction(VERB_LOOK, NOUN_CITY)) { + if (_globals[kLaserHoleIsThere]) + _vm->_dialogs->show(75212); + else + _vm->_dialogs->show(75210); + } else if (_action.isAction(VERB_LOOK, NOUN_PLATFORM)) + _vm->_dialogs->show(75213); + else if (_action.isAction(VERB_LOOK, NOUN_CEMENT_BLOCK)) + _vm->_dialogs->show(75214); + else if (_action.isAction(VERB_LOOK, NOUN_ROCK)) + _vm->_dialogs->show(75215); + else if (_action.isAction(VERB_TAKE, NOUN_ROCK)) + _vm->_dialogs->show(75216); + else if (_action.isAction(VERB_LOOK, NOUN_WEST_END_OF_PLATFORM)) + _vm->_dialogs->show(75217); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(75218); + else if ((_action.isAction(VERB_LOOK, NOUN_BONES) || _action.isAction(VERB_LOOK, NOUN_ID_CARD)) && (_action._mainObjectSource == 4)) { + if (_game._objects[OBJ_ID_CARD]._roomNumber == 752) + _vm->_dialogs->show(75219); + else + _vm->_dialogs->show(75220); + } else if (_action.isAction(VERB_TAKE, NOUN_BONES) && (_action._mainObjectSource == 4)) { + if (_game._objects.isInInventory(OBJ_BONES)) + _vm->_dialogs->show(75222); + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes7.h b/engines/mads/nebular/nebular_scenes7.h new file mode 100644 index 0000000000..dfb3c0f16e --- /dev/null +++ b/engines/mads/nebular/nebular_scenes7.h @@ -0,0 +1,238 @@ +/* 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 MADS_NEBULAR_SCENES7_H +#define MADS_NEBULAR_SCENES7_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene7xx : public NebularScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void setAAName(); + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix(); + + void sceneEntrySound(); + +public: + Scene7xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene701 : public Scene7xx { +private: + int _fishingLineId; + +public: + Scene701(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); + virtual void step(); +}; + +class Scene702 : public Scene7xx { +public: + Scene702(MADSEngine *vm) : Scene7xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene703 : public Scene7xx{ +private: + int _monsterMode; + int _boatFrame; + int _curSequence; + int _boatDir; + + bool _useBomb; + bool _startMonsterTimer; + bool _rexDeathFl; + bool _restartTrigger70Fl; + + uint32 _lastFrameTime; + uint32 _monsterTime; + + Conversation _dialog1; + + void handleBottleInterface(); + void setBottleSequence(); + void handleFillBottle(int quote); + +public: + Scene703(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene704 : public Scene7xx{ +private: + int _bottleHotspotId; + int _boatCurrentFrame; + int _animationMode; + int _boatDirection; + + bool _takeBottleFl; + + Conversation _dialog1; + + void handleFillBottle(int quote); + void setBottleSequence(); + void handleBottleInterface(); + +public: + Scene704(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene705 : public Scene7xx{ +private: + Conversation _dialog1; + + void handleFillBottle(int quote); + void setBottleSequence(); + void handleBottleInterface(); + +public: + Scene705(MADSEngine *vm) : Scene7xx(vm) {} + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene706 : public Scene7xx{ +private: + int _vaseHotspotId; + int _vaseMode; + int _animationMode; + int _animationFrame; + + bool _emptyPedestral; + + void handleTakeVase(); + void handleRexDeath(); + +public: + Scene706(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene707 : public SceneTeleporter { +public: + Scene707(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene710 : public Scene7xx { +public: + Scene710(MADSEngine *vm) : Scene7xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene711 : public SceneTeleporter { +public: + Scene711(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene751 : public Scene7xx{ +private: + bool _rexHandingLine; + +public: + Scene751(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene752 : public Scene7xx { +private: + int _cardId; + +public: + Scene752(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES7_H */ diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp new file mode 100644 index 0000000000..66502831cc --- /dev/null +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -0,0 +1,1524 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/nebular/nebular_scenes8.h" + +namespace MADS { + +namespace Nebular { + +void Scene8xx::setPlayerSpritesPrefix() { + _vm->_sound->command(5); + if ((_globals[kFromCockpit] && !_globals[kExitShip]) || + _scene->_nextSceneId == 804 || _scene->_nextSceneId == 805 || + _scene->_nextSceneId == 808 || _scene->_nextSceneId == 810) { + _game._player._spritesPrefix = ""; + } else + _game._player._spritesPrefix = _globals[kSexOfRex] == SEX_FEMALE ? "ROX" : "RXM"; + + _vm->_palette->setEntry(16, 0x0A, 0x3F, 0x3F); + _vm->_palette->setEntry(17, 0x0A, 0x2D, 0x2D); +} + +void Scene8xx::setAAName() { + _game._aaName = Resources::formatAAName(5); +} + +void Scene8xx::sceneEntrySound() { + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else { + switch (_scene->_nextSceneId) { + case 801: + case 802: + case 803: + case 804: + case 806: + case 807: + case 808: + _vm->_sound->command(20); + break; + + case 805: + _vm->_sound->command(23); + break; + + case 810: + _vm->_sound->command(10); + break; + + default: + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +Scene801::Scene801(MADSEngine *vm) : Scene8xx(vm) { + _walkThroughDoor = false; +} + +void Scene801::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_walkThroughDoor); +} + +void Scene801::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene801::enter() { + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('a', -1)); + + if (_scene->_priorSceneId != 802) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + } + + if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) { + _game._player._playerPos = Common::Point(_globals[kCutX], _globals[kCutY]); + _game._player._facing = (Facing)_globals[kCutFacing]; + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + } else if (_scene->_priorSceneId == 808) { + _game._player._playerPos = Common::Point(148, 110); + _game._player._facing = FACING_NORTH; + } else if (_scene->_priorSceneId == 802) { + _game._player._playerPos = Common::Point(307, 111); + _game._player.walk(Common::Point(270, 118), FACING_WEST); + _game._player._visible = true; + } else if ((_scene->_priorSceneId != -2) && !_globals[kTeleporterCommand]) { + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + _game._player._visible = true; + } + + _globals[kBetweenRooms] = false; + + if (_globals[kTeleporterCommand]) { + _game._player._stepEnabled = false; + switch (_globals[kTeleporterCommand]) { + case 1: + _game._player._playerPos = Common::Point(8, 117); + _globals[kTeleporterUnderstood] = true; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 75); + _vm->_sound->command(30); + break; + + case 2: + _game._player._playerPos = Common::Point(8, 117); + _globals[kTeleporterUnderstood] = true; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 1, 13); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 8090); + _vm->_sound->command(30); + break; + + case 3: + case 4: + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + _globals[kTeleporterCommand] = 0; + } + + _walkThroughDoor = false; + if (_scene->_priorSceneId == 802) { + _game._player._stepEnabled = false; + _walkThroughDoor = true; + } + + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 11, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], -1, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 14); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 9, 0, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], -1, -2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 14); + + sceneEntrySound(); +} + +void Scene801::step() { + if (_game._trigger == 75) { + if (_globals[kSexOfRex] == REX_FEMALE) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 8); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 140); + } else { + _game._player._stepEnabled = true; + _game._player._visible = true; + _game._player._playerPos = Common::Point(8, 117); + _game._player.walk(Common::Point(41, 115), FACING_EAST); + } + } + + if (_game._trigger == 140) { + _vm->_sound->command(27); + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, 8); + _scene->_sequences.addTimer(100, 141); + } + + if (_game._trigger == 141) { + _scene->_reloadSceneFlag = true; + _scene->_nextSceneId = _scene->_priorSceneId; + _globals[kTeleporterCommand] = 0; + } + + if (_game._trigger == 80) { + _globals[kTeleporterCommand] = 1; + _scene->_nextSceneId = _globals[kTeleporterDestination]; + _scene->_reloadSceneFlag = true; + } + + if (_walkThroughDoor && (_game._player._playerPos == Common::Point(270, 118))) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _walkThroughDoor = false; + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 120); + } + + if (_game._trigger == 120) { + _vm->_sound->command(12); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 90) { + _game._player.walk(Common::Point(307, 111), FACING_EAST); + _scene->_sequences.addTimer(80, 130); + } + + if (_game._trigger == 130) { + _vm->_sound->command(12); + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 110); + } + + if (_game._trigger == 110) { + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 10); + _scene->_nextSceneId = 802; + } +} + +void Scene801::preActions() { + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) { + _game._player.walk(Common::Point(148, 110), FACING_NORTH); + _game._player._needToWalk = true; + _game._player._readyToWalk = true; + } + + if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER) && _globals[kBeamIsUp]) { + _globals[kCutX] = _game._player._playerPos.x; + _globals[kCutY] = _game._player._playerPos.y; + _globals[kCutFacing] = _game._player._facing; + _globals[kForceBeamDown] = true; + _globals[kDontRepeat] = true; + _scene->_nextSceneId = 803; + } +} + +void Scene801::actions() { + if (_action.isAction(VERB_LOOK, NOUN_CONTROL_PANEL)) + _scene->_nextSceneId = 808; + else if (_action.isAction(VERB_WALK_INSIDE, NOUN_TELEPORTER)) { + _game._player._stepEnabled = false; + _game._player._visible = false; + _scene->_nextSceneId = 807; + } else if (_action.isAction(VERB_WALK_THROUGH, NOUN_DOOR) && (_game._player._playerPos == Common::Point(270, 118))) { + _game._player._stepEnabled = false; + _game._player._facing = FACING_EAST; + _game._player.selectSeries(); + _globals[kBetweenRooms] = true; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 4, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 5); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 13); + _vm->_sound->command(11); + } else if (_action.isAction(VERB_LOOK, NOUN_CEILING)) + _vm->_dialogs->show(80110); + else if (_action.isAction(VERB_LOOK, NOUN_MONITOR)) + _vm->_dialogs->show(80111); + else if (_action.isAction(VERB_LOOK, NOUN_TELEPORTER)) + _vm->_dialogs->show(80112); + else if (_action.isAction(VERB_LOOK, NOUN_EQUIPMENT) || _action._lookFlag) + _vm->_dialogs->show(80113); + else if (_action.isAction(VERB_LOOK, NOUN_SPEAKER)) + _vm->_dialogs->show(80114); + else if (_action.isAction(VERB_LOOK, NOUN_EYE_CHART)) + _vm->_dialogs->show(80115); + else if (_action.isAction(VERB_LOOK, NOUN_WALL)) + _vm->_dialogs->show(80116); + else if (_action.isAction(VERB_LOOK, NOUN_DOOR)) + _vm->_dialogs->show(80117); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene802::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_SHIELD_MODULATOR); + _scene->addActiveVocab(VERB_WALKTO); + _scene->addActiveVocab(NOUN_REMOTE); +} + +void Scene802::enter() { + _globals._spriteIndexes[2] = _scene->_sprites.addSprites("*RXMRC_8"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 2)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('f', 0)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites("*RXMBD_8"); + _globals[kBetweenRooms] = false; + + if ((_globals[kCameFromCut]) && (_globals[kCutX] != 0)) { + _game._player._playerPos.x = _globals[kCutX]; + _game._player._playerPos.y = _globals[kCutY]; + _game._player._facing = (Facing)_globals[kCutFacing]; + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + _globals[kAntigravClock] = _scene->_frameStartTime; + } else if (_scene->_priorSceneId == 801) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } else if (_scene->_priorSceneId == 803) { + _game._player._playerPos = Common::Point(303, 119); + _game._player._facing = FACING_WEST; + + } else if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 129); + _game._player._facing = FACING_EAST; + } + + _game._player._visible = true; + + + + if (_globals[kHasWatchedAntigrav] && !_globals[kRemoteSequenceRan]) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _scene->_sequences.addTimer(200, 70); + } + + if ((_globals[kRemoteOnGround]) && (!_game._objects.isInInventory(OBJ_REMOTE))) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO,_globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH); + } + + if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled]) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_WALKTO, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(93, 97), FACING_NORTH); + } + sceneEntrySound(); +} + +void Scene802::step() { + if (_game._trigger == 70) { + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[3], 1, 19); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_SPRITE, 4, 72); + } + + if (_game._trigger == 71) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 8); + int idx = _scene->_dynamicHotspots.add(NOUN_REMOTE, VERB_WALKTO, _globals._sequenceIndexes[4], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(107, 99), FACING_NORTH); + + _globals[kRemoteSequenceRan] = true; + _globals[kRemoteOnGround] = true; + _game._player._stepEnabled = true; + } + + if (_game._trigger == 72) + _vm->_sound->command(13); +} + +void Scene802::preActions() { + if (_action.isAction(VERB_WALK_TOWARDS, NOUN_BUILDING_TO_WEST)) + _game._player._walkOffScreenSceneId = 801; + + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_EAST)) { + _game._player._walkOffScreenSceneId = 803; + _globals[kForceBeamDown] = false; + } + + if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _game._player._needToWalk = false; +} + +void Scene802::actions() { + if (_action.isAction(VERB_TAKE, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], 1, 2); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[2]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_SPRITE, 2, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _vm->_sound->command(9); + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _vm->_dialogs->showItem(OBJ_SHIELD_MODULATOR, 80215); + break; + + default: + break; + } + } else if ((_action.isAction(VERB_TAKE, NOUN_REMOTE)) && (!_game._objects.isInInventory(OBJ_REMOTE))) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[5] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[5], true, 7, 2, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[5]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_SPRITE, 4, 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 2); + break; + + case 1: + _scene->_sequences.remove(_globals._sequenceIndexes[4]); + _vm->_sound->command(9); + _globals[kRemoteOnGround] = false; + break; + + case 2: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _scene->_sequences.addTimer(20, 3); + break; + + case 3: + _game._player._stepEnabled = true; + _game._objects.addToInventory(OBJ_REMOTE); + _vm->_dialogs->showItem(OBJ_REMOTE, 80223); + break; + + default: + break; + } + } else if (!_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled]) + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80210); + else if (!_globals[kRemoteOnGround]&& !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80211); + else if (_globals[kRemoteOnGround] && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80213); + else if (_globals[kRemoteOnGround] && (_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) || _globals[kShieldModInstalled]) + && (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD) || _action._lookFlag)) + _vm->_dialogs->show(80212); + else if (!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR) && !_globals[kShieldModInstalled] && _action.isAction(VERB_LOOK, NOUN_SHIELD_MODULATOR)) + _vm->_dialogs->show(80214); + else if (_globals[kRemoteOnGround] && _action.isAction(VERB_LOOK, NOUN_REMOTE)) + _vm->_dialogs->show(80216); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP)) { + if ((!_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) && (!_globals[kShieldModInstalled])) + _vm->_dialogs->show(80218); + else + _vm->_dialogs->show(80217); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES)) + _vm->_dialogs->show(80219); + else if (_action.isAction(VERB_LOOK, NOUN_PATH_TO_EAST)) + _vm->_dialogs->show(80220); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(80221); + else if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _vm->_dialogs->show(80222); + else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(80224); + else if (_action.isAction(VERB_LOOK, NOUN_BUILDING_TO_WEST)) + _vm->_dialogs->show(80225); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene803::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(NOUN_GUTS); + _scene->addActiveVocab(VERB_WALKTO); + + if ((!_globals[kFromCockpit] && _globals[kReturnFromCut] && !_globals[kBeamIsUp]) + || (_globals[kFromCockpit] && !_globals[kExitShip])) { + _game._player._spritesPrefix = ""; + _game._player._spritesChanged = true; + } +} + +void Scene803::enter() { + _globals[kBetweenRooms] = false; + _game._player._visible = false; + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('f', 1)); + _globals._spriteIndexes[9] = _scene->_sprites.addSprites("*RXMBD_2"); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1)); + + _game.loadQuoteSet(0x31B, 0x31C, 0x31D, 0x31E, 0x31F, 0x320, 0x321, 0x322, 0); + + if (_globals[kHoppyDead]) { + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('e', 1)); + _globals._sequenceIndexes[7] = _scene->_sequences.startCycle(_globals._spriteIndexes[7], false, 1); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[7], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + } + + if (!_globals[kBeamIsUp] && !_globals[kReturnFromCut] && (!_globals[kFromCockpit] || _globals[kExitShip])) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + } + + if (!_globals[kFromCockpit]) { + if (!_globals[kReturnFromCut]) { + if (_scene->_priorSceneId != -2) { + _game._player._playerPos = Common::Point(15, 130); + _game._player._facing = FACING_EAST; + } + _game._player._visible = true; + } else if (!_globals[kBeamIsUp]){ + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 3)); + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('a', 2)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 15); + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _vm->_sound->command(14); + } + + if (_globals[kBeamIsUp] && !_globals[kReturnFromCut]){ + if (_globals[kForceBeamDown]) + _game._player._visible = false; + else + _game._player._visible = true; + + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _vm->_sound->command(15); + _game._player._stepEnabled = false; + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 1, 6); + _scene->_sequences.setDepth(_globals._sequenceIndexes[5], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5], SEQUENCE_TRIGGER_EXPIRE, 0, 100); + } + } else if (!_globals[kExitShip]) { + if (!_globals[kBeamIsUp]) { + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[3] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[3], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[3], SEQUENCE_TRIGGER_EXPIRE, 0, 130); + _vm->_sound->command(14); + } else { + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('c', 1)); + _game._player._visible = false; + _game._player._stepEnabled = false; + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + _globals._sequenceIndexes[8] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[8], false, 8, 1, 0, 0); + _scene->_sequences.setDepth(_globals._sequenceIndexes[8], 1); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[8], SEQUENCE_TRIGGER_EXPIRE, 0, 140); + } + } else { + _game._player._stepEnabled = false; + _game._player._playerPos = Common::Point(197, 96); + _game._player._facing = FACING_SOUTHWEST; + _game._player._visible = true; + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('d', 1)); + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19); + _scene->_sequences.addTimer(1, 150); + } + + sceneEntrySound(); +} + +void Scene803::step() { + if (_game._trigger == 120) { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 19); + _scene->_nextSceneId = 804; + } + + if (_game._trigger == 100) { + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], 2, 2); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 1); + if (!_globals[kHoppyDead]) { + _globals._sequenceIndexes[5] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[5], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[5], 7, 12); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[5],SEQUENCE_TRIGGER_EXPIRE, 0, 101); + } else { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + _vm->_sound->command(16); + _globals[kCameFromCut] = true; + _globals[kBeamIsUp] = false; + _globals[kReturnFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = true; + _globals[kHasWatchedAntigrav] = true; + + if (_globals[kForceBeamDown]) + _scene->_nextSceneId = _scene->_priorSceneId; + else + _game._player._stepEnabled = true; + } + } + + if (_game._trigger == 101) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], false, -2); + int idx = _scene->_dynamicHotspots.add(NOUN_GUTS, VERB_WALKTO, _globals._sequenceIndexes[5], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(66, 123), FACING_SOUTH); + _vm->_sound->command(16); + _globals[kCameFromCut] = true; + _globals[kBeamIsUp] = false; + _globals[kReturnFromCut] = false; + _globals[kDontRepeat] = false; + _globals[kHoppyDead] = true; + _globals[kHasWatchedAntigrav] = true; + + if (_globals[kForceBeamDown]) + _scene->_nextSceneId = _scene->_priorSceneId; + else + _game._player._stepEnabled = true; + } + + if (_game._trigger == 80) { + if (!_globals[kHoppyDead]) + _scene->_sequences.addTimer(350, 70); + + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 12, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 1, 3); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + } + + if (_game._trigger == 70) { + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 8, 1, 0, 0); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _vm->_sound->command(31); + } + + if (_game._trigger == 71) + _scene->_sequences.addTimer(200, 110); + + if (_game._trigger == 90) { + int syncIdx = _globals._sequenceIndexes[4]; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 15, 0, 0, 0); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[4], syncIdx); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[4], 4, 9); + if (_globals[kHoppyDead]) + _scene->_sequences.addTimer(200, 110); + } + + if (_game._trigger == 110) + _scene->_nextSceneId = 808; + + if (_game._trigger == 130) { + _globals[kBeamIsUp] = true; + _scene->_nextSceneId = 804; + } + + if (_game._trigger == 140) { + if (!_globals[kWindowFixed]) { + _scene->_nextSceneId = 810; + _globals[kInSpace] = true; + } else { + if (!_globals[kShieldModInstalled]) + _game._winStatus = 1; + else if (!_globals[kTargetModInstalled]) + _game._winStatus = 2; + else + _game._winStatus = 3; + + _vm->quitGame(); + } + } + + if (_game._trigger == 150) { + _scene->_sequences.remove(_globals._sequenceIndexes[6]); + _vm->_sound->command(18); + _globals._sequenceIndexes[6] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 151); + } + + if (_game._trigger == 151) { + _globals[kBeamIsUp] = false; + _globals[kFromCockpit] = false; + _globals[kExitShip] = false; + _game._player._stepEnabled = true; + } +} + +void Scene803::preActions() { + if (_action.isAction(VERB_WALK_DOWN, NOUN_PATH_TO_WEST)) + _game._player._walkOffScreenSceneId = 802; + + if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _game._player._needToWalk = false; +} + +void Scene803::actions() { + if (_action.isAction(VERB_TAKE, NOUN_GUTS)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _game._player._visible = false; + _globals._sequenceIndexes[9] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 160); + break; + + case 160: { + int syncIdx = _globals._sequenceIndexes[9]; + _globals._sequenceIndexes[9] = _scene->_sequences.startCycle(_globals._spriteIndexes[9], false, 4); + _scene->_sequences.updateTimeout(_globals._sequenceIndexes[9], syncIdx); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addTimer(60, 161); + } + break; + + case 161: { + int quoteId = 0x31A + _vm->getRandomNumber(1, 8); + _scene->_kernelMessages.add(Common::Point(64, 67), 0x1110, 32, 0, 80, _game.getQuote(quoteId)); + _scene->_sequences.addTimer(60, 162); + } + break; + + case 162: + _scene->_sequences.remove(_globals._sequenceIndexes[9]); + _globals._sequenceIndexes[9] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[9], true, 6, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[9], 1, 4); + _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[9]); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[9], SEQUENCE_TRIGGER_EXPIRE, 0, 163); + break; + + case 163: + _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount; + _game._player._visible = true; + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_ENTER, NOUN_SHIP)) { + _vm->_sound->command(17); + _game._player._stepEnabled = false; + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[6] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[6], false, 8, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[6], 1, 19); + _scene->_sequences.setDepth(_globals._sequenceIndexes[6], 4); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[6], SEQUENCE_TRIGGER_EXPIRE, 0, 120); + _globals[kBeamIsUp] = false; + } else if (_action.isAction(VERB_LOOK, NOUN_LAUNCH_PAD)) + _vm->_dialogs->show(80310); + else if (_action._lookFlag) + _vm->_dialogs->show(80310); + else if (_action.isAction(VERB_LOOK, NOUN_PAD_TO_WEST)) + _vm->_dialogs->show(80311); + else if (_action.isAction(VERB_LOOK, NOUN_GUTS)) { + if (_game._storyMode == STORYMODE_NICE) + _vm->_dialogs->show(80312); + else + _vm->_dialogs->show(80313); + } else if (_action.isAction(VERB_LOOK, NOUN_BUSHES)) + _vm->_dialogs->show(80315); + else if (_action.isAction(VERB_LOOK, NOUN_SHIP)) + _vm->_dialogs->show(80317); + else if (_action.isAction(VERB_LOOK, NOUN_TOWER)) + _vm->_dialogs->show(80318); + else if (_action.isAction(VERB_LOOK, NOUN_TREE) || _action.isAction(VERB_LOOK, NOUN_TREES)) + _vm->_dialogs->show(80319); + else if (_action.isAction(VERB_LOOK, NOUN_SKY)) + _vm->_dialogs->show(80320); + else if (_action.isAction(VERB_TAKE, NOUN_SHIP)) + _vm->_dialogs->show(80321); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene804::Scene804(MADSEngine *vm) : Scene8xx(vm) { + _messWithThrottle = false; + _movingThrottle = false; + _throttleGone = false; + _dontPullThrottleAgain = false; + _pullThrottleReally = false; + _alreadyOrgan = false; + _alreadyPop = false; + + _throttleCounter = 0; + _resetFrame = -1; +} + +void Scene804::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_messWithThrottle); + s.syncAsByte(_movingThrottle); + s.syncAsByte(_throttleGone); + s.syncAsByte(_dontPullThrottleAgain); + s.syncAsByte(_pullThrottleReally); + s.syncAsByte(_alreadyOrgan); + s.syncAsByte(_alreadyPop); + + s.syncAsSint16LE(_resetFrame); + s.syncAsUint32LE(_throttleCounter); +} + +void Scene804::setup() { + Scene8xx::setPlayerSpritesPrefix(); + Scene8xx::setAAName(); +} + +void Scene804::enter() { + _messWithThrottle = false; + _throttleCounter = 0; + _movingThrottle = false; + _throttleGone = false; + _dontPullThrottleAgain = false; + _resetFrame = -1; + _pullThrottleReally = false; + _alreadyOrgan = false; + _alreadyPop = false; + + + if (_globals[kCopyProtectFailed]) { + // Copy protection failed + _globals[kInSpace] = true; + _globals[kWindowFixed] = 0; + } + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites(formAnimName('x', 0)); + _globals._spriteIndexes[5] = _scene->_sprites.addSprites(formAnimName('x', 1)); + _globals._spriteIndexes[6] = _scene->_sprites.addSprites(formAnimName('x', 2)); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('x', 3)); + _globals._spriteIndexes[7] = _scene->_sprites.addSprites(formAnimName('x', 4)); + _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('f', 1)); + + _game.loadQuoteSet(791, 0); + + if (_globals[kInSpace]) { + if (_globals[kWindowFixed]) { + _globals._sequenceIndexes[5] = _scene->_sequences.startCycle(_globals._spriteIndexes[5], 0, 1); + _scene->_sequences.addTimer(60, 100); + } else { + _globals._sequenceIndexes[6] = _scene->_sequences.startCycle(_globals._spriteIndexes[6], false, 1); + _globals._sequenceIndexes[7] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[7], false, 4, 0, 0, 0); + _scene->_sequences.addTimer(160, 70); + _game._player._stepEnabled = false; + } + } else { + if (_globals[kBeamIsUp] == 0) + _globals._sequenceIndexes[8] = _scene->_sequences.startCycle(_globals._spriteIndexes[8], false, 1); + + if (_globals[kWindowFixed] == 0) + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + } + + _scene->loadAnimation(Resources::formatName(804, 'r', 1, EXT_AA, "")); + + Scene8xx::sceneEntrySound(); + + if (_globals[kInSpace] && !_globals[kWindowFixed]) { + _scene->_userInterface.setup(kInputLimitedSentences); + _vm->_sound->command(19); + } +} + +void Scene804::step() { + if (!_messWithThrottle) { + + if ((_throttleGone) && (_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 39)) { + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle + (_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setPosition(_globals._sequenceIndexes[1], Common::Point(133, 139)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _throttleGone = false; + } + + if ((_movingThrottle) && (_scene->_activeAnimation->getCurrentFrame() == 42)) { + _resetFrame = 0; + _movingThrottle = false; + } + + if (_game._trigger == 70) { + _resetFrame = 42; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 65) + _scene->_sequences.remove(_globals._sequenceIndexes[7]); + + switch (_game._storyMode) { + case STORYMODE_NAUGHTY: + if (_scene->_activeAnimation->getCurrentFrame() == 81) { + _resetFrame = 80; + _globals[kInSpace] = false; + _globals[kBeamIsUp] = true; + + assert(!_globals[kCopyProtectFailed]); + _game._winStatus = 4; + _vm->quitGame(); + } + break; + + case STORYMODE_NICE: + if (_scene->_activeAnimation->getCurrentFrame() == 68) { + _resetFrame = 66; + _globals[kInSpace] = false; + _globals[kBeamIsUp] = true; + + assert(!_globals[kCopyProtectFailed]); + _game._winStatus = 4; + _vm->quitGame(); + } + } + + if (_scene->_activeAnimation->getCurrentFrame() == 34) { + _resetFrame = 36; + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 37) { + _resetFrame = 36; + if (!_dontPullThrottleAgain) { + _dontPullThrottleAgain = true; + _scene->_sequences.addTimer(60, 80); + } + } + + if (_game._trigger == 80) { + _scene->_nextSceneId = 803; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 7) && (!_globals[kWindowFixed])) { + _globals._sequenceIndexes[4] = _scene->_sequences.startCycle(_globals._spriteIndexes[4], false, 1); + _scene->_sequences.addTimer(20, 110); + _globals[kWindowFixed] = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 10) { + _resetFrame = 0; + _game._player._stepEnabled = true; + _game._objects.setRoom(OBJ_POLYCEMENT, NOWHERE); + } + + if (_scene->_activeAnimation->getCurrentFrame() == 1) { + int randomVal = _vm->getRandomNumber(29) + 1; + switch (randomVal) { + case 1: + _resetFrame = 25; + break; + case 2: + _resetFrame = 27; + break; + case 3: + _resetFrame = 29; + break; + default: + _resetFrame = 0; + break; + } + } + + switch (_scene->_activeAnimation->getCurrentFrame()) { + case 26: + case 28: + case 31: + _resetFrame = 0; + break; + } + } else { + if ((_scene->_activeAnimation->getCurrentFrame() == 36) && (!_throttleGone)) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _throttleGone = true; + } + + if (_scene->_activeAnimation->getCurrentFrame() == 39) { + _movingThrottle = false; + switch (_throttleCounter) { + case 1: + break; + case 3: + _scene->_sequences.addTimer(130, 120); + break; + } + } + + if (!_movingThrottle) { + ++_throttleCounter; + _movingThrottle = true; + if (_throttleCounter < 4) { + _resetFrame = 34; + } else { + _messWithThrottle = false; + _throttleCounter = 0; + _game._player._stepEnabled = true; + } + } + } + + if (_game._trigger == 120) { + _vm->_dialogs->show(80422); + } + + if (_game._trigger == 110) { + _vm->_dialogs->show(80426); + } + + if (_pullThrottleReally) { + _resetFrame = 32; + _pullThrottleReally = false; + } + + if (_resetFrame >= 0) { + if (_resetFrame != _scene->_activeAnimation->getCurrentFrame()) { + _scene->_activeAnimation->setCurrentFrame(_resetFrame); + _resetFrame = -1; + } + } + + if (_game._trigger == 90) { + _scene->_nextSceneId = 803; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 72) && !_alreadyPop) { + _vm->_sound->command(21); + _alreadyPop = true; + } + + if ((_scene->_activeAnimation->getCurrentFrame() == 80) && !_alreadyOrgan) { + _vm->_sound->command(22); + _alreadyOrgan = true; + } +} + +/*------------------------------------------------------------------------*/ + +void Scene805::setup() { + setPlayerSpritesPrefix(); + setAAName(); + _scene->addActiveVocab(VERB_REMOVE); + _scene->addActiveVocab(NOUN_TARGET_MODULE); + _scene->addActiveVocab(NOUN_SHIELD_MODULATOR); +} + +void Scene805::enter() { + _game._player._visible = false; + _scene->_userInterface.setup(kInputLimitedSentences); + + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('a', 1)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('a', 2)); + + if (_globals[kShieldModInstalled]) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + } + + if (_globals[kTargetModInstalled]) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, false); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + } + + sceneEntrySound(); +} + +void Scene805::step() { + if (_game._trigger == 70) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, false); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 25); + int idx = _scene->_dynamicHotspots.add(NOUN_SHIELD_MODULATOR, VERB_REMOVE, _globals._sequenceIndexes[1], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + _globals[kShieldModInstalled] = true; + _game._objects.setRoom(OBJ_SHIELD_MODULATOR, NOWHERE); + _game._player._stepEnabled = true; + _vm->_sound->command(24); + } + + if (_game._trigger == 80) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, false); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 12); + int idx = _scene->_dynamicHotspots.add(NOUN_TARGET_MODULE, VERB_REMOVE, _globals._sequenceIndexes[2], Common::Rect(0, 0, 0, 0)); + _scene->_dynamicHotspots.setPosition(idx, Common::Point(0, 0), FACING_DUMMY); + _globals[kTargetModInstalled] = true; + _game._objects.setRoom(OBJ_TARGET_MODULE, NOWHERE); + _game._player._stepEnabled = true; + _vm->_sound->command(24); + } + + if (_game._trigger == 71) { + _scene->_hotspots.activate(OBJ_SHIELD_MODULATOR, true); + _globals[kShieldModInstalled] = false; + _game._objects.addToInventory(OBJ_SHIELD_MODULATOR); + _game._player._stepEnabled = true; + } + + if (_game._trigger == 81) { + _scene->_hotspots.activate(OBJ_TARGET_MODULE, true); + _globals[kTargetModInstalled] = false; + _game._objects.addToInventory(OBJ_TARGET_MODULE); + _game._player._stepEnabled = true; + } +} + +void Scene805::preActions() { + _game._player._needToWalk = false; +} + +void Scene805::actions() { + if (_action.isAction(VERB_EXIT, NOUN_SERVICE_PANEL)) + _scene->_nextSceneId = 804; + else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && _game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && _game._objects.isInInventory(OBJ_TARGET_MODULE)) { + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_REMOVE, NOUN_SHIELD_MODULATOR) && _globals[kShieldModInstalled]) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[1] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[1], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[1], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_REMOVE, NOUN_TARGET_MODULE) && _globals[kTargetModInstalled]) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _game._triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _globals._sequenceIndexes[2] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[2], false, 7, 1, 0, 0); + _scene->_sequences.setAnimRange(_globals._sequenceIndexes[2], -1, -2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[2], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + _game._player._stepEnabled = false; + } else if (_action.isAction(VERB_INSTALL, NOUN_SHIELD_MODULATOR) && !_game._objects.isInInventory(OBJ_SHIELD_MODULATOR)) + _vm->_dialogs->show(80511); + else if (_action.isAction(VERB_INSTALL, NOUN_TARGET_MODULE) && !_game._objects.isInInventory(OBJ_TARGET_MODULE)) + _vm->_dialogs->show(80510); + else if (_action.isAction(VERB_REMOVE, NOUN_LIFE_SUPPORT_MODULE)) + _vm->_dialogs->show(80512); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +void Scene807::setup() { + _game._player._spritesPrefix = ""; + // The original was calling Scene8xx::setAAName() + _game._aaName = Resources::formatAAName(5); +} + +void Scene807::enter() { + if (_globals[kSexOfRex] == REX_FEMALE) + _handSpriteId = _scene->_sprites.addSprites("*ROXHAND"); + else + _handSpriteId = _scene->_sprites.addSprites("*REXHAND"); + + teleporterEnter(); + + // The original uses Scene8xx::SceneEntrySound() + if (!_vm->_musicFlag) + _vm->_sound->command(2); + else + _vm->_sound->command(20); +} + +void Scene807::step() { + teleporterStep(); +} + +void Scene807::actions() { + if (teleporterActions()) { + _action._inProgress = false; + return; + } + + if (_action.isAction(VERB_LOOK, NOUN_VIEWPORT)) + _vm->_dialogs->show(80710); + else if (_action.isAction(VERB_PEER_THROUGH, NOUN_VIEWPORT)) + _vm->_dialogs->show(80710); + else if (_action.isAction(VERB_LOOK, NOUN_KEYPAD) && _action.isAction(VERB_INSPECT, NOUN_KEYPAD)) + _vm->_dialogs->show(80711); + else if (_action.isAction(VERB_LOOK, NOUN_DISPLAY)) + _vm->_dialogs->show(80712); + else if (_action.isAction(VERB_LOOK, NOUN_1_KEY) || _action.isAction(VERB_LOOK, NOUN_2_KEY) + || _action.isAction(VERB_LOOK, NOUN_3_KEY) || _action.isAction(VERB_LOOK, NOUN_4_KEY) + || _action.isAction(VERB_LOOK, NOUN_5_KEY) || _action.isAction(VERB_LOOK, NOUN_6_KEY) + || _action.isAction(VERB_LOOK, NOUN_7_KEY) || _action.isAction(VERB_LOOK, NOUN_8_KEY) + || _action.isAction(VERB_LOOK, NOUN_9_KEY) || _action.isAction(VERB_LOOK, NOUN_0_KEY) + || _action.isAction(VERB_LOOK, NOUN_SMILE_KEY) || _action.isAction(VERB_LOOK, NOUN_FROWN_KEY)) + _vm->_dialogs->show(80713); + else if (_action.isAction(VERB_LOOK, NOUN_DEVICE) && _action._lookFlag) + _vm->_dialogs->show(80714); + else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene808::Scene808(MADSEngine *vm) : Scene8xx(vm) { + _goingTo803 = false; +} + +void Scene808::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_goingTo803); +} + +void Scene808::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene808::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + + _globals._spriteIndexes[4] = _scene->_sprites.addSprites ("*REXHAND"); + _globals._spriteIndexes[1] = _scene->_sprites.addSprites(formAnimName('b', 0)); + _globals._spriteIndexes[2] = _scene->_sprites.addSprites(formAnimName('b', 1)); + _globals._spriteIndexes[3] = _scene->_sprites.addSprites(formAnimName('b', 2)); + + if (_globals[kTopButtonPushed]) + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + else + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + + _goingTo803 = false; + + if (_globals[kCameFromCut] && _globals[kCutX] != 0) { + _globals[kCutX] = 0; + _globals[kCameFromCut] = false; + _globals[kReturnFromCut] = false; + _globals[kBeamIsUp] = false; + _globals[kForceBeamDown] = false; + _globals[kDontRepeat] = false; + } else if ((_scene->_priorSceneId == 803) && _globals[kReturnFromCut]){ + _globals[kDontRepeat] = false; + _globals[kBeamIsUp] = true; + _globals[kAntigravClock] = _scene->_frameStartTime; + _globals[kAntigravTiming] = _scene->_frameStartTime; + _globals[kForceBeamDown] = false; + _globals[kReturnFromCut] = false; + } + + _globals[kBetweenRooms] = false; + + if (_globals[kBeamIsUp]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + } + + sceneEntrySound(); +} + +void Scene808::actions() { + if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + break; + + case 70: + if (!_globals[kBeamIsUp] && !_globals[kTopButtonPushed]) { + _globals._sequenceIndexes[3] = _scene->_sequences.startCycle(_globals._spriteIndexes[3], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[3], 8); + _goingTo803 = true; + _vm->_sound->command(20); + _vm->_sound->command(25); + } + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 71); + break; + + case 71: + _game._player._stepEnabled = true; + if (_goingTo803 && !_globals[kTopButtonPushed]) { + _goingTo803 = false; + _globals[kReturnFromCut] = true; + _scene->_nextSceneId = 803; + } + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + break; + case 90: + if (_globals[kTopButtonPushed]) { + _scene->_sequences.remove(_globals._sequenceIndexes[1]); + _globals._sequenceIndexes[2] = _scene->_sequences.startCycle(_globals._spriteIndexes[2], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[2], 8); + _vm->_sound->command(20); + } + _globals[kTopButtonPushed] = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 91); + break; + + case 91: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_2)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + if (!_globals[kTopButtonPushed]) { + _scene->_sequences.remove(_globals._sequenceIndexes[2]); + _globals._sequenceIndexes[1] = _scene->_sequences.startCycle(_globals._spriteIndexes[1], false, 1); + _scene->_sequences.setDepth(_globals._sequenceIndexes[1], 8); + _vm->_sound->command(20); + } + _globals[kTopButtonPushed] = true; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 1, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(248, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 81); + break; + + case 81: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_START_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(168, 211)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 70); + break; + + case 70: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_REMOTE_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 163)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 80); + break; + + case 80: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_PRESS, NOUN_TIMER_BUTTON_1)) { + switch (_game._trigger) { + case 0: + _game._player._stepEnabled = false; + _globals._sequenceIndexes[4] = _scene->_sequences.startReverseCycle(_globals._spriteIndexes[4], false, 4, 2, 0, 0); + _scene->_sequences.setPosition(_globals._sequenceIndexes[4], Common::Point(172, 186)); + _scene->_sequences.setDepth(_globals._sequenceIndexes[4], 2); + _scene->_sequences.addSubEntry(_globals._sequenceIndexes[4], SEQUENCE_TRIGGER_EXPIRE, 0, 90); + break; + + case 90: + _game._player._stepEnabled = true; + break; + + default: + break; + } + } else if (_action.isAction(VERB_EXIT, NOUN_PANEL)) { + _scene->_nextSceneId = 801; + _globals[kBetweenRooms] = true; + } else + return; + + _action._inProgress = false; +} + +/*------------------------------------------------------------------------*/ + +Scene810::Scene810(MADSEngine *vm) : Scene8xx(vm) { + _moveAllowed = false; +} + +void Scene810::synchronize(Common::Serializer &s) { + Scene8xx::synchronize(s); + + s.syncAsByte(_moveAllowed); +} + +void Scene810::setup() { + setPlayerSpritesPrefix(); + setAAName(); +} + +void Scene810::enter() { + _scene->_userInterface.setup(kInputLimitedSentences); + _game._player._visible = false; + _game._player._stepEnabled = false; + _scene->loadAnimation(Resources::formatName(810, 'a', -1, EXT_AA, "")); + _moveAllowed = true; + + sceneEntrySound(); +} + +void Scene810::step() { + if ((_scene->_activeAnimation->getCurrentFrame() == 200) && _moveAllowed) { + _scene->_sequences.addTimer(100, 70); + _moveAllowed = false; + } + + if (_game._trigger == 70) + _scene->_nextSceneId = 804; +} + +/*------------------------------------------------------------------------*/ + +} // End of namespace Nebular +} // End of namespace MADS diff --git a/engines/mads/nebular/nebular_scenes8.h b/engines/mads/nebular/nebular_scenes8.h new file mode 100644 index 0000000000..39e022e31f --- /dev/null +++ b/engines/mads/nebular/nebular_scenes8.h @@ -0,0 +1,165 @@ +/* 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 MADS_NEBULAR_SCENES8_H +#define MADS_NEBULAR_SCENES8_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/nebular/nebular_scenes.h" + +namespace MADS { + +namespace Nebular { + +class Scene8xx : public NebularScene { +protected: + /** + * Initial setup code shared by several scenes + */ + void setPlayerSpritesPrefix(); + + /** + * Initial setup code shared by several scenes + */ + void setAAName(); + + /** + * Common scene enter code used by multiple scenes + */ + void sceneEntrySound(); +public: + Scene8xx(MADSEngine *vm) : NebularScene(vm) {} +}; + +class Scene801 : public Scene8xx{ +private: + bool _walkThroughDoor; + +public: + Scene801(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene802 : public Scene8xx{ +public: + Scene802(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene803 : public Scene8xx{ +public: + Scene803(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene804 : public Scene8xx { +private: + bool _messWithThrottle; + bool _movingThrottle; + bool _throttleGone; + bool _dontPullThrottleAgain; + bool _pullThrottleReally; + bool _alreadyOrgan; + bool _alreadyPop; + uint32 _throttleCounter; + int _resetFrame; + +public: + Scene804(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +class Scene805 : public Scene8xx{ +public: + Scene805(MADSEngine *vm) : Scene8xx(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void preActions(); + virtual void actions(); +}; + +class Scene807 : public SceneTeleporter { +public: + Scene807(MADSEngine *vm) : SceneTeleporter(vm) {} + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions(); +}; + +class Scene808 : public Scene8xx{ +private: + bool _goingTo803; + +public: + Scene808(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void actions(); +}; + +class Scene810 : public Scene8xx{ +private: + bool _moveAllowed; + +public: + Scene810(MADSEngine *vm); + void synchronize(Common::Serializer &s); + + virtual void setup(); + virtual void enter(); + virtual void step(); + virtual void actions() {}; +}; + +} // End of namespace Nebular +} // End of namespace MADS + +#endif /* MADS_NEBULAR_SCENES8_H */ diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp new file mode 100644 index 0000000000..fc2755db2f --- /dev/null +++ b/engines/mads/nebular/sound_nebular.cpp @@ -0,0 +1,3119 @@ +/* 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 "audio/audiostream.h" +#include "audio/decoders/raw.h" +#include "common/algorithm.h" +#include "common/debug.h" +#include "common/memstream.h" +#include "mads/sound.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +namespace Nebular { + +bool AdlibChannel::_channelsEnabled; + +AdlibChannel::AdlibChannel() { + _activeCount = 0; + _field1 = 0; + _field2 = 0; + _field3 = 0; + _field4 = 0; + _sampleIndex = 0; + _volume = 0; + _field7 = 0; + _field8 = 0; + _field9 = 0; + _fieldA = 0; + _fieldB = 0; + _fieldC = 0; + _fieldD = 0; + _fieldE = 0; + _ptr1 = nullptr; + _pSrc = nullptr; + _ptr3 = nullptr; + _ptr4 = nullptr; + _field17 = 0; + _field19 = 0; + _soundData = nullptr; + _field1D = 0; + _field1E = 0; + _field1F = 0; + + _field20 = 0; +} + +void AdlibChannel::reset() { + _activeCount = 0; + _field1 = 0; + _field2 = 0; + _field3 = 0; +} + +void AdlibChannel::enable(int flag) { + if (_activeCount) { + _fieldE = flag; + + // WORKAROUND: Original set _soundData pointer to flag. Since this seems + // just intended to invalidate any prior pointer, I've replaced it with + // a simple null pointer + _soundData = nullptr; + } + + _channelsEnabled = true; +} + +void AdlibChannel::setPtr2(byte *pData) { + _pSrc = pData; + _field2 = 0xFF; + _fieldA = 1; + _field9 = 1; +} + +void AdlibChannel::load(byte *pData) { + _ptr1 = _pSrc = _ptr3 = pData; + _ptr4 = _soundData = pData; + _fieldA = 0xFF; + _activeCount = 1; + _fieldD = 64; + _field1 = 0; + _field1F = 0; + _field2 = _field3 = 0; + _volume = _field7 = 0; + _field1D = _field1E = 0; + _fieldE = 0; + _field9 = 0; + _fieldB = 0; + _field17 = 0; + _field19 = 0; +} + +void AdlibChannel::check(byte *nullPtr) { + if (_activeCount && _fieldE) { + if (!_field1E) { + _pSrc = nullPtr; + _fieldE = 0; + } else { + _field2 = 0xFF; + _fieldA = 4; + if (!_field9) + _field9 = 1; + } + } +} + +/*-----------------------------------------------------------------------*/ + +AdlibSample::AdlibSample(Common::SeekableReadStream &s) { + _attackRate = s.readByte(); + _decayRate = s.readByte(); + _sustainLevel = s.readByte(); + _releaseRate = s.readByte(); + _egTyp = s.readByte() != 0; + _ksr = s.readByte() != 0; + _totalLevel = s.readByte(); + _scalingLevel = s.readByte(); + _waveformSelect = s.readByte(); + _freqMultiple = s.readByte(); + _feedback = s.readByte(); + _ampMod = s.readByte() != 0; + _vib = s.readByte(); + _alg = s.readByte(); + _fieldE = s.readByte(); + s.skip(1); + _freqMask = s.readUint16LE(); + _freqBase = s.readUint16LE(); + _field14 = s.readUint16LE(); +} + +/*-----------------------------------------------------------------------*/ + +ASound::ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset) { + // Open up the appropriate sound file + if (!_soundFile.open(filename)) + error("Could not open file - %s", filename.c_str()); + + // Initialize fields + _commandParam = 0; + _activeChannelPtr = nullptr; + _samplePtr = nullptr; + _frameCounter = 0; + _isDisabled = false; + _v1 = 0; + _v2 = 0; + _activeChannelNumber = 0; + _freqMask1 = _freqMask2 = 0; + _freqBase1 = _freqBase2 = 0; + _channelNum1 = _channelNum2 = 0; + _v7 = 0; + _v8 = 0; + _v9 = 0; + _v10 = 0; + _pollResult = 0; + _resultFlag = 0; + _nullData[0] = _nullData[1] = 0; + Common::fill(&_ports[0], &_ports[256], 0); + _stateFlag = false; + _activeChannelReg = 0; + _v11 = 0; + _randomSeed = 1234; + _amDep = _vibDep = _splitPoint = true; + + _samplesTillCallback = 0; + _samplesTillCallbackRemainder = 0; + _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND; + _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND; + + for (int i = 0; i < 11; ++i) { + _channelData[i]._field0 = 0; + _channelData[i]._freqMask = 0; + _channelData[i]._freqBase = 0; + _channelData[i]._field6 = 0; + } + + AdlibChannel::_channelsEnabled = false; + + // Store passed parameters, and setup OPL + _dataOffset = dataOffset; + _mixer = mixer; + _opl = OPL::Config::create(); + assert(_opl); + + _opl->init(getRate()); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, + Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + + // Initialize the Adlib + adlibInit(); + + // Reset the adlib + command0(); +} + +ASound::~ASound() { + Common::List<CachedDataEntry>::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) + delete[] (*i)._data; + + _mixer->stopHandle(_soundHandle); + delete _opl; +} + +void ASound::adlibInit() { + write(4, 0x60); + write(4, 0x80); + write(2, 0xff); + write(4, 0x21); + write(4, 0x60); + write(4, 0x80); +} + +int ASound::stop() { + command0(); + int result = _pollResult; + _pollResult = 0; + return result; +} + +int ASound::poll() { + // Update any playing sounds + update(); + + // Return result + int result = _pollResult; + _pollResult = 0; + return result; +} + +void ASound::noise() { + int randomVal = getRandomNumber(); + + if (_v1) { + setFrequency(_channelNum1, ((randomVal ^ 0xFFFF) & _freqMask1) + _freqBase1); + } + + if (_v2) { + setFrequency(_channelNum2, (randomVal & _freqMask2) + _freqBase2); + } +} + +void ASound::write(int reg, int val) { + _queue.push(RegisterValue(reg, val)); +} + +int ASound::write2(int state, int reg, int val) { + // TODO: Original has a state parameter, not used when in Adlib mode? + _ports[reg] = val; + write(reg, val); + return state; +} + +void ASound::flush() { + Common::StackLock slock(_driverMutex); + + while (!_queue.empty()) { + RegisterValue v = _queue.pop(); + _opl->writeReg(v._regNum, v._value); + } +} + +void ASound::channelOn(int reg, int volume) { + write2(8, reg, (_ports[reg] & 0xC0) | (volume & 0x3F)); +} + +void ASound::channelOff(int reg) { + write2(8, reg, _ports[reg] | 0x3F); +} + +void ASound::resultCheck() { + if (_resultFlag != 1) { + _resultFlag = 1; + _pollResult = 1; + } +} + +byte *ASound::loadData(int offset, int size) { + // First scan for an existing copy + Common::List<CachedDataEntry>::iterator i; + for (i = _dataCache.begin(); i != _dataCache.end(); ++i) { + CachedDataEntry &e = *i; + if (e._offset == offset) + return e._data; + } + + // No existing entry found, so load up data and store as a new entry + CachedDataEntry rec; + rec._offset = offset; + rec._data = new byte[size]; + _soundFile.seek(_dataOffset + offset); + _soundFile.read(rec._data, size); + _dataCache.push_back(rec); + + // Return the data + return rec._data; +} + +void ASound::playSound(int offset, int size) { + // Load the specified data block + playSoundData(loadData(offset, size)); +} + +void ASound::playSoundData(byte *pData, int startingChannel) { + // Scan for a high level free channel + for (int i = startingChannel; i < ADLIB_CHANNEL_COUNT; ++i) { + if (!_channels[i]._activeCount) { + _channels[i].load(pData); + return; + } + } + + // None found, do a secondary scan for an interruptable channel + for (int i = ADLIB_CHANNEL_COUNT - 1; i >= startingChannel; --i) { + if (_channels[i]._fieldE == 0xFF) { + _channels[i].load(pData); + return; + } + } +} + +bool ASound::isSoundActive(byte *pData) { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) { + if (_channels[i]._activeCount && _channels[i]._soundData == pData) + return true; + } + + return false; +} + +void ASound::setFrequency(int channel, int freq) { + write2(8, 0xA0 + channel, freq & 0xFF); + write2(8, 0xB0 + channel, (freq >> 8) | 0x20); +} + +int ASound::getRandomNumber() { + int v = 0x9248 + (int)_randomSeed; + _randomSeed = ((v >> 3) | (v << 13)) & 0xFFFF; + return _randomSeed; +} + +void ASound::update() { + getRandomNumber(); + if (_isDisabled) + return; + + ++_frameCounter; + pollChannels(); + checkChannels(); + + if (_v1 == _v2) { + if (_resultFlag != -1) { + _resultFlag = -1; + _pollResult = -1; + } + } else { + if (_v1) { + _freqBase1 += _v7; + if (!--_v1) { + if (!_v2 || _channelNum1 != _channelNum2) { + write2(8, 0xA0 + _channelNum1, 0); + write2(8, 0xB0 + _channelNum1, 0); + } + } + } + + if (_v2) { + _freqBase2 += _v8; + if (!--_v2) { + if (!_v1 || _channelNum2 != _channelNum1) { + write2(8, 0xA0 + _channelNum2, 0); + write2(8, 0xB0 + _channelNum2, 0); + } + } + } + } +} + +void ASound::pollChannels() { + _activeChannelNumber = 0; + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) { + _activeChannelPtr = &_channels[i]; + pollActiveChannel(); + } +} + +void ASound::checkChannels() { + if (AdlibChannel::_channelsEnabled) { + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].check(_nullData); + } +} + +void ASound::pollActiveChannel() { + AdlibChannel *chan = _activeChannelPtr; + + if (chan->_activeCount) { + if (chan->_field8 > 0 && --chan->_field8 == 0) + updateOctave(); + + bool updateFlag = true; + if (--_activeChannelPtr->_activeCount <= 0) { + for (;;) { + byte *pSrc = chan->_pSrc; + if (!chan->_ptr1) { + warning("pollActiveChannel(): No data found for sound channel"); + break; + } + if (!(*pSrc & 0x80) || (*pSrc <= 0xF0)) { + if (updateFlag) + updateActiveChannel(); + + chan->_field4 = *pSrc++; + chan->_activeCount = *pSrc++; + chan->_pSrc += 2; + + if (!chan->_field4 || !chan->_activeCount) { + updateOctave(); + } else { + chan->_field8 = chan->_activeCount - chan->_field7; + updateChannelState(); + } + + // Break out of processing loop + break; + } else { + updateFlag = false; + + switch ((~*pSrc) & 0xF) { + case 0: + if (!chan->_field17) { + if (*++pSrc == 0) { + chan->_pSrc += 2; + chan->_ptr3 = chan->_pSrc; + chan->_field17 = 0; + } else { + chan->_field17 = *pSrc; + chan->_pSrc = chan->_ptr3; + } + } else if (--chan->_field17) { + chan->_pSrc = chan->_ptr3; + } else { + chan->_pSrc += 2; + chan->_ptr3 = chan->_pSrc; + } + break; + + case 1: + if (!chan->_field19) { + if (*++pSrc == 0) { + chan->_pSrc += 2; + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + chan->_field17 = 0; + chan->_field19 = 0; + } else { + chan->_field19 = *pSrc; + chan->_pSrc = chan->_ptr4; + chan->_ptr3 = chan->_ptr4; + } + } else if (--chan->_field19) { + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + } else { + chan->_pSrc += 2; + chan->_ptr4 = chan->_pSrc; + chan->_ptr3 = chan->_pSrc; + } + break; + + case 2: + // Loop sound data + chan->_field1 = 0; + chan->_field2 = chan->_field3 = 0; + chan->_volume = chan->_field7 = 0; + chan->_field1D = chan->_field1E = 0; + chan->_field8 = 0; + chan->_field9 = 0; + chan->_fieldB = 0; + chan->_field17 = 0; + chan->_field19 = 0; + chan->_fieldD = 0x40; + chan->_ptr1 = chan->_soundData; + chan->_pSrc = chan->_soundData; + chan->_ptr3 = chan->_soundData; + chan->_ptr4 = chan->_soundData; + + chan->_pSrc += 2; + break; + + case 3: + chan->_sampleIndex = *++pSrc; + chan->_pSrc += 2; + loadSample(chan->_sampleIndex); + break; + + case 4: + chan->_field7 = *++pSrc; + chan->_pSrc += 2; + break; + + case 5: + chan->_field1 = *++pSrc; + chan->_pSrc += 2; + break; + + case 6: + ++pSrc; + if (chan->_fieldE) { + chan->_pSrc += 2; + } else { + chan->_volume = *pSrc >> 1; + updateFlag = true; + chan->_pSrc += 2; + } + break; + + case 7: + ++pSrc; + if (!chan->_fieldE) { + chan->_fieldA = *pSrc; + chan->_field2 = *++pSrc; + chan->_field9 = 1; + } + + chan->_pSrc += 3; + break; + + case 8: + chan->_field1D = *++pSrc; + chan->_pSrc += 2; + break; + + case 9: { + int v1 = *++pSrc; + ++pSrc; + int v2 = (v1 - 1) & getRandomNumber(); + int v3 = pSrc[v2]; + int v4 = pSrc[v1]; + + pSrc[v4 + v1 + 1] = v3; + chan->_pSrc += v1 + 3; + break; + } + + case 10: + ++pSrc; + if (chan->_fieldE) { + chan->_pSrc += 2; + } else { + chan->_field1E = *pSrc >> 1; + updateFlag = true; + chan->_pSrc += 2; + } + break; + + case 11: + chan->_fieldD = *++pSrc; + updateFlag = true; + chan->_pSrc += 2; + break; + + case 12: + chan->_fieldC = *++pSrc; + chan->_field3 = *++pSrc; + chan->_fieldB = 1; + chan->_pSrc += 2; + break; + + case 13: + ++pSrc; + chan->_pSrc += 2; + break; + + case 14: + chan->_field1F = *++pSrc; + chan->_pSrc += 2; + break; + + default: + break; + } + } + } + } + + if (chan->_field1) + updateFNumber(); + + updateFlag = false; + if (chan->_field9 || chan->_fieldB) { + if (!--chan->_field9) { + chan->_field9 = chan->_fieldA; + if (chan->_field2) { + int8 newVal = (int8)chan->_field2 + (int8)chan->_field1E; + if (newVal < 0) { + chan->_field9 = 0; + newVal = 0; + } else if (newVal > 63) { + chan->_field9 = 0; + newVal = 63; + } + + chan->_field1E = newVal; + updateFlag = true; + } + } + + if (!--chan->_fieldB) { + chan->_fieldB = chan->_fieldC; + if (chan->_field3) { + chan->_fieldD = chan->_field3; + updateFlag = true; + } + } + + if (updateFlag) + updateActiveChannel(); + } + } + + ++_activeChannelNumber; +} + +void ASound::updateOctave() { + int reg = 0xB0 + _activeChannelNumber; + write2(8, reg, _ports[reg] & 0xDF); +} + +static int _vList1[] = { + 0x200, 0x21E, 0x23F, 0x261, 0x285, 0x2AB, + 0x2D4, 0x2FF, 0x32D, 0x35D, 0x390, 0x3C7 +}; + +void ASound::updateChannelState() { + updateActiveChannel(); + + if (_channelData[_activeChannelNumber]._field0) { + if (_channelNum1 == _activeChannelNumber) + _stateFlag = 0; + if (_channelNum2 == _activeChannelNumber) + _stateFlag = 1; + + if (!_stateFlag) { + _stateFlag = 1; + if (_v1) + write2(8, 0xB0 + _channelNum1, _ports[0xB0 + _channelNum1] & 0xDF); + + _channelNum1 = _activeChannelNumber; + _v1 = _channelData[_channelNum1]._field0; + _freqMask1 = _channelData[_channelNum1]._freqMask; + _freqBase1 = _channelData[_channelNum1]._freqBase; + _v7 = _channelData[_channelNum1]._field6; + } else { + _stateFlag = 0; + if (_v2) + write2(8, 0xB0 + _channelNum2, _ports[0xB0 + _channelNum2] & 0xDF); + + _channelNum2 = _activeChannelNumber; + _v2 = _channelData[_channelNum2]._field0; + _freqMask2 = _channelData[_channelNum2]._freqMask; + _freqBase2 = _channelData[_channelNum2]._freqBase; + _v8 = _channelData[_channelNum2]._field6; + } + + resultCheck(); + } else { + int reg = 0xA0 + _activeChannelNumber; + int vTimes = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) / 12; + int vOffset = (_activeChannelPtr->_field4 + _activeChannelPtr->_field1F) % 12; + int val = _vList1[vOffset] + _activeChannelPtr->_field1D; + write2(8, reg, val & 0xFF); + + reg += 0x10; + write2(8, reg, (_ports[reg] & 0x20) | (vTimes << 2) | (val >> 8)); + + write2(8, reg, _ports[reg] | 0x20); + } +} + +static const int outputIndexes[] = { + 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17 +}; +static const int outputChannels[] = { + 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 0 +}; +static const int volumeList[] = { + 0x3F, 0x3F, 0x36, 0x31, 0x2D, 0x2A, 0x28, 0x26, 0x24, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, + 0x1B, 0x1A, 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, + 0x11, 0x11, 0x10, 0x10, 0x0F, 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0B, 0x0A, 0x0A, + 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void ASound::updateActiveChannel() { + int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]]; + int portVal = _ports[reg] & 0xFFC0; + int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_field1E, 0, 63); + + // Note: Original had a whole block not seeming to be used, since the initialisation + // sets a variable to 5660h, and doesn't change it, so the branch is never taken + int val = CLIP(newVolume - volumeList[_activeChannelPtr->_fieldD], 0, 63); + val = (63 - val) | portVal; + + int val2 = CLIP(newVolume - volumeList[-(_activeChannelPtr->_fieldD - 127)], 0, 63); + val2 = (63 - val2) | portVal; + write2(0, reg, val); + write2(2, reg, val2); +} + +void ASound::loadSample(int sampleIndex) { + _activeChannelReg = 0xB0 + _activeChannelNumber; + write2(8, _activeChannelReg, _ports[_activeChannelReg] & 0xDF); + + _activeChannelReg = _activeChannelNumber; + _samplePtr = &_samples[sampleIndex * 2]; + _v11 = outputChannels[outputIndexes[_activeChannelReg * 2]]; + processSample(); + + AdlibChannelData &cd = _channelData[_activeChannelNumber]; + cd._field6 = _samplePtr->_field14; + cd._freqBase = _samplePtr->_freqBase; + cd._freqMask = _samplePtr->_freqMask; + cd._field0 = _samplePtr->_fieldE; + + _samplePtr = &_samples[sampleIndex * 2 + 1]; + _v11 = outputChannels[outputIndexes[_activeChannelReg * 2 + 1]]; + processSample(); +} + +void ASound::processSample() { + // Write out vib flags and split point + write2(8, 0x40 + _v11, 0x3F); + int depthRhythm = (_ports[0xBD] & 0x3F) | (_amDep ? 0x80 : 0) | + (_vibDep ? 0x40 : 0); + write2(8, 0xBD, depthRhythm); + write2(8, 8, _splitPoint ? 0x40 : 0); + + // Write out feedback & Alg + int val = (_samplePtr->_feedback << 1) | (1 - _samplePtr->_alg); + write2(8, 0xC0 + _activeChannelReg, val); + + // Write out attack/decay rate + val = (_samplePtr->_attackRate << 4) | (_samplePtr->_decayRate & 0xF); + write2(8, 0x60 + _v11, val); + + // Write out sustain level/release rate + val = (_samplePtr->_sustainLevel << 4) | (_samplePtr->_releaseRate & 0xF); + write2(8, 0x80 + _v11, val); + + // Write out misc flags + val = (_samplePtr->_ampMod ? 0x80 : 0) | (_samplePtr->_vib ? 0x40 : 0) + | (_samplePtr->_egTyp ? 0x20 : 0) | (_samplePtr->_ksr ? 0x10 : 0) + | (_samplePtr->_freqMultiple & 0xF); + write2(8, 0x20 + _v11, val); + + // Write out waveform select + write2(8, 0xE0 + _v11, _samplePtr->_waveformSelect & 3); + + // Write out total level & scaling level + val = -((_samplePtr->_totalLevel & 0x3F) - 0x3F) | (_samplePtr->_scalingLevel << 6); + write2(8, 0x40 + _v11, val); +} + +void ASound::updateFNumber() { + int loReg = 0xA0 + _activeChannelNumber; + int hiReg = 0xB0 + _activeChannelNumber; + int val1 = (_ports[hiReg] & 0x1F) << 8; + val1 += _ports[loReg] + _activeChannelPtr->_field1; + write2(8, loReg, val1); + + int val2 = (_ports[hiReg] & 0x20) | (val1 >> 8); + write2(8, hiReg, val2); +} + +int ASound::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock slock(_driverMutex); + + int32 samplesLeft = numSamples; + memset(buffer, 0, sizeof(int16) * numSamples); + while (samplesLeft) { + if (!_samplesTillCallback) { + poll(); + flush(); + + _samplesTillCallback = _samplesPerCallback; + _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; + if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) { + _samplesTillCallback++; + _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND; + } + } + + int32 render = MIN<int>(samplesLeft, _samplesTillCallback); + samplesLeft -= render; + _samplesTillCallback -= render; + + _opl->readBuffer(buffer, render); + buffer += render; + } + return numSamples; +} + +int ASound::command0() { + bool isDisabled = _isDisabled; + _isDisabled = true; + + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].reset(); + + _v1 = 0; + _v2 = 0; + _freqMask1 = _freqMask2 = 0; + _freqBase1 = _freqBase2 = 0; + _v7 = 0; + _v8 = 0; + + // Reset Adlib port registers + for (int reg = 0x4F; reg >= 0x40; --reg) + write2(8, reg, 0x3F); + for (int reg = 0xFF; reg >= 0x60; --reg) + write2(8, reg, 0); + for (int reg = 0x3F; reg > 0; --reg) + write2(8, reg, 0); + write2(8, 1, 0x20); + + _isDisabled = isDisabled; + return 0; +} + +int ASound::command1() { + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command2() { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) + _channels[i].setPtr2(_nullData); + return 0; +} + +int ASound::command3() { + for (int i = 0; i < ADLIB_CHANNEL_MIDWAY; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command4() { + for (int i = ADLIB_CHANNEL_MIDWAY; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].setPtr2(_nullData); + return 0; +} + +int ASound::command5() { + for (int i = 5; i < ADLIB_CHANNEL_COUNT; ++i) + _channels[i].enable(0xFF); + return 0; +} + +int ASound::command6() { + _v9 = _v1; + _v1 = 0; + _v10 = _v2; + _v2 = 0; + + channelOff(0x43); + channelOff(0x44); + channelOff(0x45); + channelOff(0x4B); + channelOff(0x4C); + channelOff(0x4D); + channelOff(0x53); + channelOff(0x54); + channelOff(0x55); + + return 0; +} + +int ASound::command7() { + channelOn(0x43, _channels[0]._volume); + channelOn(0x44, _channels[1]._volume); + channelOn(0x45, _channels[2]._volume); + channelOn(0x4B, _channels[3]._volume); + channelOn(0x4C, _channels[4]._volume); + channelOn(0x4D, _channels[5]._volume); + + _v1 = _v9; + _v2 = _v10; + + if (_v9 != _v10) + resultCheck(); + + _isDisabled = 0; + return _v10; +} + +int ASound::command8() { + int result = 0; + for (int i = 0; i < ADLIB_CHANNEL_COUNT; ++i) + result |= _channels[i]._activeCount; + + return result; +} + +/*-----------------------------------------------------------------------*/ + +const ASound1::CommandPtr ASound1::_commandList[42] = { + &ASound1::command0, &ASound1::command1, &ASound1::command2, &ASound1::command3, + &ASound1::command4, &ASound1::command5, &ASound1::command6, &ASound1::command7, + &ASound1::command8, &ASound1::command9, &ASound1::command10, &ASound1::command11, + &ASound1::command12, &ASound1::command13, &ASound1::command14, &ASound1::command15, + &ASound1::command16, &ASound1::command17, &ASound1::command18, &ASound1::command19, + &ASound1::command20, &ASound1::command21, &ASound1::command22, &ASound1::command23, + &ASound1::command24, &ASound1::command25, &ASound1::command26, &ASound1::command27, + &ASound1::command28, &ASound1::command29, &ASound1::command30, &ASound1::command31, + &ASound1::command32, &ASound1::command33, &ASound1::command34, &ASound1::command35, + &ASound1::command36, &ASound1::command37, &ASound1::command38, &ASound1::command39, + &ASound1::command40, &ASound1::command41 +}; + +ASound1::ASound1(Audio::Mixer *mixer) + : ASound(mixer, "asound.001", 0x1520) { + _cmd23Toggle = false; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x12C); + for (int i = 0; i < 98; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound1::command(int commandId, int param) { + if (commandId > 41) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound1::command9() { + playSound(0xC68, 12); + return 0; +} + +int ASound1::command10() { + byte *pData1 = loadData(0x130E, 48); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x133E, 392)); + _channels[2].load(loadData(0x14C6, 46)); + _channels[3].load(loadData(0x14F4, 48)); + } + + return 0; +} + +int ASound1::command11() { + command111213(); + _channels[0]._field1E = 0; + _channels[1]._field1E = 0; + return 0; +} + +int ASound1::command12() { + command111213(); + _channels[0]._field1E = 40; + _channels[1]._field1E = 0; + return 0; +} + +int ASound1::command13() { + command111213(); + _channels[0]._field1E = 40; + _channels[1]._field1E = 50; + return 0; +} + +int ASound1::command14() { + playSound(0x1216, 248); + return 0; +} + +int ASound1::command15() { + byte *pData1 = loadData(0x1524, 152); + if (!isSoundActive(pData1)) { + command1(); + _channels[4].load(pData1); + _channels[5].load(loadData(0x15BC, 94)); + _channels[6].load(loadData(0x161A, 94)); + _channels[7].load(loadData(0x1678, 42)); + _channels[8].load(loadData(0x16A2, 42)); + } + + return 0; +} + +int ASound1::command16() { + playSound(0xC74, 14); + return 0; +} + +int ASound1::command17() { + playSound(0xE9A, 10); + return 0; +} + +int ASound1::command18() { + command1(); + playSound(0xCA6, 20); + return 0; +} + +int ASound1::command19() { + command1(); + playSound(0xCBA, 74); + return 0; +} + +int ASound1::command20() { + byte *pData = loadData(0xD18, 28); + if (!isSoundActive(pData)) + playSoundData(pData); + return 0; +} + +int ASound1::command21() { + playSound(0xD04, 20); + return 0; +} + +int ASound1::command22() { + byte *pData = loadData(0xD34, 10); + pData[6] = (getRandomNumber() & 7) + 85; + + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command23() { + _cmd23Toggle = !_cmd23Toggle; + playSound(_cmd23Toggle ? 0xD3E : 0xD46, 8); + return 0; +} + +int ASound1::command24() { + playSound(0xD4E, 18); + playSound(0xD60, 20); + playSound(0xD74, 14); + return 0; +} + +int ASound1::command25() { + byte *pData = loadData(0xD82, 16); + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command26() { + byte *pData = loadData(0xEEC, 10); + pData[5] = (command2627293032() + 0x7F) & 0xFF; + + if (!isSoundActive(pData)) + _channels[6].load(pData); + + return 0; +} + +int ASound1::command27() { + byte *pData = loadData(0xEE2, 10); + pData[5] = (command2627293032() + 0x40) & 0xFF; + + if (!isSoundActive(pData)) + _channels[7].load(pData); + + return 0; +} + +int ASound1::command28() { + playSound(0xD92, 28); + return 0; +} + +int ASound1::command29() { + byte *pData = loadData(0xC82, 36); + byte v = (command2627293032() + 0x40) & 0xFF; + pData[7] = pData[13] = pData[21] = pData[27] = v; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command30() { + byte *pData = loadData(0xEA6, 16); + pData[7] = (command2627293032() + 0x40) & 0xFF; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command31() { + byte *pData = loadData(0xDAE, 14); + if (!isSoundActive(pData)) + playSoundData(pData); + + return 0; +} + +int ASound1::command32() { + byte *pData = loadData(0xEB4, 46); + int v = command2627293032() + 0x40; + pData[9] = pData[17] = pData[25] = pData[33] = v & 0xFF; + pData[11] = pData[19] = pData[27] = pData[35] = v >> 8; + + if (!isSoundActive(pData)) + playSoundData(pData, 0); + + return 0; +} + +int ASound1::command33() { + playSound(0xDBC, 10); + playSound(0xDC6, 10); + return 0; +} + +int ASound1::command34() { + int v = getRandomNumber() & 0x20; + if (!v) + v = 0x60; + + byte *pData = loadData(0xDD0, 22); + pData[8] = pData[15] = v; + playSoundData(pData); + return 0; +} + +int ASound1::command35() { + playSound(0xDE6, 16); + return 0; +} + +int ASound1::command36() { + playSound(0xE10, 10); + command34(); + + return 0; +} + +int ASound1::command37() { + playSound(0xE1A, 14); + return 0; +} + +int ASound1::command38() { + playSound(0xE28, 114); + return 0; +} + +int ASound1::command39() { + byte *pData1 = loadData(0x16CC, 82); + if (!isSoundActive(pData1)) { + _channels[5].load(pData1); + _channels[6].load(loadData(0x171E, 30)); + _channels[7].load(loadData(0x173C, 40)); + _channels[8].load(loadData(0x1764, 64)); + } + return 0; +} + +int ASound1::command40() { + playSound(0xDF6, 26); + return 0; +} + +int ASound1::command41() { + playSound(0xC32, 34); + playSound(0xC54, 20); + return 0; +} + +void ASound1::command111213() { + byte *pData1 = loadData(0xEF6, 408); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x108E, 266)); + _channels[2].load(loadData(0x1198, 66)); + _channels[2].load(loadData(0x11DA, 60)); + } +} + +int ASound1::command2627293032() { + return (_commandParam > 0x40) ? _commandParam - 0x40 : _commandParam & 0xff00; +} + + +/*-----------------------------------------------------------------------*/ + +const ASound2::CommandPtr ASound2::_commandList[44] = { + &ASound2::command0, &ASound2::command1, &ASound2::command2, &ASound2::command3, + &ASound2::command4, &ASound2::command5, &ASound2::command6, &ASound2::command7, + &ASound2::command8, &ASound2::command9, &ASound2::command10, &ASound2::command11, + &ASound2::command12, &ASound2::command13, &ASound2::command14, &ASound2::command15, + &ASound2::command16, &ASound2::command17, &ASound2::command18, &ASound2::command19, + &ASound2::command20, &ASound2::command21, &ASound2::command22, &ASound2::command23, + &ASound2::command24, &ASound2::command25, &ASound2::command26, &ASound2::command27, + &ASound2::command28, &ASound2::command29, &ASound2::command30, &ASound2::command31, + &ASound2::command32, &ASound2::command33, &ASound2::command34, &ASound2::command35, + &ASound2::command36, &ASound2::command37, &ASound2::command38, &ASound2::command39, + &ASound2::command40, &ASound2::command41, &ASound2::command42, &ASound2::command43 +}; + +ASound2::ASound2(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) { + _command12Param = 0xFD; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x144); + for (int i = 0; i < 164; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound2::command(int commandId, int param) { + if (commandId > 43) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound2::command0() { + _command12Param = 0xFD; + return ASound::command0(); +} + +int ASound2::command9() { + byte *pData1 = loadData(0x1094, 376); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[2].load(loadData(0x123E, 130)); + + command9Randomize(); + _channels[1].load(loadData(0x120C, 50)); + } + return 0; +} + +void ASound2::command9Randomize() { + // Randomization + int v; + while (((v = getRandomNumber()) & 0x3F) > 36) + ; + + byte *pData = loadData(0x120C, 50); + command9Apply(pData, v + 20, -1); + command9Apply(pData + 1, 10 - ((v + 1) / 6), 1); +} + +void ASound2::command9Apply(byte *data, int val, int incr) { + data += 8; + for (int ctr = 0; ctr < 10; ++ctr, data += 4, val += incr) { + *data = val; + } +} + +int ASound2::command10() { + byte *pData1 = loadData(0x12C0, 60); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x12FC, 318)); + _channels[2].load(loadData(0x143A, 110)); + } + + return 0; +} + +int ASound2::command11() { + byte *pData = loadData(0x14A8, 170); + if (!isSoundActive(pData)) { + playSoundData(pData); + playSoundData(loadData(0x1552, 1802)); + playSoundData(loadData(0x1C5C, 716)); + playSoundData(loadData(0x1F28, 106)); + } + + return 0; +} + +int ASound2::command12() { + _command12Param += 26; + byte v = _command12Param & 0x7f; + + byte *pData = loadData(0x4A5E, 38); + pData[5] = pData[20] = v; + playSoundData(pData); + + pData = loadData(0x4A84, 30); + pData[5] = pData[18] = v; + playSoundData(pData); + + return 0; +} + +int ASound2::command13() { + playSoundData(loadData(0x4AA2, 20)); + playSoundData(loadData(0x4AB6, 20)); + + return 0; +} + +int ASound2::command14() { + playSound(0x4ACA, 40); + playSound(0x4AF2, 42); + + return 0; +} + +int ASound2::command15() { + byte *pData1 = loadData(0x1F92, 1074); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x23C4, 1050); + playSound(0x27DE, 58); + playSound(0x2818, 712); + playSound(0x2AE0, 256); + } + + return 0; +} + +int ASound2::command16() { + byte *pData1 = loadData(0x3960, 280); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x3A78, 266); + playSound(0x3B72, 322); + playSound(0x3CC4, 488); + playSound(0x3EAC, 104); + playSound(0x3F14, 104); + } + + return 0; +} + +int ASound2::command17() { + byte *pData1 = loadData(0x3F7C, 432); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x412C, 422); + playSound(0x42D2, 424); + playSound(0x447A, 418); + } + + return 0; +} + +static const int command18_list[16][2] = { + { 0x337C, 28 }, { 0x3398, 26 }, { 0x33B2, 26 }, { 0x33CC, 26 }, + { 0x33E6, 56 }, { 0x341E, 46 }, { 0x344C, 56 }, { 0x3484, 22 }, + { 0x349A, 38 }, { 0x34C0, 62 }, { 0x34FE, 26 }, { 0x3518, 26 }, + { 0x3532, 26 }, { 0x354C, 26 }, { 0x3566, 32 }, { 0x3586, 24 } +}; + +int ASound2::command18() { + if (_channels[3]._activeCount == 0) { + int idx = (getRandomNumber() & 0x1E) >> 1; + byte *pData = loadData(command18_list[idx][0], command18_list[idx][1]); + _channels[3].load(pData); + } + + return 0; +} + +int ASound2::command19() { + byte *pData1 = loadData(0x2BE0, 366); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x2D4E, 460); + playSound(0x2F1A, 266); + playSound(0x3024, 328); + playSound(0x316C, 162); + playSound(0x320E, 366); + } + + return 0; +} + +int ASound2::command20() { + playSound(0x4A36, 40); + + return 0; +} + +int ASound2::command21() { + playSound(0x49DE, 16); + playSound(0x49EE, 16); + playSound(0x49FF, 16); + + return 0; +} + +int ASound2::command22() { + playSound(0x4A0E, 24); + playSound(0x4A26, 16); + + return 0; +} + +int ASound2::command23() { + playSound(0x49B6, 16); + + return 0; +} + +int ASound2::command24() { + playSound(0x49C6, 24); + + return 0; +} + +int ASound2::command25() { + playSound(0x49AC, 10); + + return 0; +} + +int ASound2::command26() { + playSound(0x498A, 14); + playSound(0x4998, 20); + + return 0; +} + +int ASound2::command27() { + playSound(0x4912, 80); + playSound(0x4962, 40); + + return 0; +} + +int ASound2::command28() { + playSound(0x48E8, 28); + playSound(0x4904, 14); + + return 0; +} + +int ASound2::command29() { + playSound(0x48B2, 22); + + return 0; +} + +int ASound2::command30() { + playSound(0x4870, 22); + playSound(0x4886, 22); + playSound(0x489C, 22); + + return 0; +} + +int ASound2::command31() { + playSound(0x482E, 22); + playSound(0x4844, 22); + playSound(0x489C, 22); + + return 0; +} + +int ASound2::command32() { + playSound(0x46E8, 10); + + return 0; +} + +int ASound2::command33() { + playSound(0x46D8, 16); + + return 0; +} + +int ASound2::command34() { + playSound(0x46C8, 16); + + return 0; +} + +int ASound2::command35() { + playSound(0x46B2, 22); + + return 0; +} + +int ASound2::command36() { + playSound(0x4624, 16); + + return 0; +} + +int ASound2::command37() { + playSound(0x4674, 20); + playSound(0x4688, 32); + playSound(0x46A8, 10); + + return 0; +} + +int ASound2::command38() { + byte *pData1 = loadData(0x359E, 202); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x3668, 220); + playSound(0x3744, 124); + playSound(0x37C0, 162); + playSound(0x3862, 78); + playSound(0x38B0, 176); + } + + return 0; +} + +int ASound2::command39() { + byte *pData = loadData(0x466A, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound2::command40() { + playSound(0x4634, 34); + playSound(0x4656, 20); + + return 0; +} + +int ASound2::command41() { + playSound(0x48C8, 32); + + return 0; +} + +int ASound2::command42() { + playSound(0x46F2, 156); + playSound(0x478E, 160); + + return 0; +} + +int ASound2::command43() { + playSound(0x4B1C, 40); + playSound(0x4B44, 41); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound3::CommandPtr ASound3::_commandList[61] = { + &ASound3::command0, &ASound3::command1, &ASound3::command2, &ASound3::command3, + &ASound3::command4, &ASound3::command5, &ASound3::command6, &ASound3::command7, + &ASound3::command8, &ASound3::command9, &ASound3::command10, &ASound3::command11, + &ASound3::nullCommand, &ASound3::command13, &ASound3::command14, &ASound3::command15, + &ASound3::command16, &ASound3::command17, &ASound3::command18, &ASound3::command19, + &ASound3::command20, &ASound3::command21, &ASound3::command22, &ASound3::command23, + &ASound3::command24, &ASound3::command25, &ASound3::command26, &ASound3::command27, + &ASound3::command28, &ASound3::command29, &ASound3::command30, &ASound3::command31, + &ASound3::command32, &ASound3::command33, &ASound3::command34, &ASound3::command35, + &ASound3::command36, &ASound3::command37, &ASound3::command38, &ASound3::command39, + &ASound3::command40, &ASound3::command41, &ASound3::command42, &ASound3::command43, + &ASound3::command44, &ASound3::command45, &ASound3::command46, &ASound3::command47, + &ASound3::nullCommand, &ASound3::command49, &ASound3::command50, &ASound3::command51, + &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand, &ASound3::nullCommand, + &ASound3::nullCommand, &ASound3::command57, &ASound3::nullCommand, &ASound3::command59, + &ASound3::command60 +}; + +ASound3::ASound3(Audio::Mixer *mixer) : ASound(mixer, "asound.003", 0x15B0) { + _command39Flag = false; + + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 192; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound3::command(int commandId, int param) { + if (commandId > 60) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound3::command9() { + AdlibChannel::_channelsEnabled = _commandParam != 0; + + return 0; +} + +int ASound3::command10() { + byte *pData1 = loadData(0x13EA, 254); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0X14E8, 452)); + _channels[2].load(loadData(0x16AC, 396)); + _channels[3].load(loadData(0x1838, 118)); + _channels[4].load(loadData(0x18AE, 74)); + } + + return 0; +} + +int ASound3::command11() { + byte *pData1 = loadData(0x2B84, 596); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x2DD8, 562)); + _channels[2].load(loadData(0x300A, 1694)); + _channels[3].load(loadData(0x36A8, 1100)); + _channels[4].load(loadData(0x3AF4, 420)); + _channels[5].load(loadData(0x3C98, 1516)); + } + + return 0; +} + +int ASound3::command13() { + byte *pData1 = loadData(0x4470, 64); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x44B0, 64); + playSound(0x44F0, 64); + playSound(0x4530, 64); + playSound(0x4570, 64); + playSound(0X45b0, 64); + } + + return 0; +} + +int ASound3::command14() { + byte *pData1 = loadData(0X45F0, 36); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x4614, 36); + playSound(0x4638, 36); + playSound(0x465C, 32); + playSound(0x467C, 76); + playSound(0x46C8, 74); + } + + return 0; +} + +int ASound3::command15() { + _channels[3].load(loadData(0x36A8, 1100)); + _channels[4].load(loadData(0x3AF4, 420)); + _channels[5].load(loadData(0x3C98, 1516)); + + _channels[3]._field20 = 0xDD; + _channels[4]._field20 = 0xDD; + _channels[5]._field20 = 0xDD; + + return 0; +} + +int ASound3::command16() { + byte *pData1 = loadData(0x4712, 398); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x48A0, 354)); + _channels[2].load(loadData(0x4A02, 410)); + _channels[3].load(loadData(0x4B9C, 392)); + } + + return 0; +} + +int ASound3::command17() { + byte *pData1 = loadData(0x18F8, 400); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1A88, 680)); + _channels[2].load(loadData(0x1D30, 478)); + _channels[3].load(loadData(0x1F0E, 1146)); + _channels[4].load(loadData(0x2388, 1006)); + _channels[5].load(loadData(0x2776, 1038)); + } + + return 0; +} + +int ASound3::command18() { + byte *pData1 = loadData(0x4284, 142); + if (!isSoundActive(pData1)) { + command1(); + playSoundData(pData1); + playSound(0x4312, 172); + playSound(0x43BE, 88); + playSound(0x4416, 90); + } + + return 0; +} + +int ASound3::command19() { + playSound(0x4F6, 8); + + return 0; +} + +int ASound3::command20() { + playSound(0x4F1C, 10); + + return 0; +} + +int ASound3::command21() { + playSound(0x4F2E, 8); + + return 0; +} + +int ASound3::command22() { + playSound(0x4F36, 16); + + return 0; +} + +int ASound3::command23() { + playSound(0x4F50, 10); + playSound(0x4F46, 10); + + return 0; +} + +int ASound3::command24() { + // WORKAROUND: Original calls isSoundActive without loading data pointer + byte *pData = loadData(0x4EFC, 12); + if (!isSoundActive(pData)) { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 45) + ; + + pData[6] = v + 19; + playSoundData(pData); + } + + return 0; +} + +int ASound3::command25() { + playSound(0x4EE6, 22); + + return 0; +} + +int ASound3::command26() { + playSound(0x4F5A, 8); + + return 0; +} + +int ASound3::command27() { + playSound(0x4DA2, 34); + playSound(0x4DC4, 20); + + return 0; +} + +int ASound3::command28() { + playSound(0x4F72, 10); + playSound(0x4F72, 10); + + return 0; +} + +int ASound3::command29() { + playSound(0x4F72, 10); + playSound(0x4F72, 10); + + return 0; +} + +int ASound3::command30() { + playSound(0x4E5A, 22); + playSound(0x4E70, 22); + playSound(0x4E86, 22); + + return 0; +} + +int ASound3::command31() { + playSound(0x4F7C, 40); + + return 0; +} + +int ASound3::command32() { + playSound(0x4ED2, 10); + + return 0; +} + +int ASound3::command33() { + playSound(0x4EC2, 16); + + return 0; +} + +int ASound3::command34() { + playSound(0x4EB2, 16); + + return 0; +} + +int ASound3::command35() { + playSound(0x4E9C, 22); + + return 0; +} + +int ASound3::command36() { + playSound(0x4D2C, 16); + + return 0; +} + +int ASound3::command37() { + playSound(0x4E1E, 20); + playSound(0x4E32, 30); + playSound(0x4E50, 10); + + return 0; +} + +int ASound3::command38() { + playSound(0x4FAC, 10); + + return 0; +} + +int ASound3::command39() { + _command39Flag = !_command39Flag; + if (_command39Flag) { + playSound(0x4FD0, 8); + } else { + playSound(0x4FD8, 8); + } + + return 0; +} + +int ASound3::command40() { + _command39Flag = !_command39Flag; + if (_command39Flag) { + playSound(0x4EE0, 8); + } else { + playSound(0x4EE8, 8); + } + + return 0; +} + +int ASound3::command41() { + playSound(0x4F08, 20); + + return 0; +} + +int ASound3::command42() { + playSound(0x4DD8, 28); + playSound(0x4DF4, 42); + + return 0; +} + +int ASound3::command43() { + playSound(0x4FB6, 12); + playSound(0x4FC2, 14); + + return 0; +} + +int ASound3::command44() { + playSound(0x4FFE, 14); + + return 0; +} + +int ASound3::command45() { + playSound(0x500C, 14); + + return 0; +} + +int ASound3::command46() { + playSound(0x4D78, 14); + playSound(0x4D86, 14); + playSound(0x4D94, 14); + + return 0; +} + +int ASound3::command47() { + playSound(0x4D62, 8); + playSound(0x4D6A, 14); + + return 0; +} + +int ASound3::command49() { + playSound(0x4D62, 8); + playSound(0x4D6A, 14); + + return 0; +} + +int ASound3::command50() { + playSound(0x4D3C, 14); + playSound(0x4D4A, 14); + playSound(0x4D58, 10); + + return 0; +} + +int ASound3::command51() { + playSound(0x4FF0, 14); + + return 0; +} + +int ASound3::command57() { + byte *pData = loadData(0x4EDC, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound3::command59() { + playSound(0x4F62, 16); + + return 0; +} + +int ASound3::command60() { + playSound(0x4FA4, 8); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound4::CommandPtr ASound4::_commandList[61] = { + &ASound4::command0, &ASound4::command1, &ASound4::command2, &ASound4::command3, + &ASound4::command4, &ASound4::command5, &ASound4::command6, &ASound4::command7, + &ASound4::command8, &ASound4::nullCommand, &ASound4::command10, &ASound4::nullCommand, + &ASound4::command12, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command19, + &ASound4::command20, &ASound4::command21, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::command24, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command27, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command30, &ASound4::nullCommand, + &ASound4::command32, &ASound4::command33, &ASound4::command34, &ASound4::command35, + &ASound4::command36, &ASound4::command37, &ASound4::command38, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::command43, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, &ASound4::nullCommand, + &ASound4::nullCommand, &ASound4::command57, &ASound4::nullCommand, &ASound4::command59, + &ASound4::command60 +}; + +ASound4::ASound4(Audio::Mixer *mixer) : ASound(mixer, "asound.004", 0x14F0) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 210; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound4::command(int commandId, int param) { + if (commandId > 60) + return 0; + + _commandParam = param; + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound4::command10() { + byte *pData = loadData(0x22AA, 254); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x23A8, 452)); + _channels[2].load(loadData(0x256C, 396)); + _channels[3].load(loadData(0x26F8, 118)); + _channels[4].load(loadData(0x276E, 74)); + } + + return 0; +} + +int ASound4::command12() { + byte *pData = loadData(0x16A8, 550); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x18CE, 442)); + _channels[2].load(loadData(0x1A88, 298)); + _channels[3].load(loadData(0x1BB2, 354)); + _channels[4].load(loadData(0x1D14, 572)); + _channels[4].load(loadData(0x1F50, 560)); + } + + int v = (_commandParam > 0x40) ? _commandParam - 0x40 : 0; + v += 0xB5; + for (int channelNum = 0; channelNum < 6; ++channelNum) + _channels[channelNum]._field20 = v; + + return 0; +} + +int ASound4::command19() { + playSound(0x28EC, 8); + + return 0; +} + +int ASound4::command20() { + playSound(0x28E2, 10); + + return 0; +} + +int ASound4::command21() { + playSound(0x27C0, 8); + + return 0; +} + +int ASound4::command24() { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 45) + ; + + byte *pData = loadData(0x28D6, 12); + pData[6] = v + 19; + playSoundData(pData); + + return 0; +} + +int ASound4::command27() { + playSound(0x27D8, 34); + playSound(0x27FA, 20); + + return 0; +} + +int ASound4::command30() { + playSound(0x284A, 22); + playSound(0x2860, 22); + playSound(0x2876, 22); + + return 0; +} + +int ASound4::command32() { + playSound(0x28C2, 10); + + return 0; +} + +int ASound4::command33() { + playSound(0x28B2, 16); + + return 0; +} + +int ASound4::command34() { + playSound(0x28A2, 16); + + return 0; +} + +int ASound4::command35() { + playSound(0x288C, 22); + + return 0; +} + +int ASound4::command36() { + playSound(0x27C8, 16); + + return 0; +} + +int ASound4::command37() { + playSound(0x280E, 20); + playSound(0x2822, 30); + playSound(0x2840, 10); + + return 0; +} + +int ASound4::command38() { + playSound(0x2904, 10); + + return 0; +} + +int ASound4::command43() { + playSound(0x290E, 12); + playSound(0x291A, 14); + + return 0; +} + +int ASound4::command52() { + byte *pData = loadData(0x23A8, 452); + if (_channels[1]._ptr1 == pData) { + pData = loadData(0x146E, 570); + if (!isSoundActive(pData)) { + _channels[0].load(pData); + _channels[1]._field20 = 0xD8; + _channels[2]._field20 = 0xD8; + } + } + + return 0; +} + +int ASound4::command53() { + method1(); + _channels[0]._field20 = 0; + + return 0; +} + +int ASound4::command54() { + method1(); + _channels[1]._field20 = 0; + _channels[2]._field20 = 0; + + return 0; +} + +int ASound4::command55() { + method1(); + _channels[3]._field20 = 0; + _channels[4]._field20 = 0; + + return 0; +} + +int ASound4::command56() { + method1(); + _channels[5]._field20 = 0; + + return 0; +} + +int ASound4::command57() { + int v = (getRandomNumber() & 7) + 85; + byte *pData = loadData(0x28CC, 10); + pData[6] = v; + playSoundData(pData); + + return 0; +} + +int ASound4::command58() { + byte *pData = loadData(0x146E, 570); + if (_channels[1]._ptr1 == pData) { + _channels[0].load(loadData(0x22AA, 254)); + _channels[1]._field20 = 0; + _channels[2]._field20 = 0; + } + + return 0; +} + +int ASound4::command59() { + playSound(0x28F4, 8); + + return 0; +} + +int ASound4::command60() { + playSound(0x28FC, 8); + + return 0; +} + +void ASound4::method1() { + byte *pData = loadData(0x2180, 58); + if (!isSoundActive(pData)) { + command1(); + + _channels[0].load(pData); + _channels[1].load(loadData(0x21BA, 48)); + _channels[2].load(loadData(0x21EA, 50)); + _channels[3].load(loadData(0x221C, 40)); + _channels[4].load(loadData(0x2244, 28)); + _channels[5].load(loadData(0x2260, 74)); + + for (int channel = 0; channel < 6; ++channel) + _channels[channel]._field20 = 0xB5; + } +} + + +/*-----------------------------------------------------------------------*/ + +const ASound5::CommandPtr ASound5::_commandList[42] = { + &ASound5::command0, &ASound5::command1, &ASound5::command2, &ASound5::command3, + &ASound5::command4, &ASound5::command5, &ASound5::command6, &ASound5::command7, + &ASound5::command8, &ASound5::command9, &ASound5::command10, &ASound5::command11, + &ASound5::command11, &ASound5::command13, &ASound5::command14, &ASound5::command15, + &ASound5::command16, &ASound5::command17, &ASound5::command18, &ASound5::command19, + &ASound5::command20, &ASound5::command21, &ASound5::command22, &ASound5::command23, + &ASound5::command11, &ASound5::command11, &ASound5::command26, &ASound5::command27, + &ASound5::command28, &ASound5::command29, &ASound5::command30, &ASound5::command31, + &ASound5::command32, &ASound5::command33, &ASound5::command34, &ASound5::command35, + &ASound5::command36, &ASound5::command37, &ASound5::command38, &ASound5::command39, + &ASound5::command40, &ASound5::command41 +}; + +ASound5::ASound5(Audio::Mixer *mixer) : ASound(mixer, "asound.002", 0x15E0) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x144); + for (int i = 0; i < 164; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound5::command(int commandId, int param) { + if (commandId > 41) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound5::command9() { + byte *pData = loadData(0x2114, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound5::command10() { + playSound(0x211E, 10); + + return 0; +} + +int ASound5::command11() { + playSound(0x2016, 10); + + return 0; +} + +int ASound5::command13() { + playSound(0x2154, 10); + + return 0; +} + +int ASound5::command14() { + playSound(0x21DC, 22); + + return 0; +} + +int ASound5::command15() { + byte *pData = loadData(0x21DC, 22); + if (_channels[0]._ptr1 == pData) { + pData = loadData(0x1F2, 12); + _channels[0]._soundData = pData; + _channels[0]._field17 = 1; + _channels[0]._field19 = 1; + } + + return 0; +} + +int ASound5::command16() { + playSound(0x214C, 8); + + return 0; +} + +int ASound5::command17() { + playSound(0x2142, 10); + + return 0; +} + +int ASound5::command18() { + playSound(0x21A2, 22); + + return 0; +} + +int ASound5::command19() { + playSound(0x2190, 18); + + return 0; +} + +int ASound5::command20() { + playSound(0x2170, 16); + + return 0; +} + +int ASound5::command21() { + playSound(0x2180, 16); + + return 0; +} + +int ASound5::command22() { + playSound(0x2168, 8); + + return 0; +} + +int ASound5::command23() { + playSound(0x215E, 10); + + return 0; +} + +int ASound5::command26() { + playSound(0x21B8, 12); + + return 0; +} + +int ASound5::command27() { + playSound(0x21C4, 24); + + return 0; +} + +int ASound5::command28() { + playSound(0x2020, 34); + playSound(0x4904, 20); + + return 0; +} + +int ASound5::command29() { + byte *pData = loadData(0x17C, 312); + if (!isSoundActive(pData)) { + command1(); + _channels[0].load(pData); + _channels[1].load(loadData(0x1864, 304)); + _channels[2].load(loadData(0x1994, 222)); + _channels[3].load(loadData(0x1864, 304)); + _channels[4].load(loadData(0x1994, 222)); + } + + return 0; +} + +int ASound5::command30() { + playSound(0x2092, 22); + playSound(0x20A8, 22); + playSound(0x20BE, 22); + + return 0; +} + +int ASound5::command31() { + playSound(0x2128, 22); + playSound(0x2134, 14); + + return 0; +} + +int ASound5::command32() { + playSound(0x210A, 10); + + return 0; +} + +int ASound5::command33() { + playSound(0x20FA, 16); + + return 0; +} + +int ASound5::command34() { + playSound(0x20EA, 16); + + return 0; +} + +int ASound5::command35() { + playSound(0x20D4, 22); + + return 0; +} + +int ASound5::command36() { + playSound(0x2006, 16); + + return 0; +} + +int ASound5::command37() { + playSound(0x2056, 20); + playSound(0x206A, 30); + playSound(0x2088, 10); + + return 0; +} + +int ASound5::command38() { + byte *pData1 = loadData(0x14F2, 570); + if (_channels[3]._ptr1 == pData1) { + _channels[3].load(loadData(0x1A72, 522)); + _channels[3].load(loadData(0x1C7C, 874)); + } + + return 0; +} + +int ASound5::command39() { + playSound(0x1FEE, 8); + + return 0; +} + +int ASound5::command40() { + playSound(0x1FF6, 16); + + return 0; +} + +int ASound5::command41() { + byte *pData1 = loadData(0x14F2, 570); + if (!isSoundActive(pData1)) { + byte *pData2 = loadData(0x1A72, 522); + if (_channels[3]._ptr1 == pData2) { + _channels[3].load(pData1); + _channels[4].load(loadData(0x1FE6, 8)); + } + } + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound6::CommandPtr ASound6::_commandList[30] = { + &ASound6::command0, &ASound6::command1, &ASound6::command2, &ASound6::command3, + &ASound6::command4, &ASound6::command5, &ASound6::command6, &ASound6::command7, + &ASound6::command8, &ASound6::command9, &ASound6::command10, &ASound6::command11, + &ASound6::command11, &ASound6::command13, &ASound6::command14, &ASound6::command15, + &ASound6::command16, &ASound6::command17, &ASound6::command18, &ASound6::command19, + &ASound6::command20, &ASound6::command21, &ASound6::command22, &ASound6::command23, + &ASound6::command11, &ASound6::command11, &ASound6::nullCommand, &ASound6::nullCommand, + &ASound6::nullCommand, &ASound6::command29 +}; + +ASound6::ASound6(Audio::Mixer *mixer) : ASound(mixer, "asound.006", 0x1390) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 200; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound6::command(int commandId, int param) { + if (commandId > 29) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound6::command9() { + byte *pData = loadData(0x2194, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound6::command10() { + playSound(0x2224, 24); + + return 0; +} + +int ASound6::command11() { + playSound(0x2202, 34); + + return 0; +} + +int ASound6::command12() { + playSound(0x2246, 8); + + return 0; +} + +int ASound6::command13() { + playSound(0x2298, 28); + + return 0; +} + +int ASound6::command14() { + playSound(0x22B4, 27); + + return 0; +} + +int ASound6::command15() { + playSound(0x219E, 12); + + return 0; +} + +int ASound6::command16() { + playSound(0x21AA, 22); + playSound(0x21C0, 12); + + return 0; +} + +int ASound6::command17() { + playSound(0x21CC, 54); + + return 0; +} + +int ASound6::command18() { + playSound(0x2270, 16); + + return 0; +} + +int ASound6::command19() { + playSound(0x2280, 16); + + return 0; +} + +int ASound6::command20() { + playSound(0x223C, 10); + + return 0; +} + +int ASound6::command21() { + playSound(0x224E, 34); + + return 0; +} + +int ASound6::command22() { + playSound(0x2290, 8); + + return 0; +} + +int ASound6::command23() { + playSound(0x215E, 34); + playSound(0x2180, 20); + + return 0; +} + +int ASound6::command24() { + byte *pData1 = loadData(0x1D54, 540); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1F70, 52)); + _channels[2].load(loadData(0x1FA4, 430)); + } + + return 0; +} + +int ASound6::command25() { + playSound(0x2152, 12); + + return 0; +} + +int ASound6::command29() { + byte *pData1 = loadData(0x149A, 312); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x15D2, 304)); + _channels[2].load(loadData(0x1702, 222)); + _channels[3].load(loadData(0x17E0, 522)); + _channels[4].load(loadData(0x19EA, 874)); + } + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound7::CommandPtr ASound7::_commandList[38] = { + &ASound7::command0, &ASound7::command1, &ASound7::command2, &ASound7::command3, + &ASound7::command4, &ASound7::command5, &ASound7::command6, &ASound7::command7, + &ASound7::command8, &ASound7::command9, &ASound7::nullCommand, &ASound7::nullCommand, + &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::nullCommand, &ASound7::command15, + &ASound7::command16, &ASound7::command16, &ASound7::command18, &ASound7::command19, + &ASound7::command20, &ASound7::command21, &ASound7::command22, &ASound7::command23, + &ASound7::command24, &ASound7::command25, &ASound7::command26, &ASound7::command27, + &ASound7::command28, &ASound7::nullCommand, &ASound7::command30, &ASound7::nullCommand, + &ASound7::command32, &ASound7::command33, &ASound7::command34, &ASound7::command35, + &ASound7::command36, &ASound7::command37 +}; + +ASound7::ASound7(Audio::Mixer *mixer) : ASound(mixer, "asound.007", 0x1460) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 214; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound7::command(int commandId, int param) { + if (commandId > 37) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound7::command9() { + byte *pData1 = loadData(0x2992, 122); + if (!isSoundActive(pData1)) { + _channels[0].load(pData1); + _channels[1].load(loadData(0x2A0C, 76)); + _channels[2].load(loadData(0x2A58, 122)); + _channels[3].load(loadData(0x2AD2, 38)); + } + + return 0; +} + +int ASound7::command15() { + byte *pData = loadData(0x2B3E, 10); + pData[6] = (getRandomNumber() & 7) + 85; + + return 0; +} + +int ASound7::command16() { + playSound(0x2CE2, 8); + + return 0; +} + +int ASound7::command18() { + playSound(0x2C94, 22); + + return 0; +} + +int ASound7::command19() { + byte *pData1 = loadData(0x2C94, 22); + byte *pData2 = loadData(0x2CAA, 16); + if (_channels[8]._ptr1 == pData1 || _channels[8]._ptr1 == pData2) { + _channels[8]._soundData = loadData(0x2CBA, 12); + _channels[8]._field17 = 1; + _channels[8]._field19 = 1; + } + + return 0; +} + +int ASound7::command20() { + playSound(0x2CD0, 18); + + return 0; +} + +int ASound7::command21() { + playSound(0x2CC6, 10); + + return 0; +} + +int ASound7::command22() { + playSound(0x2C08, 140); + + return 0; +} + +int ASound7::command23() { + playSound(0x2B08, 34); + playSound(0x2B2A, 20); + + return 0; +} + +int ASound7::command24() { + byte *pData1 = loadData(0x14C6, 144); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1556, 146)); + _channels[2].load(loadData(0x15E8, 138)); + _channels[3].load(loadData(0x1672, 122)); + _channels[4].load(loadData(0x16EC, 74)); + } + + return 0; +} + +int ASound7::command25() { + byte *pData1 = loadData(0x1DBE, 182); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x1E74, 182)); + _channels[2].load(loadData(0x1F2A, 186)); + _channels[3].load(loadData(0x1FE4, 244)); + } + + return 0; +} + +int ASound7::command26() { + byte *pData1 = loadData(0x20D8, 312); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x2210, 304)); + _channels[2].load(loadData(0x2340, 222)); + _channels[3].load(loadData(0x241E, 522)); + _channels[4].load(loadData(0x2628, 874)); + } + + return 0; +} + +int ASound7::command27() { + byte *pData1 = loadData(0x1736, 158); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x17D4, 288)); + _channels[2].load(loadData(0x18F4, 290)); + _channels[3].load(loadData(0x1A16, 396)); + _channels[4].load(loadData(0x1BA2, 380)); + _channels[5].load(loadData(0x1D1E, 160)); + } + + return 0; +} + +int ASound7::command28() { + playSound(0x2CAA, 16); + + return 0; +} + +int ASound7::command30() { + playSound(0x2B86, 22); + playSound(0x2B9C, 22); + playSound(0x2BB2, 22); + + return 0; +} + +int ASound7::command32() { + playSound(0x2BFE, 10); + + return 0; +} + +int ASound7::command33() { + playSound(0x2BEE, 16); + + return 0; +} + +int ASound7::command34() { + playSound(0x2BDE, 16); + + return 0; +} + +int ASound7::command35() { + playSound(0x2BC8, 22); + + return 0; +} + +int ASound7::command36() { + playSound(0x2AF8, 16); + + return 0; +} + +int ASound7::command37() { + playSound(0x2B48, 20); + playSound(0x2B5C, 32); + playSound(0x2B7C, 10); + + return 0; +} + +/*-----------------------------------------------------------------------*/ + +const ASound8::CommandPtr ASound8::_commandList[38] = { + &ASound8::command0, &ASound8::command1, &ASound8::command2, &ASound8::command3, + &ASound8::command4, &ASound8::command5, &ASound8::command6, &ASound8::command7, + &ASound8::command8, &ASound8::command9, &ASound8::command10, &ASound8::command11, + &ASound8::command12, &ASound8::command13, &ASound8::command14, &ASound8::command15, + &ASound8::command16, &ASound8::command16, &ASound8::command18, &ASound8::command19, + &ASound8::command20, &ASound8::command21, &ASound8::command22, &ASound8::command23, + &ASound8::command24, &ASound8::command25, &ASound8::command26, &ASound8::command27, + &ASound8::command28, &ASound8::command29, &ASound8::command30, &ASound8::command31, + &ASound8::command32, &ASound8::command33, &ASound8::command34, &ASound8::command35, + &ASound8::command36, &ASound8::command37 +}; + +ASound8::ASound8(Audio::Mixer *mixer) : ASound(mixer, "asound.008", 0x1490) { + // Load sound samples + _soundFile.seek(_dataOffset + 0x122); + for (int i = 0; i < 174; ++i) + _samples.push_back(AdlibSample(_soundFile)); +} + +int ASound8::command(int commandId, int param) { + if (commandId > 37) + return 0; + + _frameCounter = 0; + return (this->*_commandList[commandId])(); +} + +int ASound8::command9() { + byte *pData = loadData(0x15BE, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound8::command10() { + byte *pData = loadData(0x2B3E, 10); + pData[6] = (getRandomNumber() & 7) + 85; + playSoundData(pData); + + return 0; +} + +int ASound8::command11() { + playSound(0x17CA, 12); + + return 0; +} + +int ASound8::command12() { + playSound(0x17D6, 12); + + return 0; +} + +int ASound8::command13() { + playSound(0x1694, 10); + + return 0; +} + +int ASound8::command14() { + playSound(0x169E, 24); + + return 0; +} + +int ASound8::command15() { + byte *pData = loadData(0x169E, 24); + if (_channels[8]._ptr1 == pData) { + _channels[8]._soundData = loadData(0x16B6, 12); + _channels[8]._field17 = 1; + _channels[8]._field19 = 1; + } + + return 0; +} + +int ASound8::command16() { + playSound(0x1686, 14); + + return 0; +} + +int ASound8::command17() { + playSound(0x17EC, 12); + + return 0; +} + +int ASound8::command18() { + playSound(0x17F8, 12); + + return 0; +} + +int ASound8::command19() { + playSound(0x16D8, 8); + + return 0; +} + +int ASound8::command20() { + playSound(0x16E0, 8); + + return 0; +} + +int ASound8::command21() { + playSound(0x17E2, 10); + + return 0; +} + +int ASound8::command22() { + playSound(0x178C, 14); + playSound(0x179A, 14); + playSound(0x17A8, 14); + + return 0; +} + +int ASound8::command23() { + playSound(0x2B08, 34); + playSound(0x2B2A, 20); + + return 0; +} + +int ASound8::command24() { + playSound(0x17B6, 8); + + return 0; +} + +int ASound8::command25() { + playSound(0x17BE, 12); + + return 0; +} + +int ASound8::command26() { + playSound(0x16C2, 22); + + return 0; +} + +int ASound8::command27() { + playSound(0x1588, 34); + playSound(0x15AA, 20); + + return 0; +} + +int ASound8::command28() { + byte *pData1 = loadData(0x114E, 376); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[2].load(loadData(0x12F8, 130)); + + byte *pData = loadData(0x12C6, 50); + method1(pData); + _channels[1].load(pData); + } + + return 0; +} + +void ASound8::method1(byte *pData) { + int v; + while ((v = (getRandomNumber() & 0x3F)) > 36) + ; + + adjustRange(pData, v + 20, -1); + adjustRange(pData + 1, 10 - ((v + 1) / 6), 1); +} + +void ASound8::adjustRange(byte *pData, byte v, int incr) { + pData += 8; + + for (int i = 0; i < 10; ++i, pData += 4, v += incr) { + *pData = v; + } +} + +int ASound8::command29() { + byte *pData1 = loadData(0x137A, 60); + if (!isSoundActive(pData1)) { + command1(); + _channels[0].load(pData1); + _channels[1].load(loadData(0x13B6, 318)); + _channels[2].load(loadData(0x14F4, 118)); + } + + return 0; +} + +int ASound8::command30() { + playSound(0x1644, 22); + playSound(0x165A, 22); + playSound(0x1670, 22); + + return 0; +} + +int ASound8::command31() { + playSound(0x156A, 14); + + return 0; +} + +int ASound8::command32() { + playSound(0x163A, 10); + + return 0; +} + +int ASound8::command33() { + playSound(0x162A, 16); + + return 0; +} + +int ASound8::command34() { + playSound(0x161A, 16); + + return 0; +} + +int ASound8::command35() { + playSound(0x1604, 22); + + return 0; +} + +int ASound8::command36() { + playSound(0x1578, 16); + + return 0; +} + +int ASound8::command37() { + playSound(0x15C8, 20); + playSound(0x15DC, 30); + playSound(0X15FA, 10); + + return 0; +} + +} // End of namespace Nebular + +} // End of namespace MADS diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h new file mode 100644 index 0000000000..c485bd7955 --- /dev/null +++ b/engines/mads/nebular/sound_nebular.h @@ -0,0 +1,720 @@ +/* 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 MADS_SOUND_NEBULAR_H +#define MADS_SOUND_NEBULAR_H + +#include "common/scummsys.h" +#include "common/file.h" +#include "common/mutex.h" +#include "common/queue.h" +#include "audio/audiostream.h" +#include "audio/fmopl.h" +#include "audio/mixer.h" + +namespace MADS { + +class SoundManager; + +namespace Nebular { + +/** + * Represents the data for a channel on the Adlib + */ +class AdlibChannel { +public: + int _activeCount; + int _field1; + int _field2; + int _field3; + int _field4; + int _sampleIndex; + int _volume; + int _field7; + int _field8; + int _field9; + int _fieldA; + uint8 _fieldB; + int _fieldC; + int _fieldD; + int _fieldE; + byte *_ptr1; + byte *_pSrc; + byte *_ptr3; + byte *_ptr4; + int _field17; + int _field19; + byte *_soundData; + int _field1D; + int _field1E; + int _field1F; + + // TODO: Only used by asound.003. Figure out usage + byte _field20; +public: + static bool _channelsEnabled; +public: + AdlibChannel(); + + void reset(); + void enable(int flag); + void setPtr2(byte *pData); + void load(byte *pData); + void check(byte *nullPtr); +}; + +class AdlibChannelData { +public: + int _field0; + int _freqMask; + int _freqBase; + int _field6; +}; + +class AdlibSample { +public: + int _attackRate; + int _decayRate; + int _sustainLevel; + int _releaseRate; + bool _egTyp; + bool _ksr; + int _totalLevel; + int _scalingLevel; + int _waveformSelect; + int _freqMultiple; + int _feedback; + bool _ampMod; + int _vib; + int _alg; + int _fieldE; + int _freqMask; + int _freqBase; + int _field14; + + AdlibSample() {} + AdlibSample(Common::SeekableReadStream &s); +}; + +struct RegisterValue { + uint8 _regNum; + uint8 _value; + + RegisterValue(int regNum, int value) { + _regNum = regNum; _value = value; + } +}; + +#define ADLIB_CHANNEL_COUNT 9 +#define ADLIB_CHANNEL_MIDWAY 5 +#define CALLBACKS_PER_SECOND 60 + +/** + * Base class for the sound player resource files + */ +class ASound : public Audio::AudioStream { +private: + struct CachedDataEntry { + int _offset; + byte *_data; + }; + Common::List<CachedDataEntry> _dataCache; + uint16 _randomSeed; + + /** + * Does the initial Adlib initialisation + */ + void adlibInit(); + + /** + * Does on-going processing for the Adlib sounds being played + */ + void update(); + + /** + * Polls each of the channels for updates + */ + void pollChannels(); + + /** + * Checks the status of the channels + */ + void checkChannels(); + + /** + * Polls the currently active channel + */ + void pollActiveChannel(); + + /** + * Updates the octave of the currently active channel + */ + void updateOctave(); + + void updateChannelState(); + void updateActiveChannel(); + + /** + * Loads up the specified sample + */ + void loadSample(int sampleIndex); + + /** + * Writes out the data of the selected sample to the Adlib + */ + void processSample(); + + void updateFNumber(); +protected: + int _commandParam; + + /** + * Queue a byte for an Adlib register + */ + void write(int reg, int val); + + /** + * Queue a byte for an Adlib register, and store it in the _ports array + */ + int write2(int state, int reg, int val); + + /** + * Flush any pending Adlib register values to the OPL driver + */ + void flush(); + + /** + * Turn a channel on + */ + void channelOn(int reg, int volume); + + /** + * Turn a channel off + */ + void channelOff(int reg); + + /** + * Checks for whether a poll result needs to be set + */ + void resultCheck(); + + /** + * Loads a data block from the sound file, caching the result for any future + * calls for the same data + */ + byte *loadData(int offset, int size); + + /** + * Play the specified sound + * @param offset Offset of sound data within sound player data segment + * @param size Size of sound data block + */ + void playSound(int offset, int size); + + /** + * Play the specified raw sound data + * @param pData Pointer to data block containing sound data + * @param startingChannel Channel to start scan from + */ + void playSoundData(byte *pData, int startingChannel = ADLIB_CHANNEL_MIDWAY); + + /** + * Checks to see whether the given block of data is already loaded into a channel. + */ + bool isSoundActive(byte *pData); + + /** + * Sets the frequency for a given channel. + */ + void setFrequency(int channel, int freq); + + /** + * Returns a 16-bit random number + */ + int getRandomNumber(); + + virtual int command0(); + int command1(); + int command2(); + int command3(); + int command4(); + int command5(); + int command6(); + int command7(); + int command8(); + + int nullCommand() { return 0; } +public: + Audio::Mixer *_mixer; + FM_OPL *_opl; + Audio::SoundHandle _soundHandle; + AdlibChannel _channels[ADLIB_CHANNEL_COUNT]; + AdlibChannel *_activeChannelPtr; + AdlibChannelData _channelData[11]; + Common::Array<AdlibSample> _samples; + AdlibSample *_samplePtr; + Common::File _soundFile; + Common::Queue<RegisterValue> _queue; + Common::Mutex _driverMutex; + int _dataOffset; + int _frameCounter; + bool _isDisabled; + int _v1; + int _v2; + int _activeChannelNumber; + int _freqMask1; + int _freqMask2; + int _freqBase1; + int _freqBase2; + int _channelNum1, _channelNum2; + int _v7; + int _v8; + int _v9; + int _v10; + int _pollResult; + int _resultFlag; + byte _nullData[2]; + int _ports[256]; + bool _stateFlag; + int _activeChannelReg; + int _v11; + bool _amDep, _vibDep, _splitPoint; + int _samplesPerCallback; + int _samplesPerCallbackRemainder; + int _samplesTillCallback; + int _samplesTillCallbackRemainder; +public: + /** + * Constructor + * @param filename Specifies the adlib sound player file to use + * @param dataOffset Offset in the file of the data segment + */ + ASound(Audio::Mixer *mixer, const Common::String &filename, int dataOffset); + + /** + * Destructor + */ + virtual ~ASound(); + + /** + * Execute a player command. Most commands represent sounds to play, but some + * low number commands also provide control operations. + * @param commandId Player ommand to execute. + * @param param Optional parameter used by a few commands + */ + virtual int command(int commandId, int param) = 0; + + /** + * Stop all currently playing sounds + */ + int stop(); + + /** + * Main poll method to allow sounds to progress + */ + int poll(); + + /** + * General noise/note output + */ + void noise(); + + /** + * Return the current frame counter + */ + int getFrameCounter() { return _frameCounter; } + + // AudioStream interface + /** + * Main buffer read + */ + virtual int readBuffer(int16 *buffer, const int numSamples); + + /** + * Mono sound only + */ + virtual bool isStereo() const { return false; } + + /** + * Data is continuously pushed, so definitive end + */ + virtual bool endOfData() const { return false; } + + /** + * Return sample rate + */ + virtual int getRate() const { return 11025; } +}; + +class ASound1 : public ASound { +private: + typedef int (ASound1::*CommandPtr)(); + static const CommandPtr _commandList[42]; + bool _cmd23Toggle; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + + void command111213(); + int command2627293032(); +public: + ASound1(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound2 : public ASound { +private: + byte _command12Param; +private: + typedef int (ASound2::*CommandPtr)(); + static const CommandPtr _commandList[44]; + + virtual int command0(); + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); + + void command9Randomize(); + void command9Apply(byte *data, int val, int incr); +public: + ASound2(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound3 : public ASound { +private: + bool _command39Flag; + + typedef int (ASound3::*CommandPtr)(); + static const CommandPtr _commandList[61]; + + int command9(); + int command10(); + int command11(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); + int command44(); + int command45(); + int command46(); + int command47(); + int command49(); + int command50(); + int command51(); + int command57(); + int command59(); + int command60(); + + void command9Randomize(); + void command9Apply(byte *data, int val, int incr); +public: + ASound3(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound4 : public ASound { +private: + typedef int (ASound4::*CommandPtr)(); + static const CommandPtr _commandList[61]; + + int command10(); + int command12(); + int command19(); + int command20(); + int command21(); + int command24(); + int command27(); + int command30(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command43(); + int command52(); + int command53(); + int command54(); + int command55(); + int command56(); + int command57(); + int command58(); + int command59(); + int command60(); + + void method1(); +public: + ASound4(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound5 : public ASound { +private: + typedef int (ASound5::*CommandPtr)(); + static const CommandPtr _commandList[42]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + int command38(); + int command39(); + int command40(); + int command41(); + int command42(); + int command43(); +public: + ASound5(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound6 : public ASound { +private: + typedef int (ASound6::*CommandPtr)(); + static const CommandPtr _commandList[30]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command29(); +public: + ASound6(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound7 : public ASound { +private: + typedef int (ASound7::*CommandPtr)(); + static const CommandPtr _commandList[38]; + + int command9(); + int command15(); + int command16(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command30(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); +public: + ASound7(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +class ASound8 : public ASound { +private: + typedef int (ASound8::*CommandPtr)(); + static const CommandPtr _commandList[38]; + + int command9(); + int command10(); + int command11(); + int command12(); + int command13(); + int command14(); + int command15(); + int command16(); + int command17(); + int command18(); + int command19(); + int command20(); + int command21(); + int command22(); + int command23(); + int command24(); + int command25(); + int command26(); + int command27(); + int command28(); + int command29(); + int command30(); + int command31(); + int command32(); + int command33(); + int command34(); + int command35(); + int command36(); + int command37(); + + void method1(byte *pData); + void adjustRange(byte *pData, byte v, int incr); +public: + ASound8(Audio::Mixer *mixer); + + virtual int command(int commandId, int param); +}; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_SOUND_NEBULAR_H */ diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp new file mode 100644 index 0000000000..755f7bcf5c --- /dev/null +++ b/engines/mads/palette.cpp @@ -0,0 +1,830 @@ +/* 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 "common/scummsys.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "mads/mads.h" +#include "mads/msurface.h" +#include "mads/staticres.h" + +namespace MADS { + +#define VGA_COLOR_TRANS(x) ((x) * 255 / 63) + +void RGB6::load(Common::SeekableReadStream *f) { + r = VGA_COLOR_TRANS(f->readByte()); + g = VGA_COLOR_TRANS(f->readByte()); + b = VGA_COLOR_TRANS(f->readByte()); + _palIndex = f->readByte(); + _u2 = f->readByte(); + _flags = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +PaletteUsage::PaletteUsage(MADSEngine *vm) { + _vm = vm; + _data = nullptr; +} + +void PaletteUsage::load(Common::Array<UsageEntry> *data) { + _data = data; +} + +void PaletteUsage::getKeyEntries(Common::Array<RGB6> &palette) { + _data->clear(); + + for (uint i = 0; i < palette.size(); ++i) { + byte *uPtr = &palette[i]._flags; + if ((*uPtr & 0x10) && _data->size() < 3) { + _data->push_back(UsageEntry(i)); + } + } +} + +static bool sortHelper(const PaletteUsage::UsageEntry &ue1, const PaletteUsage::UsageEntry &ue2) { + return ue1._sortValue < ue2._sortValue; +} + +void PaletteUsage::prioritize(Common::Array<RGB6> &palette) { + for (uint i = 0; i < _data->size(); ++i) { + RGB6 &palEntry = palette[(*_data)[i]._palIndex]; + (*_data)[i]._sortValue = _vm->_palette->rgbMerge(palEntry); + } + + Common::sort(_data->begin(), _data->end(), sortHelper); +} + +static bool rangeSorter(const PaletteUsage::UsageRange &ur1, const PaletteUsage::UsageRange &ur2) { + return ur1._v2 < ur2._v2; +} + +int PaletteUsage::process(Common::Array<RGB6> &palette, uint flags) { + int palLow; + int palHigh = (flags & 0x800) ? 0x100 : 0xFC; + int palIdx; + + PaletteUsage tempUsage(_vm); + Common::Array<UsageEntry> tempUsageData; + tempUsage.load(&tempUsageData); + + if (flags & 0x4000) { + palLow = 0; + palIdx = palHigh; + } else { + palLow = _vm->_palette->_lowRange; + if ((PALETTE_COUNT - _vm->_palette->_highRange) > palHigh) { + palIdx = palHigh; + } else { + palIdx = PALETTE_COUNT - _vm->_palette->_highRange; + } + } + + int rgbIndex = _vm->_palette->_rgbList.scan(); + uint32 rgbMask = 1 << rgbIndex; + bool noUsageFlag = flags & 0x8000; + bool hasUsage = _data != nullptr; + bool flag1 = false; + + if (hasUsage) { + if (noUsageFlag || _data->size() == 0) + hasUsage = false; + + if (noUsageFlag && _data->size() > 0) + flag1 = true; + } + + if (hasUsage) { + tempUsage.getKeyEntries(palette); + tempUsage.prioritize(palette); + } + + int freeIndex; + int palCount = getGamePalFreeIndex(&freeIndex); + Common::Array<UsageRange> palRange; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + byte pal2 = palIndex; + byte pal1 = 0; + + if (!(palette[palIndex]._flags & 0x80)) { + pal1 = 0x40; + } + if (palette[palIndex]._flags & 0x60) { + pal1 |= 0x20; + } + + palRange.push_back(UsageRange(pal1, pal2)); + } + + Common::sort(palRange.begin(), palRange.end(), rangeSorter); + + int var3A = (flags & 0x4000) ? 0xffff : 0xfffe; + + for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) { + bool var48 = false; + int var4 = 0xffff; + int v1 = palRange[palIndex]._v2; + + if (palette[v1]._flags & 8) { + var48 = true; + var4 = 0xFD; + } + + if (hasUsage && palette[v1]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < tempUsage._data->size() && !var48; ++usageIndex) { + if ((*tempUsage._data)[usageIndex]._palIndex == palIndex) { + var48 = true; + int dataIndex = MIN(usageIndex, _data->size() - 1); + var4 = (*_data)[dataIndex]._palIndex; + } + } + } + + if (flag1 && palette[palIndex]._flags & 0x10) { + for (uint usageIndex = 0; usageIndex < _data->size() && !var48; ++usageIndex) { + if ((*_data)[usageIndex]._palIndex == palIndex) { + var48 = true; + var4 = 0xF0 + usageIndex; + + // Copy data into the high end of the main palette + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[var4 * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + if (!var48 && !noUsageFlag) { + int var2 = (palette[palIndex]._flags & 0x20) || + (((flags & 0x2000) || (palette[palIndex]._flags & 0x4000)) && + ((flags & 0x1000) || (palCount == 0))) ? 0x7fff : 1; + int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2; + + for (int idx = palLow; idx < palIdx; ++idx) { + uint32 v = _vm->_palette->_palFlags[idx]; + if ((v & var3A) && !(v & var36)) { + int var10; + + if (var2 > 1) { + var10 = rgbFactor(&_vm->_palette->_mainPalette[idx * 3], palette[palIndex]); + } + else if (_vm->_palette->_mainPalette[idx * 3] != palette[palIndex].r || + _vm->_palette->_mainPalette[idx * 3 + 1] != palette[palIndex].g || + _vm->_palette->_mainPalette[idx * 3 + 2] != palette[palIndex].b) { + var10 = 1; + } else { + var10 = 0; + } + + if (var2 > var10) { + var48 = true; + var4 = idx; + var2 = var10; + } + } + } + } + + if (!var48 && (!(flags & 0x1000) || (!(palette[palIndex]._flags & 0x60) && !(flags & 0x2000)))) { + for (int idx = freeIndex; idx < palIdx && !var48; ++idx) { + if (!_vm->_palette->_palFlags[idx]) { + --palCount; + ++freeIndex; + var48 = true; + var4 = idx; + + RGB6 &pSrc = palette[palIndex]; + byte *pDest = &_vm->_palette->_mainPalette[idx * 3]; + pDest[0] = pSrc.r; + pDest[1] = pSrc.g; + pDest[2] = pSrc.b; + } + } + } + + assert(var48); + int var52 = (noUsageFlag && palette[palIndex]._u2) ? 2 : 0; + + _vm->_palette->_palFlags[var4] |= var52 | rgbMask; + palette[palIndex]._palIndex = var4; + } + + _vm->_palette->_rgbList[rgbIndex] = true; + + return rgbIndex; +} + +void PaletteUsage::transform(Common::Array<RGB6> &palette) { + if (!empty()) { + for (uint i = 0; i < _data->size(); ++i) { + int palIndex = (*_data)[i]._palIndex; + (*_data)[i]._palIndex = palette[palIndex]._palIndex; + } + } +} + +void PaletteUsage::updateUsage(Common::Array<int> &usageList, int sceneUsageIndex) { + uint32 mask1 = 0xFFFFFFFF; + uint32 mask2 = 0; + + for (uint idx = 0; idx < usageList.size(); ++idx) { + uint32 bitMask = 1 << usageList[idx]; + mask1 ^= bitMask; + mask2 |= bitMask; + _vm->_palette->_rgbList[usageList[idx]] = false; + } + + uint32 mask3 = 1 << sceneUsageIndex; + + for (uint idx = 0; idx < PALETTE_COUNT; ++idx) { + uint32 mask = mask2 & _vm->_palette->_palFlags[idx]; + if (mask) { + _vm->_palette->_palFlags[idx] = (_vm->_palette->_palFlags[idx] & + mask1) | mask3; + } + } + + _vm->_palette->_rgbList[sceneUsageIndex] = true; +} + +void PaletteUsage::resetPalFlags(int idx) { + if (idx >= 0 && idx < 32) { + uint32 rgbMask = ~(1 << idx); + + uint32 *flagP = _vm->_palette->_palFlags; + for (int i = 0; i < 256; ++i, ++flagP) { + *flagP &= rgbMask; + if (*flagP == 2) + *flagP = 0; + } + + _vm->_palette->_rgbList[idx] = 0; + } +} + +int PaletteUsage::getGamePalFreeIndex(int *palIndex) { + *palIndex = -1; + int count = 0; + + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (!_vm->_palette->_palFlags[i]) { + ++count; + if (*palIndex < 0) + *palIndex = i; + } + } + + return count; +} + +int PaletteUsage::rgbFactor(byte *palEntry, RGB6 &pal6) { + int total = 0; + total += (palEntry[0] - pal6.r) * (palEntry[0] - pal6.r); + total += (palEntry[1] - pal6.g) * (palEntry[1] - pal6.g); + total += (palEntry[2] - pal6.b) * (palEntry[2] - pal6.b); + + return total; +} + +/*------------------------------------------------------------------------*/ + +void RGBList::clear() { + for (int i = 0; i < 32; i++) + _data[i] = false; +} + +void RGBList::reset() { + for (int i = 2; i < 32; i++) + _data[i] = false; +} + +int RGBList::scan() { + for (int i = 0; i < 32; ++i) { + if (!_data[i]) + return i; + } + + error("RGBList was full"); +} + +void RGBList::copy(RGBList &src) { + Common::copy(&src._data[0], &src._data[32], &_data[0]); +} + +/*------------------------------------------------------------------------*/ + +Fader::Fader(MADSEngine *vm) + : _vm(vm) { + _colorFlags[0] = _colorFlags[1] = _colorFlags[2] = true; + _colorFlags[3] = false; + _colorValues[0] = _colorValues[1] = 0; + _colorValues[2] = _colorValues[3] = 0; + + // TODO: It would be better if the fader routines could be refactored + // to work directly with 8-bit RGB values rather than 6-bit RGB values + Common::fill(&_rgb64Map[0], &_rgb64Map[PALETTE_COUNT], 0); + for (int i = 0; i < 64; ++i) + _rgb64Map[VGA_COLOR_TRANS(i)] = i; + byte v = 0; + for (int i = 0; i < PALETTE_COUNT; ++i) { + if (_rgb64Map[i]) + v = _rgb64Map[i]; + else + _rgb64Map[i] = v; + } +} + + +void Fader::setPalette(const byte *colors, uint start, uint num) { + g_system->getPaletteManager()->setPalette(colors, start, num); +} + +void Fader::grabPalette(byte *colors, uint start, uint num) { + g_system->getPaletteManager()->grabPalette(colors, start, num); +} + +void Fader::fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + int intensity; + byte palIndex[PALETTE_COUNT][3]; + int8 signs[PALETTE_COUNT][3]; + + mapToGreyRamp(palette, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } else { + intensity = map[index]._intensity >> ABS(shiftSign); + } + } else { + intensity = _colorValues[colorCtr]; + } + + int diff = intensity - _rgb64Map[palette[palCtr * 3 + colorCtr]]; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } + + if (paletteMap != nullptr) { + for (int palCtr = 0; palCtr < numColors; palCtr++) { + paletteMap[palCtr] = map[palCtr]._mapColor; + } + } +} + +void Fader::fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps) { + GreyEntry map[PALETTE_COUNT]; + byte tempPal[PALETTE_SIZE];; + int8 signs[PALETTE_COUNT][3]; + byte palIndex[PALETTE_COUNT][3]; + int intensity; + + Common::copy(destPalette, destPalette + PALETTE_SIZE, tempPal); + + mapToGreyRamp(tempPal, baseColor, numColors, baseGrey, numGreys, map); + + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + if (_colorFlags[colorCtr]) { + int shiftSign = _colorValues[colorCtr]; + if (shiftSign >= 0) { + intensity = map[index]._intensity << shiftSign; + } + else { + intensity = map[index]._intensity >> abs(shiftSign); + } + } + else { + intensity = _colorValues[colorCtr]; + } + + int diff = _rgb64Map[destPalette[palCtr * 3 + colorCtr]] - intensity; + palIndex[palCtr][colorCtr] = (byte)ABS(diff); + signs[palCtr][colorCtr] = (diff == 0) ? 0 : (diff < 0 ? -1 : 1); + + map[index]._accum[colorCtr] = 0; + } + } + + for (int stepCtr = 0; stepCtr < steps; ++stepCtr) { + for (int palCtr = baseColor; palCtr < (baseColor + numColors); ++palCtr) { + int index = palCtr - baseColor; + for (int colorCtr = 0; colorCtr < 3; ++colorCtr) { + map[index]._accum[colorCtr] += palIndex[palCtr][colorCtr]; + while (map[index]._accum[colorCtr] >= steps) { + map[index]._accum[colorCtr] -= steps; + + byte rgb63 = _rgb64Map[palette[palCtr * 3 + colorCtr]] + + signs[palCtr][colorCtr]; + palette[palCtr * 3 + colorCtr] = VGA_COLOR_TRANS(rgb63); + } + } + } + + setFullPalette(palette); + + _vm->_events->waitForNextFrame(); + } +} + +void Fader::mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors, + int baseGrey, int numGreys, GreyEntry *map) { + byte greyList[PALETTE_COUNT]; + byte greyMapping[PALETTE_COUNT]; + byte greyTable[64]; + byte greyIntensity[64]; + int intensity, shiftSign; + + getGreyValues(palette, greyList, baseColor, numColors); + greyPopularity(greyList, greyTable, numColors); + + for (int idx = 0; idx < numColors; ++idx) { + greyMapping[idx] = idx; + Common::fill(&map[idx]._accum[0], &map[idx]._accum[3], 0); + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) { + map[idx]._mapColor = (byte)idx; + } + + // Sort the mapping lists + insertionSort(numColors, greyList, greyMapping); + + // Initialize state variables + int greySum = 0; + int greyScan = 0; + int greyMark = 0; + int greyColors = 0; + int greyAccum = 0; + int firstColor = 0; + + for (int greyCtr = 0; greyCtr < 64; ++greyCtr) { + for (int idx = 0; idx < greyTable[greyCtr]; ++idx) { + greySum += greyList[greyScan++]; + ++greyColors; + + greyAccum += numGreys; + while (greyAccum >= numColors) { + greyAccum -= numColors; + if (greyColors > 0) { + greyIntensity[greyMark] = (byte)(greySum / greyColors); + } + + for (int rescan = firstColor; rescan < greyScan; ++rescan) { + map[greyMapping[rescan]]._intensity = greyIntensity[greyMark]; + map[greyMapping[rescan]]._mapColor = (byte)(greyMark + baseGrey); + } + + firstColor = greyScan; + greySum = 0; + greyColors = 0; + ++greyMark; + } + } + } + + // Set the palette range of greyscale values to be used + byte *palP = &palette[baseGrey * 3]; + for (int greys = 0; greys < numGreys; ++greys) { + for (int color = 0; color < 3; ++color) { + if (_colorFlags[color]) { + shiftSign = (byte)_colorValues[color]; + if (shiftSign >= 0) { + intensity = greyIntensity[greys] << shiftSign; + } else { + intensity = greyIntensity[greys] >> abs(shiftSign); + } + } else { + intensity = _colorValues[color]; + } + *palP++ = VGA_COLOR_TRANS(intensity); + } + } +} + +void Fader::getGreyValues(const byte palette[PALETTE_SIZE], + byte greyList[PALETTE_COUNT], int baseColor, int numColors) { + const byte *palP = &palette[baseColor * 3]; + + for (int i = 0; i < numColors; ++i, palP += 3) { + int v = rgbMerge(palP[0], palP[1], palP[2]); + greyList[i] = v >> 7; + } +} + +void Fader::greyPopularity(const byte greyList[PALETTE_COUNT], + byte greyTable[64], int numColors) { + Common::fill(&greyTable[0], &greyTable[64], 0); + for (int i = 0; i < numColors; ++i) { + int idx = greyList[i]; + ++greyTable[idx]; + } +} + +void Fader::insertionSort(int size, byte *id, byte *value) { + bool restartFlag; + int endIndex = size - 1; + + do { + restartFlag = false; + if (endIndex <= 0) + break; + + for (int arrIndex = 0; arrIndex < endIndex && !restartFlag; ++arrIndex) { + byte *idP = id + arrIndex; + byte *valueP = value + arrIndex; + + // Check whether the next index is out of order with the one following it + if (*idP > *(idP + 1)) { + // Found an incorrect ordering + restartFlag = true; + + // Save id/value at current index + byte savedId = *idP; + byte savedValue = *valueP; + + int moveCount = size - arrIndex - 1; + if (moveCount > 0) { + Common::copy(idP + 1, idP + moveCount + 2, idP); + Common::copy(valueP + 1, valueP + moveCount + 2, valueP); + } + + // Scan for insert spot + int idx = 0; + if (endIndex > 0) { + bool breakFlag = false; + for (; idx <= endIndex && !breakFlag; ++idx) { + breakFlag = savedId < id[idx]; + } + } + + // Set up an insert point for entry + moveCount = size - idx - 1; + if (moveCount > 0) { + Common::copy_backward(id + idx, id + idx + moveCount, id + idx + moveCount + 1); + Common::copy_backward(value + idx, value + idx + moveCount, value + idx + moveCount + 1); + } + + // Set shifted values at the new position + id[idx] = savedId; + value[idx] = savedValue; + } + } + } while (restartFlag); +} + +int Fader::rgbMerge(RGB6 &palEntry) { + return rgbMerge(palEntry.r, palEntry.g, palEntry.b); +} + +int Fader::rgbMerge(byte r, byte g, byte b) { + return _rgb64Map[r] * 38 + _rgb64Map[g] * 76 + _rgb64Map[b] * 14; +} + +/*------------------------------------------------------------------------*/ + +Palette::Palette(MADSEngine *vm) : Fader(vm), _paletteUsage(vm) { + _lockFl = false; + _lowRange = 0; + _highRange = 0; + Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0); + Common::fill(&_palFlags[0], &_palFlags[PALETTE_COUNT], 0); +} + +void Palette::setEntry(byte palIndex, byte r, byte g, byte b) { + _mainPalette[palIndex * 3] = VGA_COLOR_TRANS(r); + _mainPalette[palIndex * 3 + 1] = VGA_COLOR_TRANS(g); + _mainPalette[palIndex * 3 + 2] = VGA_COLOR_TRANS(b); + + setPalette((const byte *)&_mainPalette[palIndex * 3], palIndex, 1); +} + +uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, byte *paletteData) { + byte index = 0; + int32 minDist = 0x7fffffff; + byte palData[PALETTE_SIZE]; + + if (paletteData == NULL) { + g_system->getPaletteManager()->grabPalette(palData, 0, PALETTE_COUNT); + paletteData = &palData[0]; + } + + for (int palIndex = 0; palIndex < PALETTE_COUNT; ++palIndex) { + int Rdiff = r - paletteData[palIndex * 3]; + int Gdiff = g - paletteData[palIndex * 3 + 1]; + int Bdiff = b - paletteData[palIndex * 3 + 2]; + + if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) { + minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; + index = (uint8)palIndex; + } + } + + return (uint8)index; +} + +void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2) { + int rgbCurrent = rgbValue2; + int rgbDiff = -(rgbValue2 - rgbValue1); + + if (count > 0) { + byte *pDest = palette + start * 3; + int endVal = count - 1; + int numLeft = count; + + int rgbCtr = 0; + do { + pDest[0] = pDest[1] = pDest[2] = rgbCurrent; + + if (numLeft > 1) { + rgbCtr += rgbDiff; + if (rgbCtr >= endVal) { + do { + ++rgbCurrent; + rgbCtr += 1 - numLeft; + } while (rgbCtr >= endVal); + } + } + + pDest += 3; + } while (--numLeft > 0); + } +} + +void Palette::setSystemPalette() { + byte palData[4 * 3]; + palData[0 * 3] = palData[0 * 3 + 1] = palData[0 * 3 + 2] = 0; + palData[1 * 3] = palData[1 * 3 + 1] = palData[1 * 3 + 2] = 0x54; + palData[2 * 3] = palData[2 * 3 + 1] = palData[2 * 3 + 2] = 0xb4; + palData[3 * 3] = palData[3 * 3 + 1] = palData[3 * 3 + 2] = 0xff; + + setPalette(palData, 0, 4); +} + +void Palette::resetGamePalette(int lowRange, int highRange) { + Common::fill((byte *)&_palFlags[0], (byte *)&_palFlags[PALETTE_COUNT], 0); + initVGAPalette(_mainPalette); + + // Reserve the start of the palette for things like on-screen text + if (lowRange) { + Common::fill(&_palFlags[0], &_palFlags[lowRange], 1); + } + + // Reserve the high end of the palette for dialog display + if (highRange) { + Common::fill(&_palFlags[256 - highRange], &_palFlags[256], 1); + } + + _rgbList.clear(); + _rgbList[0] = _rgbList[1] = true; + + _lockFl = false; + _lowRange = lowRange; + _highRange = highRange; +} + +void Palette::initPalette() { + uint32 palMask = 1; + + if (_vm->_game->_player._spritesLoaded && _vm->_game->_player._numSprites) { + + for (int idx = 0; idx < _vm->_game->_player._numSprites; ++idx) { + SpriteAsset *asset = _vm->_game->_scene._sprites[ + _vm->_game->_player._spritesStart + idx]; + + uint32 mask = 1; + if (asset->_usageIndex) + mask <<= asset->_usageIndex; + + palMask = mask; + } + } + + for (int idx = 0; idx < PALETTE_COUNT; ++idx) + _palFlags[idx] = palMask; + + _lockFl = false; + _rgbList.reset(); +} + +void Palette::initVGAPalette(byte *palette) { + byte *destP = palette; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_LOW_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } + + destP = &palette[0xF0 * 3]; + for (int palIndex = 0; palIndex < 16; ++palIndex) { + for (int byteCtr = 2; byteCtr >= 0; --byteCtr) + *destP++ = ((DEFAULT_VGA_HIGH_PALETTE[palIndex] >> (8 * byteCtr)) & 0xff) >> 2; + } +} + +void Palette::setLowRange() { + _mainPalette[0] = _mainPalette[1] = _mainPalette[2] = VGA_COLOR_TRANS(0); + _mainPalette[3] = _mainPalette[4] = _mainPalette[5] = VGA_COLOR_TRANS(0x15); + _mainPalette[6] = _mainPalette[7] = _mainPalette[8] = VGA_COLOR_TRANS(0x2A); + _mainPalette[9] = _mainPalette[10] = _mainPalette[11] = VGA_COLOR_TRANS(0x3F); + _vm->_palette->setPalette(_mainPalette, 0, 4); +} + +void Palette::setColorFlags(byte r, byte g, byte b) { + _colorFlags[0] = r; + _colorFlags[1] = g; + _colorFlags[2] = b; +} + +void Palette::setColorValues(byte r, byte g, byte b) { + _colorValues[0] = r; + _colorValues[1] = g; + _colorValues[2] = b; +} + +void Palette::lock() { + if (_rgbList[31] && !_lockFl) + error("Palette Lock - Unexpected values"); + + _lockFl = true; + _rgbList[31] = true; + + for (int i = 0; i < 256; i++) { + if (_palFlags[i]) + _palFlags[i] |= 0x80000000; + } +} + +void Palette::unlock() { + if (!_lockFl) + return; + + for (int i = 0; i < 256; i++) + _palFlags[i] &= 0x7FFFFFFF; + + _rgbList[31] = false; + _lockFl = false; +} + +void Palette::refreshSceneColors() { + int val = 18; + if (_vm->_game->_scene._cyclingActive) + val += _vm->_game->_scene._totalCycleColors; + + setPalette(_mainPalette + (val * 3), val, 256 - val); +} + +} // End of namespace MADS diff --git a/engines/mads/palette.h b/engines/mads/palette.h new file mode 100644 index 0000000000..ff93b2f2fe --- /dev/null +++ b/engines/mads/palette.h @@ -0,0 +1,330 @@ +/* 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 MADS_PALETTE_H +#define MADS_PALETTE_H + +#include "common/scummsys.h" +#include "common/stream.h" + +namespace MADS { + +class MADSEngine; + +#define PALETTE_USAGE_COUNT 4 + +#define PALETTE_RESERVED_LOW_COUNT 18 +#define PALETTE_RESERVED_HIGH_COUNT 10 + +#define PALETTE_COUNT 256 +#define PALETTE_SIZE (256 * 3) + +/** + * Palette mapping options + */ +enum { + PALFLAG_BACKGROUND = 0x8000, // Loading initial background + PALFLAG_RESERVED = 0x4000, // Enable mapping reserved colors + PALFLAG_ANY_TO_CLOSEST = 0x2000, // Any color can map to closest + PALFLAG_ALL_TO_CLOSEST = 0x1000, // Any colors that can map must map + PALFLAG_TOP_COLORS = 0x0800, // Allow mapping to high four colors + PALFLAG_DEFINE_RESERVED = 0x0400, // Define initial reserved color + PALFLAG_MASK = 0xfc00 // Mask for all the palette flags +}; + +struct PaletteCycle { + byte _colorCount; + byte _firstListColor; + byte _firstColorIndex; + byte _ticks; + + PaletteCycle() { _colorCount = _firstListColor = _firstColorIndex = _ticks = 0; } +}; + +struct RGB6 { + byte r; + byte g; + byte b; + byte _palIndex; + byte _u2; + byte _flags; + + /** + * Load an entry from a stream + */ + void load(Common::SeekableReadStream *f); +}; + +class PaletteUsage { +public: + struct UsageEntry { + uint16 _palIndex; + int _sortValue; + + UsageEntry(int palIndex) { _palIndex = palIndex; _sortValue = -1; } + UsageEntry() { _palIndex = 0; _sortValue = 0; } + }; + struct UsageRange { + byte _v1, _v2; + + UsageRange(byte v1, byte v2) { _v1 = v1; _v2 = v2; } + }; +private: + MADSEngine *_vm; + Common::Array<UsageEntry> *_data; + + int getGamePalFreeIndex(int *palIndex); + + int rgbFactor(byte *palEntry, RGB6 &pal6); + + Common::Array<UsageEntry> _nullUsage; +public: + /** + * Constructor + */ + PaletteUsage(MADSEngine *vm); + + void load(Common::Array<UsageEntry> *data); + + /** + * Returns whether the usage list is empty + */ + bool empty() const { return _data == nullptr; } + + uint16 &operator[](int index) { return (*_data)[index]._palIndex; } + + /** + * Assigns the class to an empty usage array + */ + void setEmpty() { _data = &_nullUsage; } + + /** + * Gets key entries from the passed palette + * @param palette 6-bit per entry read in palette + */ + void getKeyEntries(Common::Array<RGB6> &palette); + + /** + * Prioritizes the palette index list based on the intensity of the + * RGB values of the palette entries that they refer to + */ + void prioritize(Common::Array<RGB6> &palette); + + int process(Common::Array<RGB6> &palette, uint flags); + + void transform(Common::Array<RGB6> &palette); + + void updateUsage(Common::Array<int> &usageList, int sceneUsageIndex); + + void resetPalFlags(int idx); +}; + +class RGBList { +private: + bool _data[32]; +public: + RGBList() { clear(); } + + void clear(); + + void reset(); + + /** + * Copies the data from another instance + */ + void copy(RGBList &src); + + /** + * Scans for a free slot + */ + int scan(); + + bool &operator[](int idx) { return _data[idx]; } +}; + +class Fader { +public: + struct GreyEntry { + byte _intensity; + byte _mapColor; + uint16 _accum[3]; + }; +private: + void mapToGreyRamp(byte palette[PALETTE_SIZE], int baseColor, int numColors, + int baseGrey, int numGreys, GreyEntry *map); + + void getGreyValues(const byte palette[PALETTE_SIZE], byte greyList[PALETTE_COUNT], + int baseColor, int numColors); + + /** + * Given a grey value list containing grey shades (0-63), creates a 64 byte + * grey table containing the number of grey values for each intensity + */ + void greyPopularity(const byte greyList[PALETTE_COUNT], byte greyTable[64], int numColors); + + /** + * Does an insertion sort of a given id/value array pair + */ + void insertionSort(int size, byte *id, byte *value); +protected: + MADSEngine *_vm; + byte _rgb64Map[PALETTE_COUNT]; +public: + bool _colorFlags[4]; + int _colorValues[4]; +public: + /** + * Constructor + */ + Fader(MADSEngine *vm); + + /** + * Sets a new palette + */ + void setPalette(const byte *colors, uint start, uint num); + + /** + * Returns a subset of the currently loaded palette + */ + void grabPalette(byte *colors, uint start, uint num); + + /** + * Gets the entire palette at once + */ + void getFullPalette(byte palette[PALETTE_SIZE]) { + grabPalette(&palette[0], 0, PALETTE_COUNT); + } + + /** + * Sets the entire palette at once + */ + void setFullPalette(byte palette[PALETTE_SIZE]) { + setPalette(&palette[0], 0, PALETTE_COUNT); + } + + /** + * Calculates a merge/hash for a given palette entry + */ + int rgbMerge(byte r, byte g, byte b); + + /** + * Calculates a merge/hash for a given palette entry + */ + int rgbMerge(RGB6 &palEntry); + + /** + * Fades the given palette out to black or grey + */ + void fadeOut(byte palette[PALETTE_SIZE], byte *paletteMap, + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps); + + /** + * Fade into the given palette + */ + void fadeIn(byte palette[PALETTE_SIZE], byte destPalette[PALETTE_SIZE], + int baseColor, int numColors, int baseGrey, int numGreys, + int tickDelay, int steps); +}; + +class Palette : public Fader { +private: + /** + * Initializes the first 16 palette indexes with the equivalent + * standard VGA palette + */ + void initVGAPalette(byte *palette); +public: + byte _mainPalette[PALETTE_SIZE]; + byte _cyclingPalette[PALETTE_SIZE]; + uint32 _palFlags[PALETTE_COUNT]; + PaletteUsage _paletteUsage; + RGBList _rgbList; + bool _lockFl; + int _lowRange; + int _highRange; +public: + /** + * Constructor + */ + Palette(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~Palette() {} + + /** + * Set a palette entry + */ + void setEntry(byte palIndex, byte r, byte g, byte b); + + /** + * Returns the palette index in the palette that most closely matches the + * specified RGB pair + */ + uint8 palIndexFromRgb(byte r, byte g, byte b, byte *paletteData = nullptr); + + /** + * Sets a small set of system/core colors needed by the game + */ + void setSystemPalette(); + + /** + * Update a range of an arbitrary palette + */ + static void setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2); + + /** + * Resets the game palette + */ + void resetGamePalette(int v1, int v2); + + /** + * Initializes the main palette + */ + void initPalette(); + + /** + * Set the first four palette entries with preset values + */ + void setLowRange(); + + /** + * Set up the palette as the game ends + */ + void close() { + warning("TODO: Palette::close"); + } + + void setColorFlags(byte r, byte g, byte b); + void setColorValues(byte r, byte g, byte b); + + void lock(); + void unlock(); + + void refreshSceneColors(); +}; + +} // End of namespace MADS + +#endif /* MADS_PALETTE_H */ diff --git a/engines/mads/phantom/game_phantom.cpp b/engines/mads/phantom/game_phantom.cpp new file mode 100644 index 0000000000..15ac241d8c --- /dev/null +++ b/engines/mads/phantom/game_phantom.cpp @@ -0,0 +1,161 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/phantom/game_phantom.h" +//#include "mads/nebular/dialogs_nebular.h" +//#include "mads/nebular/globals_nebular.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +namespace Phantom { + +GamePhantom::GamePhantom(MADSEngine *vm) + : Game(vm) { + _surface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); + _storyMode = STORYMODE_NAUGHTY; +} + +ProtectionResult GamePhantom::checkCopyProtection() { + /* + // DEBUG: Flag copy protection failure + _globals[5] = -1; + + if (!ConfMan.getBool("copy_protection")) + return true; + + * DEBUG: Disabled for now + CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg->show(); + delete dlg; + */ + + // DEBUG: Return that copy protection failed + return PROTECTION_SUCCEED; +} + +void GamePhantom::initializeGlobals() { + //int count, count2; + //int bad; + + _globals.reset(); + //_globals[kTalkInanimateCount] = 8; + + /* Section #1 variables */ + // TODO + + /* Section #2 variables */ + // TODO + + /* Section #3 variables */ + // TODO + + /* Section #4 variables */ + // TODO + + /* Section #5 variables */ + // TODO + + /* Section #9 variables */ + // TODO + + _player._facing = FACING_NORTH; + _player._turnToFacing = FACING_NORTH; + + //Player::preloadSequences("RXM", 1); + //Player::preloadSequences("ROX", 1); +} + +void GamePhantom::setSectionHandler() { + delete _sectionHandler; + + switch (_sectionNumber) { + case 1: + _sectionHandler = new Section1Handler(_vm); + break; + case 2: + _sectionHandler = new Section2Handler(_vm); + break; + case 3: + _sectionHandler = new Section3Handler(_vm); + break; + case 4: + _sectionHandler = new Section4Handler(_vm); + break; + case 5: + _sectionHandler = new Section5Handler(_vm); + break; + default: + break; + } +} + +void GamePhantom::checkShowDialog() { + // TODO: Copied from Nebular + if (_vm->_dialogs->_pendingDialog && _player._stepEnabled && !_globals[5]) { + _player.releasePlayerSprites(); + _vm->_dialogs->showDialog(); + _vm->_dialogs->_pendingDialog = DIALOG_NONE; + } +} + +void GamePhantom::doObjectAction() { + // TODO: Copied from Nebular + //Scene &scene = _scene; + MADSAction &action = _scene._action; + //Dialogs &dialogs = *_vm->_dialogs; + //int id; + + action._inProgress = false; +} + +void GamePhantom::unhandledAction() { + // TODO +} + +void GamePhantom::step() { + if (_player._visible && _player._stepEnabled && !_player._moving && + (_player._facing == _player._turnToFacing)) { + + // TODO + } + +} + +void GamePhantom::synchronize(Common::Serializer &s, bool phase1) { + Game::synchronize(s, phase1); + + // TODO: Copied from Nebular + if (!phase1) { + _globals.synchronize(s); + } +} + +} // End of namespace Phantom + +} // End of namespace MADS diff --git a/engines/mads/phantom/game_phantom.h b/engines/mads/phantom/game_phantom.h new file mode 100644 index 0000000000..7a84ee1c72 --- /dev/null +++ b/engines/mads/phantom/game_phantom.h @@ -0,0 +1,124 @@ +/* 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 MADS_GAME_PHANTOM_H +#define MADS_GAME_PHANTOM_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/globals.h" +//#include "mads/nebular/globals_nebular.h" + +namespace MADS { + +namespace Phantom { + +// TODO: Adapt for Phantom's difficulty setting +enum StoryMode { STORYMODE_NAUGHTY = 1, STORYMODE_NICE = 2 }; + +enum InventoryObject { + OBJ_NONE = -1, + OBJ_KEY = 0, + OBJ_LANTERN = 1, + OBJ_RED_FRAME = 2, + OBJ_SANDBAG = 3, + OBJ_YELLOW_FRAME = 4, + OBJ_FIRE_AXE = 5, + OBJ_SMALL_NOTE = 6, + OBJ_ROPE = 7, + OBJ_SWORD = 8, + OBJ_ENVELOPE = 9, + OBJ_TICKET = 10, + OBJ_PIECE_OF_PAPER = 11, + OBJ_PARCHMENT = 12, + OBJ_LETTER = 13, + OBJ_NOTICE = 14, + OBJ_BOOK = 15, + OBJ_CRUMPLED_NOTE = 16, + OBJ_BLUE_FRAME = 17, + OBJ_LARGE_NOTE = 18, + OBJ_GREEN_FRAME = 19, + OBJ_MUSIC_SCORE = 20, + OBJ_WEDDING_RING = 21, + OBJ_CABLE_HOOK = 22, + OBJ_ROPE_WITH_HOOK = 23, + OBJ_OAR = 24 +}; + +// HACK: A stub for now, remove from here once it's implemented properly +class PhantomGlobals : public Globals { +public: + PhantomGlobals() { + resize(210); // Rex has 210 globals + } + virtual ~PhantomGlobals() {} +}; + +class GamePhantom : public Game { + friend class Game; +protected: + GamePhantom(MADSEngine *vm); + + virtual ProtectionResult checkCopyProtection(); + + virtual void initializeGlobals(); + + virtual void setSectionHandler(); + + virtual void checkShowDialog(); +public: + PhantomGlobals _globals; + StoryMode _storyMode; + + virtual Globals &globals() { return _globals; } + + virtual void doObjectAction(); + + virtual void unhandledAction(); + + virtual void step(); + + virtual void synchronize(Common::Serializer &s, bool phase1); +}; + + +class Section1Handler : public SectionHandler { +public: + Section1Handler(MADSEngine *vm) : SectionHandler(vm) {} + + // TODO: Properly implement handler methods + virtual void preLoadSection() {} + virtual void sectionPtr2() {} + virtual void postLoadSection() {} +}; + +// TODO: Properly implement handler classes +typedef Section1Handler Section2Handler; +typedef Section1Handler Section3Handler; +typedef Section1Handler Section4Handler; +typedef Section1Handler Section5Handler; + +} // End of namespace Nebular + +} // End of namespace MADS + +#endif /* MADS_GAME_PHANTOM_H */ diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp new file mode 100644 index 0000000000..dbce014525 --- /dev/null +++ b/engines/mads/phantom/phantom_scenes.cpp @@ -0,0 +1,204 @@ +/* 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 "common/scummsys.h" +#include "common/config-manager.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/resources.h" +#include "mads/scene.h" +#include "mads/phantom/game_phantom.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +namespace Phantom { + +SceneLogic *SceneFactory::createScene(MADSEngine *vm) { + Scene &scene = vm->_game->_scene; + + // TODO + //scene.addActiveVocab(NOUN_DROP); + + switch (scene._nextSceneId) { + // Scene group #1 (theater, stage and dressing rooms) + case 101: // seats + return new DummyScene(vm); // TODO + case 102: // music stands + return new DummyScene(vm); // TODO + case 103: // below stage + return new DummyScene(vm); // TODO + case 104: // stage + return new DummyScene(vm); // TODO + case 105: // ground floor, storage room + return new DummyScene(vm); // TODO + case 106: // behind stage + return new DummyScene(vm); // TODO + case 107: // stage right wing + return new DummyScene(vm); // TODO + case 108: // stage left wing + return new DummyScene(vm); // TODO + case 109: // upper floor, staircase + return new DummyScene(vm); // TODO + case 110: // outside dressing rooms 1 + return new DummyScene(vm); // TODO + case 111: // outside dressing rooms 2 + return new DummyScene(vm); // TODO + case 112: // inside dressing room 1 + return new DummyScene(vm); // TODO + case 113: // inside dressing room 2 + return new DummyScene(vm); // TODO + case 114: // lower floor, storage room + return new DummyScene(vm); // TODO + case 150: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #2 (theater entrance, offices, balcony) + case 201: // entrance / ticket office + return new DummyScene(vm); // TODO + case 202: // outside offices / paintings room + return new DummyScene(vm); // TODO + case 203: // office + return new DummyScene(vm); // TODO + case 204: // library + return new DummyScene(vm); // TODO + case 205: // upper floor, outside balcony boxes + return new DummyScene(vm); // TODO + case 206: // balcony box #1 + return new DummyScene(vm); // TODO + case 207: // balcony box #2 + return new DummyScene(vm); // TODO + case 208: // stage and balcony view + return new DummyScene(vm); // TODO + case 250: // cutscene + return new DummyScene(vm); // TODO + + // Scene group #3 (catwalks, chandelier, lake / catacombs entrance) + case 301: // catwalk #1 above stage + return new DummyScene(vm); // TODO + case 302: // catwalk #2 above stage + return new DummyScene(vm); // TODO + case 303: // above chandelier + return new DummyScene(vm); // TODO + case 304: // chandelier + return new DummyScene(vm); // TODO + case 305: // chandelier fight, phantom closeup + return new DummyScene(vm); // TODO + case 306: // chandelier #2 + return new DummyScene(vm); // TODO + case 307: // catwalk #3 above stage + return new DummyScene(vm); // TODO + case 308: // hidden staircase behind balcony box + return new DummyScene(vm); // TODO + case 309: // lake and archway + return new DummyScene(vm); // TODO + case 310: // lake + return new DummyScene(vm); // TODO + + // Scene group #4 (labyrinth) + case 401: // labyrinth room, 3 exits + return new DummyScene(vm); // TODO + case 403: // labyrinth room (big), 4 exits + 1 bricked door, left + return new DummyScene(vm); // TODO + case 404: // labyrinth room, 3 exits + return new DummyScene(vm); // TODO + case 406: // labyrinth room, 2 exits + return new DummyScene(vm); // TODO + case 407: // catacomb room / lake + return new DummyScene(vm); // TODO + case 408: // catacomb corridor + return new DummyScene(vm); // TODO + case 409: // catacomb room, door with switch panel + return new DummyScene(vm); // TODO + case 410: // skull switch panel + return new DummyScene(vm); // TODO + case 453: // Labyrinth room (big), 4 exits + 1 bricked door, right + return new DummyScene(vm); // TODO + case 456: // Labyrinth room, 2 exits + return new DummyScene(vm); // TODO + + // Scene group #5 (Phantom's hideout) + case 501: // catacombs, outside phantom's hideout, lake and boat + return new DummyScene(vm); // TODO + case 502: // push panel trap + return new DummyScene(vm); // TODO + case 504: // Phantom's hideout, church organ + return new DummyScene(vm); // TODO + case 505: // Phantom's hideout, sarcophagus + return new DummyScene(vm); // TODO + case 506: // catacomb room with ramp + return new DummyScene(vm); // TODO + + default: + error("Invalid scene %d called", scene._nextSceneId); + } +} + +/*------------------------------------------------------------------------*/ + +PhantomScene::PhantomScene(MADSEngine *vm) : SceneLogic(vm), + _globals(static_cast<GamePhantom *>(vm->_game)->_globals), + _game(*static_cast<GamePhantom *>(vm->_game)), + _action(vm->_game->_scene._action) { +} + +Common::String PhantomScene::formAnimName(char sepChar, int suffixNum) { + return Resources::formatName(_scene->_currentSceneId, sepChar, suffixNum, + EXT_NONE, ""); +} + +/*------------------------------------------------------------------------*/ + +void SceneInfoPhantom::loadCodes(MSurface &depthSurface, int variant) { + File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT")); + MadsPack codesPack(&f); + Common::SeekableReadStream *stream = codesPack.getItemStream(variant + 1); + + loadCodes(depthSurface, stream); + + delete stream; + f.close(); +} + +void SceneInfoPhantom::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) { + byte *destP = depthSurface.getData(); + byte *endP = depthSurface.getBasePtr(0, depthSurface.h); + + byte runLength = stream->readByte(); + while (destP < endP && runLength > 0) { + byte runValue = stream->readByte(); + + // Write out the run length + Common::fill(destP, destP + runLength, runValue); + destP += runLength; + + // Get the next run length + runLength = stream->readByte(); + } + + if (destP < endP) + Common::fill(destP, endP, 0); +} + +} // End of namespace Phantom + +} // End of namespace MADS diff --git a/engines/mads/phantom/phantom_scenes.h b/engines/mads/phantom/phantom_scenes.h new file mode 100644 index 0000000000..cd295a28b6 --- /dev/null +++ b/engines/mads/phantom/phantom_scenes.h @@ -0,0 +1,521 @@ +/* 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 MADS_PHANTOM_SCENES_H +#define MADS_PHANTOM_SCENES_H + +#include "common/scummsys.h" +#include "mads/game.h" +#include "mads/scene.h" +#include "mads/phantom/game_phantom.h" +//#include "mads/phantom/globals_phantom.h" + + +namespace MADS { + +namespace Phantom { + +enum Noun { + NOUN_GAME = 0x1, + NOUN_QSAVE = 0x2, + NOUN_LOOK = 0x3, + NOUN_TAKE = 0x4, + NOUN_PUSH = 0x5, + NOUN_OPEN = 0x6, + NOUN_PUT = 0x7, + NOUN_TALK_TO = 0x8, + NOUN_GIVE = 0x9, + NOUN_PULL = 0xA, + NOUN_CLOSE = 0xB, + NOUN_THROW = 0xC, + NOUN_WALK_TO = 0xD, + NOUN_ = 0xE, + NOUN_IN_ONE = 0xF, + NOUN_IN_TWO = 0x10, + NOUN_ACT_CURTAIN = 0x11, + NOUN_AISLE = 0x12, + NOUN_APRON = 0x13, + NOUN_ATTACK = 0x14, + NOUN_BACKSTAGE = 0x15, + NOUN_BEAR_PROP = 0x16, + NOUN_BLUE_FRAME = 0x17, + NOUN_BOOK = 0x18, + NOUN_BUST = 0x19, + NOUN_CABLE = 0x1A, + NOUN_CARPET = 0x1B, + NOUN_CARTON = 0x1C, + NOUN_CARTONS = 0x1D, + NOUN_CEILING = 0x1E, + NOUN_CHAIR = 0x1F, + NOUN_CIRCULAR_STAIRCASE = 0x20, + NOUN_CLIMB_DOWN = 0x21, + NOUN_CLIMB_INTO = 0x22, + NOUN_CLIMB_THROUGH = 0x23, + NOUN_COLUMN_PROP = 0x24, + NOUN_CONDUCTORS_STAND = 0x25, + NOUN_CORRIDOR = 0x26, + NOUN_COUCH = 0x27, + NOUN_COUNTERWEIGHT_SYSTEM = 0x28, + NOUN_CRATE = 0x29, + NOUN_CRATES = 0x2A, + NOUN_CRUMPLED_NOTE = 0x2B, + NOUN_CYCLORAMA = 0x2C, + NOUN_CYLINDER = 0x2D, + NOUN_DOOR = 0x2E, + NOUN_DRESSING_ROOM_DOOR = 0x2F, + NOUN_DRESSING_SCREEN = 0x30, + NOUN_DRESSING_TABLE = 0x31, + NOUN_ELEPHANT_PROP = 0x32, + NOUN_ENVELOPE = 0x33, + NOUN_EXIT = 0x34, + NOUN_EXIT_DOWN = 0x35, + NOUN_EXIT_SIGN = 0x36, + NOUN_EXIT_TO = 0x37, + NOUN_EXIT_TO_BACKSTAGE = 0x38, + NOUN_EXIT_TO_CELLAR = 0x39, + NOUN_EXIT_TO_CORRIDOR = 0x3A, + NOUN_EXIT_TO_DRESSING_RMS = 0x3B, + NOUN_EXIT_TO_LEFT_WING = 0x3C, + NOUN_EXIT_TO_PIT = 0x3D, + NOUN_EXIT_TO_RIGHT_WING = 0x3E, + NOUN_EXIT_TO_STAGE = 0x3F, + NOUN_EXIT_TO_STAIRWELL = 0x40, + NOUN_EXIT_TO_TRAP_ROOM = 0x41, + NOUN_EXIT_UP = 0x42, + NOUN_EXPOSED_BRICK = 0x43, + NOUN_FAN = 0x44, + NOUN_FIRE_AXE = 0x45, + NOUN_FL = 0x46, + NOUN_FLAT = 0x47, + NOUN_FLATS = 0x48, + NOUN_FLOOR = 0x49, + NOUN_FOLDING_CHAIRS = 0x4A, + NOUN_GARBAGE_CAN = 0x4B, + NOUN_GRAFFITI = 0x4C, + NOUN_GREEN_FRAME = 0x4D, + NOUN_HEMP = 0x4E, + NOUN_HOLE = 0x4F, + NOUN_HOUSE = 0x50, + NOUN_IN_ONE2 = 0x51, + NOUN_IN_TWO2 = 0x52, + NOUN_JUMP_INTO = 0x53, + NOUN_JUNK = 0x54, + NOUN_KEY = 0x55, + NOUN_LAMP = 0x56, + NOUN_LANTERN = 0x57, + NOUN_LARGE_NOTE = 0x58, + NOUN_LASSO = 0x59, + NOUN_LEG = 0x5A, + NOUN_LETTER = 0x5B, + NOUN_LIGHT_FIXTURE = 0x5C, + NOUN_LOCK = 0x5D, + NOUN_LOCKING_RAIL = 0x5E, + NOUN_LOCKRAIL = 0x5F, + NOUN_LOOK_AT = 0x60, + NOUN_LOOK_THROUGH = 0x61, + NOUN_MANNEQUINS = 0x62, + NOUN_MIRROR = 0x63, + NOUN_MUMMY_PROP = 0x64, + NOUN_MURAL = 0x65, + NOUN_MUSIC_SCORE = 0x66, + NOUN_MUSIC_STAND = 0x67, + NOUN_MUSIC_STANDS = 0x68, + NOUN_NOTHING = 0x69, + NOUN_NOTICE = 0x6A, + NOUN_ORCHESTRA_DOOR = 0x6B, + NOUN_ORCHESTRA_PIT = 0x6C, + NOUN_PAINTING = 0x6D, + NOUN_PARCHMENT = 0x6E, + NOUN_PIECE_OF_PAPER = 0x6F, + NOUN_PIPE = 0x70, + NOUN_PIT = 0x71, + NOUN_PLANT = 0x72, + NOUN_POSTER = 0x73, + NOUN_PROMPTERS_BOX = 0x74, + NOUN_PROP_TABLE = 0x75, + NOUN_PROPS = 0x76, + NOUN_PROSCENIUM_ARCH = 0x77, + NOUN_PURCHASE_LINES = 0x78, + NOUN_RAILING = 0x79, + NOUN_READ = 0x7A, + NOUN_RED_FRAME = 0x7B, + NOUN_REMOVE = 0x7C, + NOUN_ROPE = 0x7D, + NOUN_RUG = 0x7E, + NOUN_SANDBAG = 0x7F, + NOUN_SCAFFOLDING = 0x80, + NOUN_SEATS = 0x81, + NOUN_SIDE_WALL = 0x82, + NOUN_SMALL_NOTE = 0x83, + NOUN_STAGE = 0x84, + NOUN_STAGE_EXIT = 0x85, + NOUN_STAGE_LEFT = 0x86, + NOUN_STAGE_RIGHT = 0x87, + NOUN_STAGEMANAGERS_POST = 0x88, + NOUN_STAIR_UNIT = 0x89, + NOUN_STAIRCASE = 0x8A, + NOUN_STAIRWELL = 0x8B, + NOUN_STOOL = 0x8C, + NOUN_STRIKE = 0x8D, + NOUN_SWORD = 0x8E, + NOUN_TABLE = 0x8F, + NOUN_THE_HOUSE = 0x90, + NOUN_THUNDER_MACHINE = 0x91, + NOUN_TICKET = 0x92, + NOUN_TRAP_CEILING = 0x93, + NOUN_TRAP_DOOR = 0x94, + NOUN_TURN_OFF = 0x95, + NOUN_TURN_ON = 0x96, + NOUN_UNLOCK = 0x97, + NOUN_URN = 0x98, + NOUN_WALK_ACROSS = 0x99, + NOUN_WALK_DOWN = 0x9A, + NOUN_WALK_THROUGH = 0x9B, + NOUN_WALK_UP = 0x9C, + NOUN_WALL = 0x9D, + NOUN_WARDROBE = 0x9E, + NOUN_WASTE_BASKET = 0x9F, + NOUN_WATER_PIPE = 0xA0, + NOUN_WEAR = 0xA1, + NOUN_WEDDING_RING = 0xA2, + NOUN_YELLOW_FRAME = 0xA3, + NOUN_PROP = 0xA4, + NOUN_CLIMB_UP = 0xA5, + NOUN_WALK_ONTO = 0xA6, + NOUN_WALK = 0xA7, + NOUN_LEFT_DOOR = 0xA8, + NOUN_RIGHT_DOOR = 0xA9, + NOUN_DOOR_TO_PIT = 0xAA, + NOUN_HEADPHONES = 0xAB, + NOUN_BOXES = 0xAC, + NOUN_MUG = 0xAD, + NOUN_DINETTE_SET = 0xAE, + NOUN_BOX = 0xAF, + NOUN_CASES = 0xB0, + NOUN_TRASH_BUCKET = 0xB1, + NOUN_CORK_BOARD = 0xB2, + NOUN_HEADSET = 0xB3, + NOUN_GRAND_FOYER = 0xB4, + NOUN_BACK_WALL = 0xB5, + NOUN_BALLET_BAR = 0xB6, + NOUN_THROW_RUGS = 0xB7, + NOUN_COSTUME_RACK = 0xB8, + NOUN_COAT_RACK = 0xB9, + NOUN_PAINTINGS = 0xBA, + NOUN_UMBRELLA = 0xBB, + NOUN_SHELF = 0xBC, + NOUN_CONTAINER = 0xBD, + NOUN_TORN_POSTER = 0xBE, + NOUN_REVIEW = 0xBF, + NOUN_REVIEWS = 0xC0, + NOUN_STAGE_RIGHT_WING = 0xC1, + NOUN_STAGE_LEFT_WING = 0xC2, + NOUN_PEDESTAL = 0xC3, + NOUN_PLANT_PROP = 0xC4, + NOUN_STATUE = 0xC5, + NOUN_BATTEN = 0xC6, + NOUN_BIG_PROP = 0xC7, + NOUN_VENTILATION_DUCT = 0xC8, + NOUN_CHANDELIER = 0xC9, + NOUN_BARRIER = 0xCA, + NOUN_PLACARD = 0xCB, + NOUN_TICKET_WINDOW = 0xCC, + NOUN_ARCHWAY = 0xCD, + NOUN_COLUMN = 0xCE, + NOUN_RAIL = 0xCF, + NOUN_SEAT = 0xD0, + NOUN_LOGE_CORRIDOR = 0xD1, + NOUN_HOUSE_LIGHT = 0xD2, + NOUN_FLOV = 0xD3, + NOUN_LEFT_COLUMN = 0xD4, + NOUN_RIGHT_COLUMN = 0xD5, + NOUN_BOOKCASE = 0xD6, + NOUN_DOORWAY = 0xD7, + NOUN_COMFY_CHAIR = 0xD8, + NOUN_DESK = 0xD9, + NOUN_MANAGERS_CHAIR = 0xDA, + NOUN_DESK_LAMP = 0xDB, + NOUN_WINDOW = 0xDC, + NOUN_SHEERS = 0xDD, + NOUN_TAPESTRY = 0xDE, + NOUN_OVERDOOR_MEDALLION = 0xDF, + NOUN_LATTICEWORK = 0xE0, + NOUN_DECORATIVE_MOLDING = 0xE1, + NOUN_LEFT_DOORWAY = 0xE2, + NOUN_LEFT_ARCHWAY = 0xE3, + NOUN_RIGHT_DOORWAY = 0xE4, + NOUN_RIGHT_ARCHWAY = 0xE5, + NOUN_SOFA = 0xE6, + NOUN_END_TABLE = 0xE7, + NOUN_COFFEE_TABLE = 0xE8, + NOUN_DECORATIVE_VASE = 0xE9, + NOUN_MARBLE_COLUMN = 0xEA, + NOUN_BOX_FIVE = 0xEB, + NOUN_ENTER = 0xEC, + NOUN_BOX_SIX = 0xED, + NOUN_BOX_SEVEN = 0xEE, + NOUN_BOX_EIGHT = 0xEF, + NOUN_BOX_NINE = 0xF0, + NOUN_STEP = 0xF1, + NOUN_PANEL = 0xF2, + NOUN_WALK_BEHIND = 0xF3, + NOUN_MIDDLE_DOORWAY = 0xF4, + NOUN_LIGHT = 0xF5, + NOUN_CANDLE = 0xF6, + NOUN_CASE = 0xF7, + NOUN_HANDLE = 0xF8, + NOUN_AXE = 0xF9, + NOUN_DOOR_CHUNKS = 0xFA, + NOUN_FLO = 0xFB, + NOUN_BULLETIN_BOARD = 0xFC, + NOUN_JULIE = 0xFD, + NOUN_GLASS_CASE = 0xFE, + NOUN_KEYHOLE = 0xFF, + NOUN_MIDDLE_DOOR = 0x100, + NOUN_DRESSING_GOWN = 0x101, + NOUN_MONSIEUR_BRIE = 0x102, + NOUN_CATWALK = 0x103, + NOUN_GRID = 0x104, + NOUN_GIRDER = 0x105, + NOUN_GRIDWORK = 0x106, + NOUN_DUCTWORK = 0x107, + NOUN_OPENING = 0x108, + NOUN_DOME = 0x109, + NOUN_ALCOVE = 0x10A, + NOUN_CHRISTINE_DAAE = 0x10B, + NOUN_CHRISTINE = 0x10C, + NOUN_WOMAN = 0x10D, + NOUN_PROMPTERS_STAND = 0x10E, + NOUN_SUPPORT = 0x10F, + NOUN_OTHER_CATWALK = 0x110, + NOUN_SLOT = 0x111, + NOUN_BEAM_POSITION = 0x112, + NOUN_LIGHTING_INSTRUMENT = 0x113, + NOUN_TARP = 0x114, + NOUN_FACE = 0x115, + NOUN_CATWALK_OVER_HOUSE = 0x116, + NOUN_STAIRCASE_POST = 0x117, + NOUN_JACQUES = 0x118, + NOUN_GENTLEMAN = 0x119, + NOUN_BODY = 0x11A, + NOUN_HOLLOW_COLUMN = 0x11B, + NOUN_UPPER_LEVEL = 0x11C, + NOUN_MIDDLE_LEVEL = 0x11D, + NOUN_LOWER_LEVEL = 0x11E, + NOUN_LADDER = 0x11F, + NOUN_CLIMB = 0x120, + NOUN_CHANDELIER_TRAP = 0x121, + NOUN_PIECE_OF_WOOD = 0x122, + NOUN_CUT_HEMP = 0x123, + NOUN_STONE_WALL = 0x124, + NOUN_LAKE = 0x125, + NOUN_STONE_COLUMN = 0x126, + NOUN_EXIT_THROUGH = 0x127, + NOUN_STONE_FLOOR = 0x128, + NOUN_STONE_ARCHWAY = 0x129, + NOUN_CHARLES = 0x12A, + NOUN_SWITCH = 0x12B, + NOUN_PROMPTERS_SEAT = 0x12C, + NOUN_LEVER = 0x12D, + NOUN_MONSIEUR_RICHARD = 0x12E, + NOUN_JULIE2 = 0x12F, + NOUN_CABLE_HOOK = 0x130, + NOUN_ATTACH = 0x131, + NOUN_ROPE_WITH_HOOK = 0x132, + NOUN_GRAPPLE = 0x133, + NOUN_OAR = 0x134, + NOUN_ORGAN = 0x135, + NOUN_SIT_AT = 0x136, + NOUN_ORGAN_BENCH = 0x137, + NOUN_SIT_ON = 0x138, + NOUN_LARGE_CHAIR = 0x139, + NOUN_SIT_IN = 0x13A, + NOUN_SARCOPHAGUS = 0x13B, + NOUN_SKULL = 0x13C, + NOUN_SKULLS = 0x13D, + NOUN_TOTEM = 0x13E, + NOUN_POLE = 0x13F, + NOUN_CURTAIN = 0x140, + NOUN_TORCH = 0x141, + NOUN_RAMP = 0x142, + NOUN_MADAME_GIRY = 0x143, + NOUN_PANELS = 0x144, + NOUN_MORE_CATACOMBS = 0x145, + NOUN_BLOCKED_ARCHWAY = 0x146, + NOUN_GRATE = 0x147, + NOUN_CATACOMBS = 0x148, + NOUN_TICKET_SELLER = 0x149, + NOUN_USHER = 0x14A, + NOUN_UNLUCKY_ADVENTURER = 0x14B, + NOUN_SWITCH_PANEL = 0x14C, + NOUN_SKULL_SWITCH = 0x14D, + NOUN_TOGGLE = 0x14E, + NOUN_CATACOMB_ROOM = 0x14F, + NOUN_BOX_TEN = 0x150, + NOUN_FOYER = 0x151, + NOUN_WALK_DOWN_STAIRCASE = 0x152, + NOUN_WALK_DOWN_STAIRS_TO = 0x153, + NOUN_HAT_RACK = 0x154, + NOUN_VASE = 0x155, + NOUN_CLOTHES_DUMMY = 0x156, + NOUN_NOTICES = 0x157, + NOUN_ARCHWAY_TO_NORTH = 0x158, + NOUN_ARCHWAY_TO_WEST = 0x159, + NOUN_ARCHWAY_TO_EAST = 0x15A, + NOUN_GATE = 0x15B, + NOUN_NEST = 0x15C, + NOUN_POT = 0x15D, + NOUN_PUDDLE = 0x15E, + NOUN_WEB = 0x15F, + NOUN_PLANK = 0x160, + NOUN_BLOCK = 0x161, + NOUN_RATS_NEST = 0x162, + NOUN_BROKEN_POT = 0x163, + NOUN_STONE = 0x164, + NOUN_DRAIN = 0x165, + NOUN_FATE = 0x166, + NOUN_SKULL_SWITCH_1 = 0x167, + NOUN_SKULL_SWITCH_2 = 0x168, + NOUN_SKULL_SWITCH_3 = 0x169, + NOUN_SKULL_SWITCH_4 = 0x16A, + NOUN_SKULL_SWITCH_5 = 0x16B, + NOUN_SKULL_SWITCH_6 = 0x16C, + NOUN_SKULL_SWITCH_7 = 0x16D, + NOUN_SKULL_SWITCH_8 = 0x16E, + NOUN_SKULL_SWITCH_9 = 0x16F, + NOUN_SKULL_SWITCH_10 = 0x170, + NOUN_SKULL_SWITCH_11 = 0x171, + NOUN_SKULL_SWITCH_12 = 0x172, + NOUN_SKULL_SWITCH_13 = 0x173, + NOUN_SKULL_SWITCH_14 = 0x174, + NOUN_SKULL_SWITCH_15 = 0x175, + NOUN_SKULL_SWITCH_16 = 0x176, + NOUN_SKULL_SWITCH_17 = 0x177, + NOUN_SKULL_SWITCH_18 = 0x178, + NOUN_SKULL_SWITCH_19 = 0x179, + NOUN_SKULL_SWITCH_20 = 0x17A, + NOUN_SKULL_SWITCH_21 = 0x17B, + NOUN_SKULL_SWITCH_22 = 0x17C, + NOUN_SKULL_SWITCH_23 = 0x17D, + NOUN_SKULL_SWITCH_24 = 0x17E, + NOUN_SKULL_SWITCH_25 = 0x17F, + NOUN_SKULL_SWITCH_26 = 0x180, + NOUN_EDGAR_DEGAS = 0x181, + NOUN_CHANDELIER_CABLE = 0x182, + NOUN_COB_WEB = 0x183, + NOUN_SKULL_FACE = 0x184, + NOUN_BOAT = 0x185, + NOUN_HOOK = 0x186, + NOUN_AROUND = 0x187, + NOUN_CANE = 0x188, + NOUN_MASK = 0x189, + NOUN_COVER = 0x18A, + NOUN_PADLOCK = 0x18B, + NOUN_LID = 0x18C, + NOUN_COBWEB = 0x18D, + NOUN_PHANTOM = 0x18E, + NOUN_PAPER = 0x18F +}; + +class SceneFactory { +public: + static SceneLogic *createScene(MADSEngine *vm); +}; + +/** + * Specialized base class for Dragonsphere game scenes + */ +class PhantomScene : public SceneLogic { +protected: + PhantomGlobals &_globals; + GamePhantom &_game; + MADSAction &_action; + + /** + * Forms an animation resource name + */ + Common::String formAnimName(char sepChar, int suffixNum); + + /** + * Plays appropriate sound for entering varous rooms + */ + void lowRoomsEntrySound(); +public: + /** + * Constructor + */ + PhantomScene(MADSEngine *vm); + + void sub7178C(); +}; + +class SceneInfoPhantom : public SceneInfo { + friend class SceneInfo; +protected: + virtual void loadCodes(MSurface &depthSurface, int variant); + + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream); + + /** + * Constructor + */ + SceneInfoPhantom(MADSEngine *vm) : SceneInfo(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class Scene1xx : public PhantomScene { +protected: + /** + * Plays an appropriate sound when entering a scene + */ + void sceneEntrySound() {} + + /** + *Sets the AA file to use for the scene + */ + void setAAName() {} + + /** + * Updates the prefix used for getting player sprites for the scene + */ + void setPlayerSpritesPrefix() {} +public: + Scene1xx(MADSEngine *vm) : PhantomScene(vm) {} +}; + +// TODO: Temporary, remove once implemented properly +class DummyScene : public PhantomScene { +public: + DummyScene(MADSEngine *vm) : PhantomScene(vm) { + warning("Unimplemented scene"); + } + + virtual void setup() {} + virtual void enter() {} + virtual void actions() {} +}; + +} // End of namespace Phantom + +} // End of namespace MADS + +#endif /* MADS_PHANTOM_SCENES_H */ diff --git a/engines/mads/player.cpp b/engines/mads/player.cpp new file mode 100644 index 0000000000..ed585cf636 --- /dev/null +++ b/engines/mads/player.cpp @@ -0,0 +1,794 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/player.h" + +namespace MADS { + +#define PLAYER_SEQ_INDEX -2 + +const int Player::_directionListIndexes[32] = { + 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 +}; + +Player::Player(MADSEngine *vm) + : _vm(vm) { + _action = nullptr; + _facing = FACING_NORTH; + _turnToFacing = FACING_NORTH; + _targetFacing = FACING_NORTH; + _prepareWalkFacing = FACING_NONE; + _mirror = false; + _spritesLoaded = false; + _spritesStart = 0; + _spritesIdx = 0; + _numSprites = 0; + _stepEnabled = false; + _visible = false; + _priorVisible = false; + _needToWalk = false; + _readyToWalk = false; + _beenVisible = false; + _loadsFirst = false; + _loadedFirst = false; + _walkAnywhere = false; + _special = 0; + _ticksAmount = 0; + _priorTimer = 0; + _trigger = 0; + _scalingVelocity = false; + _spritesChanged = false; + _forceRefresh = false; + _highSprites = false; + _currentDepth = 0; + _currentScale = 0; + _frameNumber = 0; + _centerOfGravity = 0; + _frameCount = 0; + _velocity = 0; + _upcomingTrigger = 0; + _trigger = 0; + _frameListIndex = 0; + _stopWalkerIndex = 0; + _totalDistance = 0; + _distAccum = 0; + _pixelAccum = 0; + _deltaDistance = 0; + _xDirection = 0; + _yDirection = 0; + _moving = false; + _walkOffScreen = 0; + _walkOffScreenSceneId = -1; + + Common::fill(&_stopWalkerList[0], &_stopWalkerList[12], 0); + Common::fill(&_stopWalkerTrigger[0], &_stopWalkerTrigger[12], 0); + Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false); +} + +void Player::cancelWalk() { + Scene &scene = _vm->_game->_scene; + _action = &scene._action; + _targetPos = _playerPos; + _targetFacing = FACING_NONE; + _turnToFacing = _facing; + _moving = false; + _walkOffScreen = _walkOffScreenSceneId = 0; + scene._rails.resetRoute(); + _walkAnywhere = false; + + _needToWalk = false; + _readyToWalk = false; +} + +bool Player::loadSprites(const Common::String &prefix) { + Common::String suffixList = "89632741"; + + Common::String newPrefix; + if (prefix.empty()) { + newPrefix = _spritesPrefix; + } else { + _spritesPrefix = prefix; + newPrefix = prefix; + } + + _numSprites = 0; + if (!_spritesPrefix.empty()) { + for (int fileIndex = 0; fileIndex < PLAYER_SPRITES_FILE_COUNT; ++fileIndex) { + Common::String setName = Common::String::format("*%s_%c.SS", + newPrefix.c_str(), suffixList[fileIndex]); + if (fileIndex >= 5) + _highSprites = true; + + _spriteSetsPresent[fileIndex] = true; + + int setIndex = -1; + if (Common::File::exists(setName)) { + setIndex = _vm->_game->_scene._sprites.addSprites(setName, 4); + ++_numSprites; + } else if (fileIndex < 5) { + _highSprites = 0; + return true; + } else { + _spriteSetsPresent[fileIndex] = false; + } + + if (fileIndex == 0) + _spritesStart = setIndex; + } + + _spritesLoaded = true; + _spritesChanged = false; + _highSprites = false; + return false; + } else { + Common::fill(&_spriteSetsPresent[0], &_spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT], false); + _highSprites = false; + return false; + } +} + +void Player::setFinalFacing() { + if (_targetFacing != FACING_NONE) + _turnToFacing = _targetFacing; +} + +void Player::changeFacing() { + int dirIndex = 0, dirIndex2 = 0; + int newDir = 0, newDir2 = 0; + + if (_facing != _turnToFacing) { + // Find the index for the given direction in the player direction list + int tempDir = _facing; + do { + ++dirIndex; + newDir += tempDir; + tempDir = _directionListIndexes[tempDir + 10]; + } while (tempDir != _turnToFacing); + } + + + if (_facing != _turnToFacing) { + // Find the index for the given direction in the player direction list + int tempDir = _facing; + do { + ++dirIndex2; + newDir2 += tempDir; + tempDir = _directionListIndexes[tempDir + 20]; + } while (tempDir != _turnToFacing); + } + + int diff = dirIndex - dirIndex2; + if (diff == 0) + diff = newDir - newDir2; + + _facing = (diff >= 0) ? (Facing)_directionListIndexes[_facing + 20] : + (Facing)_directionListIndexes[_facing + 10]; + selectSeries(); + + if ((_facing == _turnToFacing) && !_moving) + updateFrame(); + + _priorTimer += 1; +} + +void Player::cancelCommand() { + cancelWalk(); + _action->_inProgress = false; +} + +void Player::selectSeries() { + Scene &scene = _vm->_game->_scene; + + clearStopList(); + _mirror = false; + + _spritesIdx = _directionListIndexes[_facing]; + if (!_spriteSetsPresent[_spritesIdx]) { + // Direction isn't present, so use alternate direction, with entries flipped + _spritesIdx -= 4; + _mirror = true; + } + + // If the user isn't to be present (such as for a cutscene), exit immediately + // WORKAROUND: Original didn't do a secondary check for the sprite set being + // present, but it's needed to prevent invalid reads during cutscenes + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesIdx]) + return; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + _velocity = MAX(spriteSet._charInfo->_velocity, 100); + setBaseFrameRate(); + + _frameCount = spriteSet._charInfo->_totalFrames; + if (_frameCount == 0) + _frameCount = spriteSet.getCount(); + + _centerOfGravity = spriteSet._charInfo->_centerOfGravity; + + if ((_frameNumber <= 0) || (_frameNumber > _frameCount)) + _frameNumber = 1; + + _forceRefresh = true; +} + +void Player::updateFrame() { + // WORKAROUND: Prevent character info being referenced when not present + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + return; + + Scene &scene = _vm->_game->_scene; + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + if (!spriteSet._charInfo->_numEntries) { + _frameNumber = 1; + } else { + _frameListIndex = _stopWalkerList[_stopWalkerIndex]; + + if (!_visible) { + _upcomingTrigger = 0; + } else { + _upcomingTrigger = _stopWalkerTrigger[_stopWalkerIndex]; + + if (_stopWalkerIndex > 0) + --_stopWalkerIndex; + } + + // Set the player frame number + int listIndex = ABS(_frameListIndex); + _frameNumber = (_frameListIndex >= 0) ? spriteSet._charInfo->_startFrames[listIndex] : + spriteSet._charInfo->_stopFrames[listIndex]; + + // Set next waiting period in ticks + if (listIndex == 0) { + setBaseFrameRate(); + } else { + _ticksAmount = spriteSet._charInfo->_ticksList[listIndex]; + } + } + + _forceRefresh = true; +} + +void Player::update() { + Scene &scene = _vm->_game->_scene; + + if (_forceRefresh || (_visible != _priorVisible)) { + int slotIndex = getSpriteSlot(); + if (slotIndex >= 0) + scene._spriteSlots[slotIndex]._flags = IMG_ERASE; + + int newDepth = 1; + int yp = MIN(_playerPos.y, (int16)(MADS_SCENE_HEIGHT - 1)); + + for (int idx = 1; idx < 15; ++idx) { + if (scene._sceneInfo->_depthList[newDepth] >= yp) + newDepth = idx + 1; + } + _currentDepth = newDepth; + + // Get the scale + int newScale = getScale(_playerPos.y); + _currentScale = MIN(newScale, 100); + + if (_visible) { + // Player sprite needs to be rendered + SpriteSlot slot; + slot._flags = IMG_UPDATE; + slot._seqIndex = PLAYER_SEQ_INDEX; + slot._spritesIndex = _spritesStart + _spritesIdx; + slot._frameNumber = _mirror ? -_frameNumber : _frameNumber; + slot._position.x = _playerPos.x; + slot._position.y = _playerPos.y + (_centerOfGravity * newScale) / 100; + slot._depth = newDepth; + slot._scale = newScale; + + if (slotIndex >= 0) { + // Check if the existing player slot has the same details, and can be re-used + SpriteSlot &s2 = scene._spriteSlots[slotIndex]; + bool equal = (s2._seqIndex == slot._seqIndex) + && (s2._spritesIndex == slot._spritesIndex) + && (s2._frameNumber == slot._frameNumber) + && (s2._position == slot._position) + && (s2._depth == slot._depth) + && (s2._scale == slot._scale); + + if (equal) + // Undo the prior expiry of the player sprite + s2._flags = IMG_STATIC; + else + slotIndex = -1; + } + + if (slotIndex < 0) { + // New slot needed, so allocate one and copy the slot data + slotIndex = scene._spriteSlots.add(); + scene._spriteSlots[slotIndex] = slot; + } + + // If changing a scene, check to change the scene when the player + // has moved off-screen + if (_walkOffScreen) { + SpriteAsset *asset = scene._sprites[slot._spritesIndex]; + MSprite *frame = asset->getFrame(_frameNumber - 1); + int xScale = frame->w * newScale / 200; + int yScale = frame->h * newScale / 100; + int playerX = slot._position.x; + int playerY = slot._position.y; + + if ((playerX + xScale) < 0 || (playerX + xScale) >= MADS_SCREEN_WIDTH || + playerY < 0 || (playerY + yScale) >= MADS_SCENE_HEIGHT) { + scene._nextSceneId = _walkOffScreen; + _walkOffScreen = 0; + _walkAnywhere = false; + } + } + + } + } + + _beenVisible |= _visible; + _priorVisible = _visible; + _forceRefresh = false; +} + +void Player::clearStopList() { + _stopWalkerList[0] = 0; + _stopWalkerTrigger[0] = 0; + _stopWalkerIndex = 0; + _upcomingTrigger = 0; + _trigger = 0; +} + +void Player::startWalking(const Common::Point &pt, Facing facing) { + Scene &scene = _vm->_game->_scene; + + clearStopList(); + setBaseFrameRate(); + _moving = true; + _targetFacing = facing; + + bool v = scene._depthSurface.getDepthHighBit(pt); + + scene._rails.setupRoute(v, _playerPos, pt); +} + +void Player::walk(const Common::Point &pos, Facing facing) { + cancelWalk(); + _needToWalk = true; + _readyToWalk = true; + _prepareWalkPos = pos; + _prepareWalkFacing = facing; +} + +void Player::nextFrame() { + Scene &scene = _vm->_game->_scene; + + uint32 newTime = _priorTimer + _ticksAmount; + if (scene._frameStartTime >= newTime) { + _priorTimer = scene._frameStartTime; + if (_moving) { + move(); + } else { + idle(); + } + + setFrame(); + update(); + } +} + +void Player::move() { + Scene &scene = _vm->_game->_scene; + Rails &rails = scene._rails; + bool newFacing = false; + + if (_moving) { + while (!_walkOffScreen && _playerPos == _targetPos) { + bool isRouteEmpty = rails.empty(); + if (!isRouteEmpty) { + const WalkNode &node = rails.popNode(); + + _targetPos = node._walkPos; + newFacing = true; + } else if (!_walkOffScreenSceneId) { + // End of walking path + rails.resetRoute(); + _moving = false; + setFinalFacing(); + newFacing = true; + } else { + _walkOffScreen = _walkOffScreenSceneId; + _walkAnywhere = true; + _walkOffScreenSceneId = 0; + _stepEnabled = false; + newFacing = false; + } + + if (!_moving) + break; + } + } + + if (newFacing && _moving) + startMovement(); + + if (_turnToFacing != _facing) + changeFacing(); + else if (!_moving) + updateFrame(); + + int velocity = _velocity; + if (_scalingVelocity && (_totalDistance > 0)) { + int angleRange = 100 - _currentScale; + int angleScale = angleRange * (_posDiff.x - 1) / _totalDistance + _currentScale; + velocity = MAX(1L, (angleScale * _currentScale * velocity) / 10000L); + } + + if (!_moving || (_facing != _turnToFacing)) + return; + + Common::Point newPos = _playerPos; + newFacing = false; + _special = 0; + + if (_distAccum < velocity) { + do { + if (_pixelAccum < _posDiff.x) + _pixelAccum += _posDiff.y; + if (_pixelAccum >= _posDiff.x) { + if ((_posChange.y > 0) || _walkOffScreen) + newPos.y += _yDirection; + --_posChange.y; + _pixelAccum -= _posDiff.x; + } + + if (_pixelAccum < _posDiff.x) { + if ((_posChange.x > 0) || _walkOffScreen) + newPos.x += _xDirection; + --_posChange.x; + } + + if (!_walkAnywhere && !_walkOffScreen && (_walkOffScreenSceneId == 0)) { + newFacing = scene._depthSurface.getDepthHighBit(newPos); + + if (_special == 0) + _special = scene.getDepthHighBits(newPos); + } + + _distAccum += _deltaDistance; + + } while ((_distAccum < velocity) && !newFacing && ((_posChange.x > 0) || (_posChange.y > 0) || (_walkOffScreen != 0))); + } + + _distAccum -= velocity; + + if (newFacing) { + cancelCommand(); + } else { + if (!_walkOffScreen) { + // If the move is complete, make sure the position is exactly on the given destination + if (_posChange.x == 0) + newPos.x = _targetPos.x; + if (_posChange.y == 0) + newPos.y = _targetPos.y; + } + + _playerPos = newPos; + } +} + +void Player::idle() { + Scene &scene = _vm->_game->_scene; + + if (_facing != _turnToFacing) { + // The direction has changed, so reset for new direction + changeFacing(); + return; + } + + if ((_spritesStart + _spritesIdx) < 0 || !_spriteSetsPresent[_spritesStart + _spritesIdx]) + return; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + if (spriteSet._charInfo->_numEntries == 0) + // No entries, so exit immediately + return; + + int frameIndex = ABS(_frameListIndex); + int direction = (_frameListIndex < 0) ? -1 : 1; + + if (frameIndex >= spriteSet._charInfo->_numEntries) { + // Reset back to the start of the list + _frameListIndex = 0; + } else { + _frameNumber += direction; + _forceRefresh = true; + + if (spriteSet._charInfo->_stopFrames[frameIndex] < _frameNumber) { + _trigger = _upcomingTrigger; + updateFrame(); + } + if (spriteSet._charInfo->_startFrames[frameIndex] < _frameNumber) { + _trigger = _upcomingTrigger; + updateFrame(); + } + } +} + +void Player::setFrame() { + if (_moving) { + if (++_frameNumber > _frameCount) + _frameNumber = 1; + _forceRefresh = true; + } else { + if (!_forceRefresh) + idle(); + } +} + +int Player::getSpriteSlot() { + SpriteSlots &spriteSlots = _vm->_game->_scene._spriteSlots; + + for (uint idx = 0; idx < spriteSlots.size(); ++idx) { + if (spriteSlots[idx]._seqIndex == PLAYER_SEQ_INDEX && + spriteSlots[idx]._flags >= IMG_STATIC) + return idx; + } + + return - 1; +} + +int Player::getScale(int yp) { + Scene &scene = _vm->_game->_scene; + + int scale = (scene._bandsRange == 0) ? scene._sceneInfo->_maxScale : + (yp - scene._sceneInfo->_yBandsStart) * scene._scaleRange / scene._bandsRange + + scene._sceneInfo->_minScale; + + return MIN(scale, 100); +} + +void Player::setBaseFrameRate() { + Scene &scene = _vm->_game->_scene; + + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + _ticksAmount = spriteSet._charInfo->_ticksAmount; + if (_ticksAmount == 0) + _ticksAmount = 6; +} + +void Player::startMovement() { + int xDiff = _targetPos.x - _playerPos.x; + int yDiff = _targetPos.y - _playerPos.y; + int srcScale = getScale(_playerPos.y); + int destScale = getScale(_targetPos.y); + + // Sets the X direction + if (xDiff > 0) + _xDirection = 1; + else if (xDiff < 0) + _xDirection = -1; + else + _xDirection = 0; + + // Sets the Y direction + if (yDiff > 0) + _yDirection = 1; + else if (yDiff < 0) + _yDirection = -1; + else + _yDirection = 0; + + xDiff = ABS(xDiff); + yDiff = ABS(yDiff); + int scaleDiff = ABS(srcScale - destScale); + + int xAmt100 = xDiff * 100; + int yAmt100 = yDiff * 100; + int xAmt33 = xDiff * 33; + + int scaleAmount = (_scalingVelocity ? scaleDiff * 3 : 0) + 100 * yDiff / 100; + int scaleAmount100 = scaleAmount * 100; + + // Figure out direction that will need to be moved in + int majorDir; + if (xDiff == 0) { + majorDir = 1; + } else if (yDiff == 0) { + majorDir = 3; + } else { + if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141)) + majorDir = 3; + else if (yDiff <= xDiff) + majorDir = 2; + else if ((scaleAmount100 / xDiff) >= 141) + majorDir = 1; + else + majorDir = 2; + } + + switch (majorDir) { + case 1: + _turnToFacing = (_yDirection <= 0) ? FACING_NORTH : FACING_SOUTH; + break; + case 2: { + _turnToFacing = (Facing)(((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0)); + break; + } + case 3: + _turnToFacing = (_xDirection <= 0) ? FACING_WEST : FACING_EAST; + break; + default: + break; + } + + _totalDistance = sqrt((double)(xAmt100 * xAmt100 + yAmt100 * yAmt100)); + _posDiff.x = xDiff + 1; + _posDiff.y = yDiff + 1; + _posChange.x = xDiff; + _posChange.y = yDiff; + + int majorChange = MAX(xDiff, yDiff); + _deltaDistance = (majorChange == 0) ? 0 : _totalDistance / majorChange; + + if (_playerPos.x > _targetPos.x) + _pixelAccum = MAX(_posChange.x, _posChange.y); + else + _pixelAccum = 0; + + _totalDistance /= 100; + _distAccum = -_deltaDistance; +} + +void Player::newWalk() { + if (_needToWalk && _readyToWalk) { + startWalking(_prepareWalkPos, _prepareWalkFacing); + _needToWalk = false; + } +} + +void Player::addWalker(int walker, int trigger) { + Scene &scene = _vm->_game->_scene; + SpriteAsset &spriteSet = *scene._sprites[_spritesStart + _spritesIdx]; + assert(spriteSet._charInfo); + + if (walker < spriteSet._charInfo->_numEntries && _stopWalkerIndex < 11) { + ++_stopWalkerIndex; + _stopWalkerList[_stopWalkerIndex] = walker; + _stopWalkerTrigger[_stopWalkerIndex] = trigger; + } +} + + +/** +* Releases any sprites used by the player +*/ +void Player::releasePlayerSprites() { + Scene &scene = _vm->_game->_scene; + + if (_spritesLoaded && _numSprites > 0) { + int spriteEnd = _spritesStart + _numSprites - 1; + do { + scene._sprites.remove(spriteEnd); + } while (--spriteEnd >= _spritesStart); + } + + _numSprites = 0; + _spritesLoaded = false; + _spritesChanged = true; + + if (scene._sprites._assetCount > 0) { + warning("Player::releasePlayerSprites(): leftover sprites remain, clearing list"); + scene._sprites.clear(); + } +} + +void Player::synchronize(Common::Serializer &s) { + s.syncAsByte(_moving); + s.syncAsSint16LE(_playerPos.x); + s.syncAsSint16LE(_playerPos.y); + s.syncAsSint16LE(_targetPos.x); + s.syncAsSint16LE(_targetPos.y); + s.syncAsSint16LE(_xDirection); + s.syncAsSint16LE(_yDirection); + s.syncAsSint16LE(_posDiff.x); + s.syncAsSint16LE(_posDiff.y); + s.syncAsSint16LE(_posChange.x); + s.syncAsSint16LE(_posChange.y); + s.syncAsUint16LE(_targetFacing); + s.syncAsSint16LE(_special); + s.syncAsByte(_forceRefresh); + s.syncAsSint16LE(_ticksAmount); + s.syncAsByte(_walkAnywhere); + s.syncAsUint16LE(_walkOffScreenSceneId); + s.syncAsByte(_walkOffScreen); + s.syncAsByte(_needToWalk); + s.syncAsByte(_readyToWalk); + s.syncAsUint16LE(_prepareWalkFacing); + s.syncAsSint16LE(_prepareWalkPos.x); + s.syncAsSint16LE(_prepareWalkPos.y); + s.syncAsByte(_stepEnabled); + s.syncAsByte(_visible); + s.syncAsByte(_priorVisible); + + for (int i = 0; i < 8; ++i) + s.syncAsByte(_spriteSetsPresent[i]); + + s.syncAsByte(_facing); + s.syncAsByte(_turnToFacing); + s.syncAsSint16LE(_spritesIdx); + s.syncAsSint16LE(_frameNumber); + s.syncAsSint16LE(_currentDepth); + s.syncAsSint16LE(_currentScale); + s.syncAsSint16LE(_frameListIndex); + + for (int i = 0; i < 12; ++i) { + s.syncAsSint16LE(_stopWalkerList[i]); + s.syncAsSint16LE(_stopWalkerTrigger[i]); + } + + s.syncAsSint16LE(_stopWalkerIndex); + s.syncAsSint16LE(_upcomingTrigger); + s.syncAsSint16LE(_trigger); + s.syncAsSint16LE(_scalingVelocity); + s.syncAsSint16LE(_pixelAccum); + s.syncAsSint16LE(_distAccum); + s.syncAsSint16LE(_deltaDistance); + s.syncAsSint16LE(_totalDistance); + s.syncAsSint16LE(_velocity); + s.syncAsUint16LE(_frameCount); + s.syncString(_spritesPrefix); + s.syncAsUint32LE(_priorTimer); + s.syncAsByte(_loadsFirst); + s.syncAsByte(_loadedFirst); + s.syncAsByte(_spritesLoaded); + s.syncAsByte(_spritesChanged); + s.syncAsByte(_beenVisible); + s.syncAsSint16LE(_centerOfGravity); + s.syncAsByte(_mirror); +} + +void Player::removePlayerSprites() { + Scene &scene = _vm->_game->_scene; + int heroSpriteId = _spritesStart; + for (int i = 0; i < 8; i++) { + if (_spriteSetsPresent[i]) { + scene._sprites.remove(heroSpriteId++); + _spriteSetsPresent[i] = false; + } + } + + if (scene._activeAnimation != nullptr) + scene._activeAnimation->resetSpriteSetsCount(); + + scene._spriteSlots.fullRefresh(); + _visible = false; +} + +} // End of namespace MADS diff --git a/engines/mads/player.h b/engines/mads/player.h new file mode 100644 index 0000000000..671ac9d16e --- /dev/null +++ b/engines/mads/player.h @@ -0,0 +1,228 @@ +/* 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 MADS_PLAYER_H +#define MADS_PLAYER_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/serializer.h" + +namespace MADS { + +class MADSEngine; +class MADSAction; + +#define PLAYER_SPRITES_FILE_COUNT 8 +#define MAX_ROUTE_NODES 22 + +/** + * Player facings + */ +enum Facing { + FACING_NORTH = 8, FACING_SOUTH = 2, FACING_EAST = 6, FACING_WEST = 4, + FACING_NORTHEAST = 9, FACING_SOUTHEAST = 3, + FACING_SOUTHWEST = 1, FACING_NORTHWEST = 7, + FACING_NONE = 5, FACING_DUMMY = 0 +}; + +class Player { +private: + static const int _directionListIndexes[32]; +private: + MADSEngine *_vm; + bool _highSprites; + bool _spriteSetsPresent[PLAYER_SPRITES_FILE_COUNT]; + bool _mirror; + int _frameCount; + int _frameListIndex; + int _distAccum; + int _pixelAccum; + int _deltaDistance; + int _stopWalkerList[12]; + int _stopWalkerTrigger[12]; + int _totalDistance; + + void clearStopList(); + + /** + * If the player is moving, handles figuring out the correct motion + */ + void move(); + + /** + * Update the player's frame number + */ + void setFrame(); + + /** + * Get the sprite slot index for the player + */ + int getSpriteSlot(); + + /** + * Get the scale for the player at the given Y position + */ + int getScale(int yp); + + /** + * Sets the frame rate for the current sprite set + */ + void setBaseFrameRate(); + + /** + * Starts a player moving to a given destination + */ + void startMovement(); + + void changeFacing(); +public: + MADSAction *_action; + + Facing _facing; + Facing _turnToFacing; + Facing _prepareWalkFacing; + int _xDirection, _yDirection; + Facing _targetFacing; + bool _spritesLoaded; + int _spritesStart; + int _spritesIdx; + int _numSprites; + bool _stepEnabled; + bool _spritesChanged; + bool _visible; + bool _priorVisible; + bool _beenVisible; + bool _walkAnywhere; + int _frameNumber; + bool _loadsFirst; + bool _loadedFirst; + Common::Point _playerPos; + Common::Point _targetPos; + Common::Point _posChange; + Common::Point _posDiff; + Common::Point _prepareWalkPos; + bool _moving; + int _walkOffScreen, _walkOffScreenSceneId; + int _special; + int _ticksAmount; + uint32 _priorTimer; + int _velocity; + int _upcomingTrigger; + int _trigger; + bool _scalingVelocity; + bool _forceRefresh; + bool _needToWalk; + bool _readyToWalk; + int _stopWalkerIndex; + int _centerOfGravity; + int _currentDepth; + int _currentScale; + Common::String _spritesPrefix; +public: + Player(MADSEngine *vm); + + /** + * Load sprites for the player + */ + bool loadSprites(const Common::String &prefix); + + /** + * Called when the player has reached the given destination, start him + * turning to the specified facing + */ + void setFinalFacing(); + + /** + * Stops the player walking + */ + void cancelWalk(); + + /** + * Cancels any oustanding player action + */ + void cancelCommand(); + + /** + * Set up control parameters for the current active series (the + * direction which the player is facing in) */ + void selectSeries(); + + /* + * Moves to the next frame for the currently active player sprite set + */ + void updateFrame(); + + void update(); + + /** + * Handler method for when the player is not moving + */ + void idle(); + + /** + * Starts the player walking towards a given point and direction facing + * @param pos Destination location + * @param facing Direction to face once the destination is reached + */ + void startWalking(const Common::Point &pt, Facing facing); + + /** + * Used by the game scripst to make the player walk to a given destination. + * The difference from startWalking is that this contains several extra + * layers of checking that startWalking bypasses. + */ + void walk(const Common::Point &pos, Facing facing); + + /** + * If a new walk sequence is pending, and has been okayed by the preparser, + * start the actual walking + */ + void newWalk(); + + void nextFrame(); + + /** + * Add a walker to the current queue + */ + void addWalker(int walker, int trigger); + + /** + * Delete any sprites used by the player + */ + void releasePlayerSprites(); + + /** + * Serialize the data of the player + */ + void synchronize(Common::Serializer &s); + + static void preloadSequences(const Common::String &prefix, int level) { + // No implementation in ScummVM + } + + void removePlayerSprites(); +}; + +} // End of namespace MADS + +#endif /* MADS_PLAYER_H */ diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp new file mode 100644 index 0000000000..7f8a56d21b --- /dev/null +++ b/engines/mads/rails.cpp @@ -0,0 +1,277 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/rails.h" + +namespace MADS { + +WalkNode::WalkNode() { + _active = false; + Common::fill(&_distances[0], &_distances[MAX_ROUTE_NODES], 0); +} + +void WalkNode::load(Common::SeekableReadStream *f) { + _walkPos.x = f->readSint16LE(); + _walkPos.y = f->readSint16LE(); + for (int i = 0; i < MAX_ROUTE_NODES; ++i) + _distances[i] = f->readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + +Rails::Rails() { + _depthSurface = nullptr; + _routeLength = 0; + _depthStyle = 0; + _next = 0; +} + +void Rails::load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle) { + // Store the depth surface and depth style to use + _depthSurface = depthSurface; + _depthStyle = depthStyle; + + // Load the passed node list + _nodes.clear(); + + for (uint i = 0; i < nodes.size(); ++i) + _nodes.push_back(nodes[i]); + + // Add two more empty nodes for the start and end points of any walk sequence + _nodes.push_back(WalkNode()); + _nodes.push_back(WalkNode()); +} + + +void Rails::setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos) { + // Reset the nodes in as being inactive + for (uint i = 0; i < _nodes.size(); ++i) + _nodes[i]._active = false; + + // Set the two extra walk nodes to the start and destination positions + setNodePosition(_nodes.size() - 2, srcPos); + setNodePosition(_nodes.size() - 1, destPos); + + // Start constructing route node list + _routeLength = 0x3FFF; + _routeIndexes.clear(); + + // Recursively form a route from the destination walk node back to the player's position + setupRouteNode(&_tempRoute[0], _nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0); + + _next = 0; + if (_routeIndexes.size() > 0) { + Common::Point currPos = srcPos; + for (int routeCtr = size() - 1; (routeCtr >= 0) && !_next; --routeCtr) { + int idx = _routeIndexes[routeCtr]; + const Common::Point &pt = _nodes[idx]._walkPos; + + _next = scanPath(currPos, pt); + currPos = pt; + } + } +} + +void Rails::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) { + WalkNode ¤tNode = _nodes[nodeIndex]; + currentNode._active = true; + + *routeIndexP++ = nodeIndex; + + // Get the index of the ultimate source position (the player) + int subIndex = _nodes.size() - 2; + + int distanceVal = _nodes[nodeIndex]._distances[subIndex]; + if (distanceVal & flags) { + routeLength += distanceVal & 0x3FFF; + if (routeLength < _routeLength) { + // Found a new shorter route to destination, so set up the route with the found one + _routeIndexes.clear(); + for (int i = 0; routeIndexP != &_tempRoute[i]; ++i) + _routeIndexes.push(_tempRoute[i]); + _routeLength = routeLength; + } + } else { + for (int idx = _nodes.size() - 2; idx > 0; --idx) { + int nodePos = idx - 1; + if (!_nodes[nodePos]._active && ((currentNode._distances[nodePos] & flags) != 0)) + setupRouteNode(routeIndexP, nodePos, 0x8000, routeLength + (distanceVal & 0x3fff)); + } + } + + currentNode._active = false; +} + + +int Rails::scanPath(const Common::Point &srcPos, const Common::Point &destPos) { + // For compressed depth surfaces, always return 0 + if (_depthStyle == 2) + return 0; + + int yDiff = destPos.y - srcPos.y; + int yAmount = MADS_SCREEN_WIDTH; + + if (yDiff < 0) { + yDiff = -yDiff; + yAmount = -yAmount; + } + + int xDiff = destPos.x - srcPos.x; + int xDirection = 1; + int xAmount = 0; + if (xDiff < 0) { + xDiff = -xDiff; + xDirection = -xDirection; + xAmount = MIN(yDiff, xDiff); + } + + ++xDiff; + ++yDiff; + + const byte *srcP = _depthSurface->getBasePtr(srcPos.x, srcPos.y); + int index = xAmount; + + // Outer loop + for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) { + index += yDiff; + int v = (*srcP & 0x7F) >> 4; + if (v) + return v; + + // Inner loop for handling vertical movement + while (index >= xDiff) { + index -= xDiff; + + v = (*srcP & 0x7F) >> 4; + if (v) + return v; + + srcP += yAmount; + } + } + + return 0; +} + +void Rails::resetRoute() { + _routeIndexes.clear(); + _next = 0; +} + +const WalkNode &Rails::popNode() { + assert(!_routeIndexes.empty()); + + return _nodes[_routeIndexes.pop()]; +} + +void Rails::setNodePosition(int nodeIndex, const Common::Point &pt) { + int flags, hypotenuse; + + _nodes[nodeIndex]._walkPos = pt; + + // Recalculate inter-node lengths + for (uint idx = 0; idx < _nodes.size(); ++idx) { + int entry; + if (idx == (uint)nodeIndex) { + entry = 0x3FFF; + } else { + // Process the node + flags = getRouteFlags(pt, _nodes[idx]._walkPos); + + int xDiff = ABS(_nodes[idx]._walkPos.x - pt.x); + int yDiff = ABS(_nodes[idx]._walkPos.y - pt.y); + hypotenuse = sqrt((double)(xDiff * xDiff + yDiff * yDiff)); + + if (hypotenuse >= 0x3FFF) + // Shouldn't ever be this large + hypotenuse = 0x3FFF; + + entry = hypotenuse | flags; + } + + _nodes[idx]._distances[nodeIndex] = entry; + _nodes[nodeIndex]._distances[idx] = entry; + } +} + +int Rails::getRouteFlags(const Common::Point &src, const Common::Point &dest) { + int result = 0x8000; + bool flag = false; + + int xDiff = ABS(dest.x - src.x); + int yDiff = ABS(dest.y - src.y); + int xDirection = dest.x >= src.x ? 1 : -1; + int yDirection = dest.y >= src.y ? _depthSurface->w : -_depthSurface->w; + int minorDiff = 0; + if (dest.x < src.x) + minorDiff = MIN(xDiff, yDiff); + ++xDiff; + ++yDiff; + + byte *srcP = _depthSurface->getBasePtr(src.x, src.y); + + int totalCtr = minorDiff; + for (int xCtr = 0; xCtr < xDiff; ++xCtr, srcP += xDirection) { + totalCtr += yDiff; + + if ((*srcP & 0x80) == 0) + flag = false; + else if (!flag) { + flag = true; + result -= 0x4000; + if (result == 0) + break; + } + + while (totalCtr >= xDiff) { + totalCtr -= xDiff; + + if ((*srcP & 0x80) == 0) + flag = false; + else if (!flag) { + flag = true; + result -= 0x4000; + if (result == 0) + break; + } + + srcP += yDirection; + } + if (result == 0) + break; + } + + return result; +} + +void Rails::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_routeLength); + s.syncAsSint16LE(_next); + + if (s.isLoading()) { + _routeIndexes.clear(); + } +} + +} // End of namespace MADS diff --git a/engines/mads/rails.h b/engines/mads/rails.h new file mode 100644 index 0000000000..e6cab08f85 --- /dev/null +++ b/engines/mads/rails.h @@ -0,0 +1,134 @@ +/* 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 MADS_RAILS_H +#define MADS_RAILS_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "common/serializer.h" +#include "common/stack.h" +#include "mads/msurface.h" + +namespace MADS { + +class WalkNode { +public: + Common::Point _walkPos; + uint16 _distances[MAX_ROUTE_NODES]; + bool _active; + + /** + * Constructor + */ + WalkNode(); + + /** + * Loads the scene node + */ + void load(Common::SeekableReadStream *f); +}; +typedef Common::Array<WalkNode> WalkNodeList; + +/** + * This class handles storing the intermediate walk node points for a + * given scene, and calculating walking routes between any two positions. + */ +class Rails { +private: + WalkNodeList _nodes; + DepthSurface *_depthSurface; + int _depthStyle; + int _routeLength; + int _next; + int _tempRoute[MAX_ROUTE_NODES]; + Common::Stack<int> _routeIndexes; +private: + /** + * Change the position of a walking node. Doing so causes a recalculation of the + * distance between it and every other node, and vice versa + */ + void setNodePosition(int nodeIndex, const Common::Point &pt); + + int getRouteFlags(const Common::Point &src, const Common::Point &dest); +public: + /** + * Constructor + */ + Rails(); + + /** + * Loads the scene data for the list of intermediate walk nodes and the + * depth surface to use. + * @param nodes Intermediate walk-points + * @param depthSurface Depth surface to use + */ + void load(const WalkNodeList &nodes, DepthSurface *depthSurface, int depthStyle); + + /** + * Set up a route between two points in a scene + */ + void setupRoute(bool bitFlag, const Common::Point &srcPos, const Common::Point &destPos); + + void setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength); + + /** + * Resets any currently running route + */ + void resetRoute(); + + /** + * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first + * pixel high nibble encountered with a non-zero value + */ + int scanPath(const Common::Point &srcPos, const Common::Point &destPos); + + /* + * Return the number of walk nodes in the calculated route + */ + int size() const { return _routeIndexes.size(); } + + /** + * Returns true if the current calculated walk route is empty + */ + bool empty() const { return _routeIndexes.empty(); } + + /** + * Returns the data for a given walk node + */ + const WalkNode &operator[](int idx) { return _nodes[_routeIndexes[idx]]; } + + const WalkNode &popNode(); + + void resetNext() { _next = 0; } + int getNext() { return _next; } + + /** + * Synchronize the data for the route + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_RAILS_H */ diff --git a/engines/mads/resources.cpp b/engines/mads/resources.cpp new file mode 100644 index 0000000000..1fb75e6ba2 --- /dev/null +++ b/engines/mads/resources.cpp @@ -0,0 +1,417 @@ +/* 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 "common/scummsys.h" +#include "common/archive.h" +#include "common/textconsole.h" +#include "mads/mads.h" +#include "mads/resources.h" + +namespace MADS { + +enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_I, + RESTYPE_OB, RESTYPE_FONT, RESTYPE_SOUND, RESTYPE_SPEECH, RESTYPE_HAS_EXT, RESTYPE_NO_EXT}; + +/** + * HAG Archives implementation + */ +class HagArchive : public Common::Archive { +private: + /** + * Details of a single entry in a HAG file index + */ + struct HagEntry { + Common::String _resourceName; + uint32 _offset; + uint32 _size; + + HagEntry() : _offset(0), _size(0) {} + HagEntry(Common::String resourceName, uint32 offset, uint32 size) + : _resourceName(resourceName), _offset(offset), _size(size) { + } + }; + + class HagIndex { + public: + Common::List<HagEntry> _entries; + Common::String _filename; + }; + + Common::Array<HagIndex> _index; + + /** + * Load the index of all the game's HAG files + */ + void loadIndex(MADSEngine *vm); + + /** + * Given a resource name, opens up the correct HAG file and returns whether + * an entry with the given name exists. + */ + bool getHeaderEntry(const Common::String &resourceName, HagIndex &hagIndex, HagEntry &hagEntry) const; + + /** + * Returns the HAG resource filename that will contain a given resource + */ + Common::String getResourceFilename(const Common::String &resourceName) const; + + /** + * Return a resource type given a resource name + */ + ResourceType getResourceType(const Common::String &resourceName) const; +public: + HagArchive(MADSEngine *vm); + virtual ~HagArchive(); + + // Archive implementation + virtual bool hasFile(const Common::String &name) const; + virtual int listMembers(Common::ArchiveMemberList &list) const; + virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const; + virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const; +}; + +const char *const MADSCONCAT_STRING = "MADSCONCAT"; + +HagArchive::HagArchive(MADSEngine *vm) { + loadIndex(vm); +} + +HagArchive::~HagArchive() { +} + +// Archive implementation +bool HagArchive::hasFile(const Common::String &name) const { + HagIndex hagIndex; + HagEntry hagEntry; + return getHeaderEntry(name, hagIndex, hagEntry); +} + +int HagArchive::listMembers(Common::ArchiveMemberList &list) const { + int members = 0; + + for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) { + HagIndex hagIndex = _index[hagCtr]; + Common::List<HagEntry>::iterator i; + + for (i = hagIndex._entries.begin(); i != hagIndex._entries.end(); ++i) { + list.push_back(Common::ArchiveMemberList::value_type( + new Common::GenericArchiveMember((*i)._resourceName, this))); + ++members; + } + } + + return members; +} + +const Common::ArchiveMemberPtr HagArchive::getMember(const Common::String &name) const { + if (!hasFile(name)) + return Common::ArchiveMemberPtr(); + + return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this)); +} + +Common::SeekableReadStream *HagArchive::createReadStreamForMember(const Common::String &name) const { + HagIndex hagIndex; + HagEntry hagEntry; + + if (getHeaderEntry(name, hagIndex, hagEntry)) { + // Entry found. If the correct file is not already open, open it + Common::File f; + if (!f.open(hagIndex._filename)) + error("Could not open HAG file"); + + // Return a new stream for the specific resource + f.seek(hagEntry._offset); + return f.readStream(hagEntry._size); + } + + return nullptr; +} + +void HagArchive::loadIndex(MADSEngine *vm) { + Common::File hagFile; + + for (int sectionIndex = -1; sectionIndex < 11; ++sectionIndex) { + if (sectionIndex == 0) + continue; + + // Dragonsphere does not have some sections - skip them + if (vm->getGameID() == GType_Dragonsphere) { + if (sectionIndex == 7 || sectionIndex == 8) + continue; + } + + // Phantom does not have some sections - skip them + if (vm->getGameID() == GType_Phantom) { + if (sectionIndex == 6 || sectionIndex == 7 || sectionIndex == 8) + continue; + } + + Common::String filename = (sectionIndex == -1) ? "GLOBAL.HAG" : + Common::String::format("SECTION%d.HAG", sectionIndex); + if (sectionIndex == 10) { + // Speech + if (!Common::File::exists("SPEECH.HAG")) + break; + else + filename = "SPEECH.HAG"; + } + if (!hagFile.open(filename)) + error("Could not locate HAG file - %s", filename.c_str()); + + // Check for header + char headerBuffer[16]; + if ((hagFile.read(headerBuffer, 16) != 16) || + (strncmp(headerBuffer, MADSCONCAT_STRING, 10) != 0)) + error("Invalid HAG file opened"); + + // Scan through the HAG index + int numEntries = hagFile.readUint16LE(); + + HagIndex hagIndex; + hagIndex._filename = filename; + + for (int idx = 0; idx < numEntries; ++idx) { + // Read in the details of the next resource + char resourceBuffer[14]; + uint32 offset = hagFile.readUint32LE(); + uint32 size = hagFile.readUint32LE(); + hagFile.read(resourceBuffer, 14); + + hagIndex._entries.push_back(HagEntry(resourceBuffer, offset, size)); + } + + hagFile.close(); + _index.push_back(hagIndex); + } +} + +bool HagArchive::getHeaderEntry(const Common::String &resourceName, + HagIndex &hagIndex, HagEntry &hagEntry) const { + Common::String resName = resourceName; + resName.toUppercase(); + if (resName[0] == '*') + resName.deleteChar(0); + + Common::String hagFilename = getResourceFilename(resName); + + // Find the index for the given file + for (uint hagCtr = 0; hagCtr < _index.size(); ++hagCtr) { + hagIndex = _index[hagCtr]; + + if (hagIndex._filename == hagFilename) { + Common::List<HagEntry>::iterator ei; + for (ei = hagIndex._entries.begin(); ei != hagIndex._entries.end(); ++ei) { + hagEntry = *ei; + if (hagEntry._resourceName.compareToIgnoreCase(resName) == 0) + return true; + } + } + } + + return false; +} + +Common::String HagArchive::getResourceFilename(const Common::String &resourceName) const { + ResourceType resType = getResourceType(resourceName); + Common::String outputFilename = "GLOBAL.HAG"; + + if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) { + int value = atoi(resourceName.c_str() + 2); + int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value; + + if (hagFileNum > 0) + outputFilename = Common::String::format("SECTION%d.HAG", hagFileNum); + } + + if (resType == RESTYPE_SPEECH) + outputFilename = "SPEECH.HAG"; + + return outputFilename; +} + +ResourceType HagArchive::getResourceType(const Common::String &resourceName) const { + if (resourceName.hasPrefix("RM")) { + // Room resource + return RESTYPE_ROOM; + } else if (resourceName.hasPrefix("SC")) { + // SC resource + return RESTYPE_SC; + } else if (resourceName.hasSuffix(".TXT")) { + // Text resource + return RESTYPE_TEXT; + } else if (resourceName.hasSuffix(".QUO")) { + // QUO resource + return RESTYPE_QUO; + } else if (resourceName.hasPrefix("I")) { + // I resource + return RESTYPE_I; + } else if (resourceName.hasPrefix("OB")) { + // OB resource + return RESTYPE_OB; + } else if (resourceName.hasPrefix("FONT")) { + // FONT resource + return RESTYPE_FONT; + } else if (resourceName.hasPrefix("SOUND")) { + // SOUND resource + return RESTYPE_SOUND; + } else if (resourceName.hasPrefix("SPCHC")) { + // SPEECH resource + return RESTYPE_SPEECH; + } + + // Check for a known extension + const char *extPos = strchr(resourceName.c_str(), '.'); + if (extPos) { + ++extPos; + if (!strcmp(extPos, "FL") || !strcmp(extPos, "LBM") || !strcmp(extPos, "ANM") || + !strcmp(extPos, "AA") || !strcmp(extPos, "SS")) { + return RESTYPE_HAS_EXT; + } + } + + return RESTYPE_NO_EXT; +} + +/*------------------------------------------------------------------------*/ + +void Resources::init(MADSEngine *vm) { + SearchMan.add("HAG", new HagArchive(vm)); +} + +Common::String Resources::formatName(RESPREFIX resType, int id, const Common::String &ext) { + Common::String result = "*"; + + if (resType == 3 && !id) { + id = id / 100; + } + + if (!ext.empty()) { + switch (resType) { + case RESPREFIX_GL: + result += "GL000"; + break; + case RESPREFIX_SC: + result += Common::String::format("SC%.3d", id); + break; + case RESPREFIX_RM: + result += Common::String::format("RM%.3d", id); + break; + default: + break; + } + + result += ext; + } + + return result; +} + +Common::String Resources::formatName(int prefix, char asciiCh, int id, EXTTYPE extType, + const Common::String &suffix) { + Common::String result; + if (prefix <= 0) { + result = "*"; + } else { + result = Common::String::format("%s%.3d", + (prefix < 100) ? "*SC" : "*RM", prefix); + } + + result += Common::String::format("%c", asciiCh); + if (id >= 0) + result += Common::String::format("%d", id); + if (!suffix.empty()) + result += suffix; + + switch (extType) { + case EXT_SS: + result += ".SS"; + break; + case EXT_AA: + result += ".AA"; + break; + case EXT_DAT: + result += ".DAT"; + break; + case EXT_HH: + result += ".HH"; + break; + case EXT_ART: + result += ".ART"; + break; + case EXT_INT: + result += ".INT"; + break; + default: + break; + } + + return result; +} + +Common::String Resources::formatResource(const Common::String &resName, + const Common::String &hagFilename) { +// int v1 = 0, v2 = 0; + + if (resName.hasPrefix("*")) { + // Resource file specified + error("TODO: formatResource"); + } else { + // File outside of hag file + return resName; + } +} + +Common::String Resources::formatAAName(int idx) { + return formatName(0, 'I', idx, EXT_AA, ""); +} + +/*------------------------------------------------------------------------*/ + +void File::openFile(const Common::String &filename) { + if (!Common::File::open(filename)) + error("Could not open file - %s", filename.c_str()); +} + +/*------------------------------------------------------------------------*/ + +void SynchronizedList::synchronize(Common::Serializer &s) { + int v = 0; + int count = size(); + s.syncAsUint16LE(count); + + if (s.isSaving()) { + for (int idx = 0; idx < count; ++idx) { + v = (*this)[idx]; + s.syncAsSint32LE(v); + } + } else { + clear(); + reserve(count); + for (int idx = 0; idx < count; ++idx) { + s.syncAsSint32LE(v); + push_back(v); + } + } +} + +} // End of namespace MADS diff --git a/engines/mads/resources.h b/engines/mads/resources.h new file mode 100644 index 0000000000..8d9ab1e39f --- /dev/null +++ b/engines/mads/resources.h @@ -0,0 +1,89 @@ +/* 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 MADS_RESOURCES_H +#define MADS_RESOURCES_H + +#include "common/scummsys.h" +#include "common/file.h" +#include "common/serializer.h" +#include "common/str.h" + +namespace MADS { + +class MADSEngine; + +enum RESPREFIX { + RESPREFIX_GL = 1, RESPREFIX_SC = 2, RESPREFIX_RM = 3 +}; + +enum EXTTYPE { + EXT_NONE = -1, EXT_SS = 1, EXT_AA = 2, EXT_DAT = 3, EXT_HH = 4, + EXT_ART = 5, EXT_INT = 6 +}; + +class Resources { +public: + /** + * Instantiates the resource manager + */ + static void init(MADSEngine *vm); + + static Common::String formatName(RESPREFIX resType, int id, const Common::String &ext); + static Common::String formatName(int prefix, char asciiCh, int id, + EXTTYPE extType, const Common::String &suffix); + static Common::String formatResource(const Common::String &resName, const Common::String &hagFilename); + static Common::String formatAAName(int idx); +}; + +/** + * Derived file class + */ +class File : public Common::File { +public: + /** + * Constructor + */ + File() : Common::File() {} + + /** + * Constructor + */ + File(const Common::String &filename) { openFile(filename); } + + /** + * Opens the given file, throwing an error if it can't be opened + */ + void openFile(const Common::String &filename); +}; + +class SynchronizedList : public Common::Array<int> { +public: + /** + * Synchronize the list + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_RESOURCES_H */ diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp new file mode 100644 index 0000000000..e98648f009 --- /dev/null +++ b/engines/mads/scene.cpp @@ -0,0 +1,719 @@ +/* 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 "common/scummsys.h" +#include "mads/scene.h" +#include "mads/compression.h" +#include "mads/mads.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +Scene::Scene(MADSEngine *vm) + : _vm(vm), _action(_vm), _depthSurface(vm), + _dirtyAreas(_vm), _dynamicHotspots(vm), _hotspots(vm), + _kernelMessages(vm), _sequences(vm), _sprites(vm), _spriteSlots(vm), + _textDisplay(vm), _userInterface(vm) { + _priorSceneId = 0; + _nextSceneId = 0; + _currentSceneId = 0; + _sceneLogic = nullptr; + _sceneInfo = nullptr; + _cyclingActive = false; + _cyclingThreshold = 0; + _cyclingDelay = 0; + _totalCycleColors = 0; + _depthStyle = 0; + _roomChanged = false; + _reloadSceneFlag = false; + _freeAnimationFlag = false; + _animationData = nullptr; + _activeAnimation = nullptr; + _textSpacing = -1; + _frameStartTime = 0; + _layer = LAYER_GUI; + _lookFlag = false; + _bandsRange = 0; + _scaleRange = 0; + _interfaceY = 0; + _spritesCount = 0; + _variant = 0; + + _paletteUsageF.push_back(PaletteUsage::UsageEntry(0xF)); + + // Set up a scene surface that maps to our physical screen drawing surface + _sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH, + _vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8()); + + // Set up the verb list + _verbList.push_back(VerbInit(VERB_LOOK, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_TAKE, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_PUSH, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_OPEN, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_PUT, VERB_THIS, PREP_RELATIONAL)); + _verbList.push_back(VerbInit(VERB_TALKTO, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_GIVE, VERB_THIS, PREP_TO)); + _verbList.push_back(VerbInit(VERB_PULL, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_CLOSE, VERB_THAT, PREP_NONE)); + _verbList.push_back(VerbInit(VERB_THROW, VERB_THIS, PREP_TO)); +} + +Scene::~Scene() { + delete _sceneLogic; + delete _sceneInfo; +} + +void Scene::clearVocab() { + _activeVocabs.clear(); +} + +void Scene::addActiveVocab(int vocabId) { + if (activeVocabIndexOf(vocabId) == -1) { + assert(_activeVocabs.size() < 200); + _activeVocabs.push_back(vocabId); + } +} + +int Scene::activeVocabIndexOf(int vocabId) { + for (uint i = 0; i < _activeVocabs.size(); ++i) { + if (_activeVocabs[i] == vocabId) + return i; + } + + return -1; +} + +void Scene::clearSequenceList() { + _sequences.clear(); +} + +void Scene::clearMessageList() { + _kernelMessages.clear(); + _talkFont = FONT_CONVERSATION; + _textSpacing = -1; +} + +void Scene::loadSceneLogic() { + delete _sceneLogic; + + switch (_vm->getGameID()) { + case GType_RexNebular: + _sceneLogic = Nebular::SceneFactory::createScene(_vm); + break; + case GType_Dragonsphere: + _sceneLogic = Dragonsphere::SceneFactory::createScene(_vm); + break; + case GType_Phantom: + _sceneLogic = Phantom::SceneFactory::createScene(_vm); + break; + default: + error("Scene logic: Unknown game"); + } +} + +void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) { + // Store the previously active scene number and set the new one + _priorSceneId = _currentSceneId; + _currentSceneId = sceneId; + + _variant = 0; + if (palFlag) + _vm->_palette->resetGamePalette(18, 10); + + _spriteSlots.reset(false); + _sequences.clear(); + _kernelMessages.clear(); + _vm->_palette->_paletteUsage.load(&_scenePaletteUsage); + + int flags = SCENEFLAG_LOAD_SHADOW; + if (_vm->_dithering) + flags |= SCENEFLAG_DITHER; + + _sceneInfo = SceneInfo::init(_vm); + _sceneInfo->load(_currentSceneId, _variant, Common::String(), flags, + _depthSurface, _backgroundSurface); + + // Initialize palette animation for the scene + initPaletteAnimation(_sceneInfo->_paletteCycles, false); + + // Copy over nodes + _rails.load(_sceneInfo->_nodes, &_depthSurface, _sceneInfo->_depthStyle); + + // Load hotspots + loadHotspots(); + + // Load vocab + loadVocab(); + + // Load palette usage + _vm->_palette->_paletteUsage.load(&_paletteUsageF); + + // Load interface + flags = PALFLAG_RESERVED | ANIMFLAG_LOAD_BACKGROUND; + if (_vm->_dithering) + flags |= ANIMFLAG_DITHER; + if (_vm->_textWindowStill) + flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY; + + _animationData = Animation::init(_vm, this); + DepthSurface depthSurface(_vm); + _animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr); + + _vm->_palette->_paletteUsage.load(&_scenePaletteUsage); + + _bandsRange = _sceneInfo->_yBandsEnd - _sceneInfo->_yBandsStart; + _scaleRange = _sceneInfo->_maxScale - _sceneInfo->_minScale; + + _spriteSlots.reset(false); + _interfaceY = MADS_SCENE_HEIGHT; + _spritesCount = _sprites.size(); + + _userInterface.setup(_vm->_game->_screenObjects._inputMode); + + _vm->_game->_screenObjects._category = CAT_NONE; + _vm->_events->showCursor(); +} + +void Scene::loadHotspots() { + File f(Resources::formatName(RESPREFIX_RM, _currentSceneId, ".HH")); + MadsPack madsPack(&f); + bool isV2 = (_vm->getGameID() != GType_RexNebular); + + Common::SeekableReadStream *stream = madsPack.getItemStream(0); + int count = stream->readUint16LE(); + delete stream; + + stream = madsPack.getItemStream(1); + _hotspots.clear(); + for (int i = 0; i < count; ++i) + _hotspots.push_back(Hotspot(*stream, isV2)); + + delete stream; + f.close(); +} + +void Scene::loadVocab() { + // Add all the verbs to the active vocab list + for (uint i = 0; i < _verbList.size(); ++i) + addActiveVocab(_verbList[i]._id); + + // Load the vocabs for any object descriptions and custom actions + for (uint objIndex = 0; objIndex < _vm->_game->_objects.size(); ++objIndex) { + InventoryObject &io = _vm->_game->_objects[objIndex]; + addActiveVocab(io._descId); + + for (int vocabIndex = 0; vocabIndex <io._vocabCount; ++vocabIndex) { + addActiveVocab(io._vocabList[vocabIndex]._vocabId); + } + } + + // Load scene hotspot list vocabs and verbs + for (uint i = 0; i < _hotspots.size(); ++i) { + addActiveVocab(_hotspots[i]._vocabId); + if (_hotspots[i]._verbId) + addActiveVocab(_hotspots[i]._verbId); + } + + loadVocabStrings(); +} + +void Scene::loadVocabStrings() { + _vocabStrings.clear(); + File f("*VOCAB.DAT"); + Common::String msg; + + for (;;) { + char c = (char)f.readByte(); + if (f.eos()) break; + + if (c == '\0') { + _vocabStrings.push_back(msg); + msg = ""; + } else { + msg += c; + } + } + + f.close(); +} + +uint32 Scene::getVocabStringsCount() const { + return _vocabStrings.size(); +} + +void Scene::initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag) { + // Initialize the animation palette and ticks list + _cycleTicks.clear(); + _paletteCycles.clear(); + + for (uint i = 0; i < palCycles.size(); ++i) { + _cycleTicks.push_back(_vm->_events->getFrameCounter()); + _paletteCycles.push_back(palCycles[i]); + } + + // Save the initial starting palette + Common::copy(&_vm->_palette->_mainPalette[0], &_vm->_palette->_mainPalette[PALETTE_SIZE], + &_vm->_palette->_cyclingPalette[0]); + + // Calculate total + _totalCycleColors = 0; + for (uint i = 0; i < _paletteCycles.size(); ++i) + _totalCycleColors += _paletteCycles[i]._colorCount; + + _cyclingThreshold = (_totalCycleColors > 16) ? 3 : 0; + _cyclingActive = animFlag; +} + +void Scene::animatePalette() { + byte rgb[3]; + + if (_cyclingActive) { + Scene::_cyclingDelay++; + if (_cyclingDelay >= _cyclingThreshold) { + uint32 frameCounter = _vm->_events->getFrameCounter(); + bool changesFlag = false; + for (uint16 idx = 0; idx < _paletteCycles.size(); idx++) { + if (frameCounter >= (_cycleTicks[idx] + _paletteCycles[idx]._ticks)) { + _cycleTicks[idx] = frameCounter; + int count = _paletteCycles[idx]._colorCount; + int first = _paletteCycles[idx]._firstColorIndex; + int listIndex = _paletteCycles[idx]._firstListColor; + changesFlag = true; + + if (count > 1) { + // Make a copy of the last color + byte *pSrc = &_vm->_palette->_cyclingPalette[first * 3]; + byte *pEnd = pSrc + count * 3; + Common::copy(pEnd - 3, pEnd, &rgb[0]); + + // Shift the cycle palette forward one entry + Common::copy_backward(pSrc, pEnd - 3, pEnd); + + // Move the saved color to the start of the cycle + Common::copy(&rgb[0], &rgb[3], pSrc); + + if (++listIndex >= count) + listIndex = 0; + } + + _paletteCycles[idx]._firstListColor = listIndex; + } + } + + if (changesFlag) { + int firstColor = _paletteCycles[0]._firstColorIndex; + byte *pSrc = &_vm->_palette->_cyclingPalette[firstColor * 3]; + _vm->_palette->setPalette(pSrc, firstColor, _totalCycleColors); + } + + _cyclingDelay = 0; + } + } +} + +bool Scene::getDepthHighBits(const Common::Point &pt) { + if (_sceneInfo->_depthStyle == 2) { + return 0; + } else { + const byte *p = _depthSurface.getBasePtr(pt.x, pt.y); + return (*p & 0x70) >> 4; + } +} + +void Scene::loop() { + while (!_vm->shouldQuit() && !_reloadSceneFlag && (_nextSceneId == _currentSceneId)) { + // Handle drawing a game frame + doFrame(); + + // TODO: Verify correctness of frame wait + _vm->_events->waitForNextFrame(); + + if (_vm->_dialogs->_pendingDialog != DIALOG_NONE && !_vm->_game->_trigger + && _vm->_game->_player._stepEnabled) + _reloadSceneFlag = true; + } +} + +void Scene::doFrame() { + Player &player = _vm->_game->_player; + bool flag = false; + + if (_action._selectedAction || !player._stepEnabled) { + _action.clear(); + _action._selectedAction = 0; + } + + if (!_vm->_game->_trigger && !player._trigger) { + // Refresh the dynamic hotspots if they've changed + if (_dynamicHotspots._changed) + _dynamicHotspots.refresh(); + + // Check all on-screen visual objects + _vm->_game->_screenObjects.check(player._stepEnabled && !player._needToWalk && + !_vm->_game->_fx); + } + + if (_action._selectedAction && player._stepEnabled && !player._needToWalk && + !_vm->_game->_trigger && !player._trigger) { + _action.startAction(); + if (_action._activeAction._verbId == Nebular::VERB_LOOK_AT) { + _action._activeAction._verbId = VERB_LOOK; + _action._savedFields._command = false; + } + + flag = true; + } + + if (flag || (_vm->_game->_trigger && _vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE)) { + doPreactions(); + } + + player.newWalk(); + if (!_vm->_game->_fx) + _frameStartTime = _vm->_events->getFrameCounter(); + + // Handle parser actions as well as game triggers + if ((_action._inProgress && !player._moving && !player._needToWalk && + (player._facing == player._turnToFacing) && !_vm->_game->_trigger) || + (_vm->_game->_trigger && (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER))) { + doAction(); + } + + if (_currentSceneId != _nextSceneId) { + _freeAnimationFlag = true; + } else { + doSceneStep(); + checkKeyboard(); + + if (_currentSceneId != _nextSceneId) { + _freeAnimationFlag = true; + } else { + player.nextFrame(); + + // Cursor update code + updateCursor(); + + if (!_vm->_game->_trigger) { + // Handle any active sequences + _sequences.tick(); + + // Handle any active animation + if (_activeAnimation) + _activeAnimation->update(); + } + + // If the debugget flag is set, show the mouse position + int mouseTextIndex = 0; + if (_vm->_debugger->_showMousePos) { + Common::Point pt = _vm->_events->mousePos(); + Common::String msg = Common::String::format("(%d,%d)", pt.x, pt.y); + mouseTextIndex = _kernelMessages.add(Common::Point(5, 5), + 0x203, 0, 0, 1, msg); + } + + if (!_vm->_game->_trigger) { + if (_reloadSceneFlag || _currentSceneId != _nextSceneId) + _kernelMessages.reset(); + _kernelMessages.update(); + } + + _userInterface._uiSlots.draw(!_vm->_game->_fx, _vm->_game->_fx); + + // Write any text needed by the interface + if (_vm->_game->_fx) + _userInterface.drawTextElements(); + + // Draw any elements + drawElements((ScreenTransition)_vm->_game->_fx, _vm->_game->_fx); + + // Handle message updates + if (_vm->_game->_fx) { + uint32 priorTime = _vm->_game->_priorFrameTimer; + uint32 newTime = _vm->_events->getFrameCounter(); + _sequences.delay(newTime, priorTime); + _kernelMessages.delay(newTime, priorTime); + } + + if (_vm->_debugger->_showMousePos) + // Mouse position display isn't persistent, so remove it + _kernelMessages.remove(mouseTextIndex); + + // Original had a debugger check/call here to allow pausing after + // drawing each frame. Not implemented under ScummVM + } + } + + if (_vm->_game->_fx) + _cyclingActive = true; + _vm->_game->_fx = kTransitionNone; + + if (_freeAnimationFlag) + freeAnimation(); +} + +void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) { + // Draw any sprite backgrounds + _spriteSlots.drawBackground(); + + // Set up dirty areas for any text display + _textDisplay.setDirtyAreas(); + + // Merge any identified dirty areas + _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); + + // Copy background for the dirty areas to the screen + _dirtyAreas.copy(&_backgroundSurface, &_vm->_screen, _posAdjust); + + // Handle dirty areas for foreground objects + if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games + _spriteSlots.setDirtyAreas(); + _textDisplay.setDirtyAreas2(); + _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); + + // Draw sprites that have changed + if (_vm->getGameID() == GType_RexNebular) // TODO: Implement for V2 games + _spriteSlots.drawSprites(&_sceneSurface); + + // Draw text elements onto the view + _textDisplay.draw(&_vm->_screen); + + if (transitionType) { + // Fading in the screen + _vm->_screen.transition(transitionType, surfaceFlag); + _vm->_sound->startQueuedCommands(); + } else { + // Copy dirty areas to the screen + _dirtyAreas.copyToScreen(_vm->_screen._offset); + } + + _spriteSlots.cleanUp(); + _textDisplay.cleanUp(); +} + +void Scene::doPreactions() { + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) { + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PREPARE; + _action.checkAction(); + _sceneLogic->preActions(); + + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PREPARE) + _vm->_game->_trigger = 0; + } +} + +void Scene::doAction() { + bool flag = false; + + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_PARSER; + if ((_action._inProgress || _vm->_game->_trigger) && !_action._savedFields._commandError) { + _sceneLogic->actions(); + flag = !_action._inProgress; + } + + if (_vm->_game->_screenObjects._inputMode == kInputConversation) { + _action._inProgress = false; + } else { + if ((_action._inProgress || _vm->_game->_trigger) || + (!flag && _action._savedFields._commandError == flag)) { + _vm->_game->_sectionHandler->sectionPtr2(); + flag = !_action._inProgress; + } + + if ((_action._inProgress || _vm->_game->_trigger) && + (!flag || _action._savedFields._commandError == flag)) { + _vm->_game->doObjectAction(); + } + + if (!_action._savedFields._lookFlag) { + if (_action._inProgress) { + _action._savedFields._commandError = true; + _sceneLogic->postActions(); + } + + if (_action._inProgress) { + _action._savedFields._commandError = true; + _sceneLogic->unhandledAction(); + } + + if (_action._inProgress) + _vm->_game->unhandledAction(); + } + } + + _action._inProgress = false; + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_PARSER) + _vm->_game->_trigger = 0; +} + +void Scene::doSceneStep() { + _vm->_game->_triggerSetupMode = SEQUENCE_TRIGGER_DAEMON; + _sceneLogic->step(); + _vm->_game->_sectionHandler->step(); + _vm->_game->step(); + + if (_vm->_game->_triggerMode == SEQUENCE_TRIGGER_DAEMON) + _vm->_game->_trigger = 0; +} + +void Scene::checkKeyboard() { + if (_vm->_events->isKeyPressed()) { + Common::Event evt = _vm->_events->_pendingKeys.pop(); + _vm->_game->handleKeypress(evt); + } + + if ((_vm->_events->_mouseStatus & 3) == 3 && _vm->_game->_player._stepEnabled) { + _reloadSceneFlag = true; + _vm->_dialogs->_pendingDialog = DIALOG_GAME_MENU; + _action.clear(); + _action._selectedAction = 0; + } +} + +void Scene::loadAnimation(const Common::String &resName, int trigger) { + // WORKAROUND: If there's already a previous active animation used by the + // scene, then free it before we create the new one + if (_activeAnimation) + freeAnimation(); + + DepthSurface depthSurface(_vm); + UserInterface interfaceSurface(_vm); + + _activeAnimation = Animation::init(_vm, this); + _activeAnimation->load(interfaceSurface, depthSurface, resName, + _vm->_dithering ? ANIMFLAG_DITHER : 0, nullptr, nullptr); + _activeAnimation->startAnimation(trigger); +} + +void Scene::updateCursor() { + Player &player = _vm->_game->_player; + + CursorType cursorId = CURSOR_ARROW; + if (_action._interAwaiting == AWAITING_COMMAND && !_vm->_events->_rightMousePressed && + _vm->_game->_screenObjects._category == CAT_HOTSPOT) { + int idx = _vm->_game->_screenObjects._selectedObject - + _userInterface._categoryIndexes[CAT_HOTSPOT - 1]; + assert(idx >= 0); + + if (idx >= (int)_hotspots.size()) { + idx -= _hotspots.size(); + _vm->_events->_newCursorId = _dynamicHotspots[idx]._cursor; + } else { + idx = _hotspots.size() - idx - 1; + _vm->_events->_newCursorId = _hotspots[idx]._cursor; + } + + cursorId = _vm->_events->_newCursorId == CURSOR_NONE ? + CURSOR_ARROW : _vm->_events->_newCursorId; + } + + if (!player._stepEnabled) + cursorId = CURSOR_WAIT; + if (cursorId >= _vm->_events->_cursorSprites->getCount()) + cursorId = (CursorType)_vm->_events->_cursorSprites->getCount(); + _vm->_events->_newCursorId = cursorId; + + if (cursorId != _vm->_events->_cursorId) { + _vm->_events->setCursor(cursorId); + } +} + +void Scene::freeCurrentScene() { + if (_animationData) { + delete _animationData; + _animationData = nullptr; + } + if (_activeAnimation) { + delete _activeAnimation; + _activeAnimation = nullptr; + } + + _vm->_palette->_paletteUsage.load(nullptr); + _hotspots.clear(); + _backgroundSurface.free(); + _depthSurface.free(); + + delete _sceneInfo; + _sceneInfo = nullptr; +} + +void Scene::removeSprites() { + for (int idx = _sprites.size() - 1; idx >= _spritesCount; --idx) + _sprites.remove(idx); +} + +void Scene::changeVariant(int variant) { + _variant = variant; + _sceneInfo->loadCodes(_depthSurface, variant); + _spriteSlots.fullRefresh(); +} + +void Scene::resetScene() { + _vm->_game->clearQuotes(); + _spriteSlots.fullRefresh(true); + _sequences.clear(); +} + +void Scene::freeAnimation() { + if (_activeAnimation) { + Player &player = _vm->_game->_player; + + if (!_freeAnimationFlag) { + _spriteSlots.fullRefresh(true); + _sequences.scan(); + } + + // Refresh the player + if (player._visible) { + player._forceRefresh = true; + player.update(); + } + + // Remove any kernel messages in use by the animation + for (uint i = 0; i < _activeAnimation->_messages.size(); ++i) { + int msgIndex = _activeAnimation->_messages[i]._kernelMsgIndex; + if (msgIndex >= 0) + _kernelMessages.remove(msgIndex); + } + + // Delete the animation + delete _activeAnimation; + _activeAnimation = nullptr; + } + + _freeAnimationFlag = false; +} + +void Scene::synchronize(Common::Serializer &s) { + _action.synchronize(s); + _rails.synchronize(s); + _userInterface.synchronize(s); + s.syncAsByte(_reloadSceneFlag); + s.syncAsByte(_roomChanged); + s.syncAsUint16LE(_nextSceneId); + s.syncAsUint16LE(_priorSceneId); + _dynamicHotspots.synchronize(s); +} + +} // End of namespace MADS diff --git a/engines/mads/scene.h b/engines/mads/scene.h new file mode 100644 index 0000000000..407d70dc85 --- /dev/null +++ b/engines/mads/scene.h @@ -0,0 +1,251 @@ +/* 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 MADS_SCENE_H +#define MADS_SCENE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/assets.h" +#include "mads/screen.h" +#include "mads/hotspots.h" +#include "mads/messages.h" +#include "mads/msurface.h" +#include "mads/scene_data.h" +#include "mads/animation.h" +#include "mads/rails.h" +#include "mads/sequence.h" +#include "mads/sprites.h" +#include "mads/user_interface.h" + +namespace MADS { + +class Scene { +private: + /** + * Return the index of a given Vocab in the active vocab list + */ + int activeVocabIndexOf(int vocabId); + + /** + * Secondary loading vocab list + */ + void loadVocabStrings(); + + /* + * Initializes the data for palette animation within the scene + */ + void initPaletteAnimation(Common::Array<PaletteCycle> &palCycles, bool animFlag); + + /** + * Handles a single frame within the game scene + */ + void doFrame(); + + void doPreactions(); + + void doAction(); + + /** + * Calls all the necessary step handlers for the current frame + */ + void doSceneStep(); + + /** + * Checks whether there's a pending keypress, and if so handles it. + */ + void checkKeyboard(); + + /** + * Checks for a highlighted hotspot, and updates the cursor accordingly + */ + void updateCursor(); +protected: + MADSEngine *_vm; +public: + SceneLogic *_sceneLogic; + MSurface _sceneSurface; + int _priorSceneId; + int _nextSceneId; + int _currentSceneId; + Common::Array<VerbInit> _verbList; + TextDisplayList _textDisplay; + SpriteSlots _spriteSlots; + SpriteSets _sprites; + DynamicHotspots _dynamicHotspots; + Common::Array<int> _activeVocabs; + SequenceList _sequences; + KernelMessages _kernelMessages; + Rails _rails; + Common::String _talkFont; + int _textSpacing; + Hotspots _hotspots; + DirtyAreas _dirtyAreas; + int _variant; + SceneInfo *_sceneInfo; + MSurface _backgroundSurface; + DepthSurface _depthSurface; + UserInterface _userInterface; + bool _cyclingActive; + int _cyclingThreshold; + int _cyclingDelay; + int _totalCycleColors; + Common::Array<uint32> _cycleTicks; + Common::Array<PaletteCycle> _paletteCycles; + Common::StringArray _vocabStrings; + Animation *_animationData; + Animation *_activeAnimation; + bool _freeAnimationFlag; + int _depthStyle; + int _bandsRange; + int _scaleRange; + int _interfaceY; + int _spritesCount; + MADSAction _action; + bool _roomChanged; + bool _reloadSceneFlag; + Common::Point _posAdjust; + uint32 _frameStartTime; + Layer _layer; + bool _lookFlag; + Common::Point _customDest; + Common::Array<PaletteUsage::UsageEntry> _paletteUsageF; + Common::Array<PaletteUsage::UsageEntry> _scenePaletteUsage; + + /** + * Constructor + */ + Scene(MADSEngine *vm); + + /** + * Destructor + */ + ~Scene(); + + /** + * Clear the vocabulary list + */ + void clearVocab(); + + /** + * Add a given vocab entry to the active list + */ + void addActiveVocab(int vocabId); + + /** + * Get the number of entries in the game's vocabulary + */ + uint32 getVocabStringsCount() const; + + /** + * Clear the sequence list + */ + void clearSequenceList(); + + /** + * Clear the message list + */ + void clearMessageList(); + + /** + * Loads the scene logic for a given scene + */ + void loadSceneLogic(); + + /** + * Loads the resources associated with the given scene + * @param sceneId Scene to load + * @param prefix Prefix to use for retrieving animation data + * @param palFlag Flag for whether to reset the high/lo palette areas + */ + void loadScene(int sceneId, const Common::String &prefix, bool palFlag); + + /** + * Loads the hotstpots for the scene + */ + void loadHotspots(); + + /** + * Loads the vocab list + */ + void loadVocab(); + + bool getDepthHighBits(const Common::Point &pt); + + /** + * Main scene loop + */ + void loop(); + + /** + * Draw all the elements onto the scene + */ + void drawElements(ScreenTransition transitionType, bool surfaceFlag); + + /** + * Handles cycling palette colors for the scene + */ + void animatePalette(); + + /** + * Load an animation + */ + void loadAnimation(const Common::String &resName, int trigger = 0); + + /** + * Returns a vocab entry + */ + Common::String getVocab(int vocabId) { return _vocabStrings[vocabId - 1]; } + + /** + * Clear the data for the currently loaded scene + */ + void freeCurrentScene(); + + /** + * Set the walk surface for a scene to a different variant + */ + void changeVariant(int variant); + + void resetScene(); + + /** + * Removes all the scene specific sprites fromt the sprites list, + * leaving any player sprites list in place at the start of the list. + */ + void removeSprites(); + + /** + * Frees any currently active animation for the scene + */ + void freeAnimation(); + + /** + * Synchronize the game + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_SCENE_H */ diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp new file mode 100644 index 0000000000..d53a668fd3 --- /dev/null +++ b/engines/mads/scene_data.cpp @@ -0,0 +1,463 @@ +/* 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 "common/scummsys.h" +#include "mads/scene_data.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/screen.h" +#include "mads/resources.h" +#include "mads/dragonsphere/dragonsphere_scenes.h" +#include "mads/nebular/nebular_scenes.h" +#include "mads/phantom/phantom_scenes.h" + +namespace MADS { + +KernelMessage::KernelMessage() { + _flags = 0; + _sequenceIndex = 0; + _color1 = 0; + _color2 = 0; + _msgOffset = 0; + _numTicks = 0; + _frameTimer2 = 0; + _frameTimer = 0; + _timeout = 0; + _trigger = 0; + _abortMode = SEQUENCE_TRIGGER_PARSER; + _actionDetails._verbId = VERB_NONE; + _actionDetails._objectNameId = 0; + _actionDetails._indirectObjectId = 0; + _textDisplayIndex = 0; +} + +/*------------------------------------------------------------------------*/ + +void ARTHeader::load(Common::SeekableReadStream *f, bool isV2) { + if (!isV2) { + // Read in dimensions of image + _width = f->readUint16LE(); + _height = f->readUint16LE(); + } + + // Read in palette information + int palCount = f->readUint16LE(); + for (int i = 0; i < palCount; ++i) { + RGB6 rgb; + rgb.load(f); + _palette.push_back(rgb); + } + f->skip(6 * (256 - palCount)); + + // Read palette animations + int cycleCount = f->readUint16LE(); + for (int i = 0; i < cycleCount; ++i) { + PaletteCycle cycle; + cycle._colorCount = f->readByte(); + cycle._firstListColor = f->readByte(); + cycle._firstColorIndex = f->readByte(); + cycle._ticks = f->readByte(); + + _paletteCycles.push_back(cycle); + } +} + +/*------------------------------------------------------------------------*/ + +void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) { + f->skip(3); + _spriteSetIndex = f->readByte(); + f->skip(2); + _position.x = f->readSint16LE(); + _position.y = f->readSint16LE(); + _depth = f->readByte(); + _scale = f->readByte(); +} + +/*------------------------------------------------------------------------*/ + +SceneInfo::SceneInfo(MADSEngine *vm) : _vm(vm) { + _sceneId = 0; + _artFileNum = 0; + _depthStyle = 0; + _width = 0; + _height = 0; + _yBandsEnd = 0; + _yBandsStart = 0; + _maxScale = 0; + _minScale = 0; + _field4A = 0; + _usageIndex = 0; + for (int i = 0; i < 15; ++i) + _depthList[i] = 0; +} + +SceneInfo *SceneInfo::init(MADSEngine *vm) { + switch (vm->getGameID()) { + case GType_RexNebular: + return new Nebular::SceneInfoNebular(vm); + case GType_Dragonsphere: + return new Dragonsphere::SceneInfoDragonsphere(vm); + case GType_Phantom: + return new Phantom::SceneInfoPhantom(vm); + default: + error("SceneInfo: Unknown game"); + } + + return nullptr; +} + +void SceneInfo::load(int sceneId, int variant, const Common::String &resName, + int flags, DepthSurface &depthSurface, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + + // Figure out the resource to use + Common::String resourceName; + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT"); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Open the scene info resource for access + File infoFile(resourceName); + MadsPack infoPack(&infoFile); + + // Read in basic data + Common::SeekableReadStream *infoStream = infoPack.getItemStream(0); + if (_vm->getGameID() == GType_RexNebular) { + _sceneId = infoStream->readUint16LE(); + } else { + infoStream->skip(6); // actual scene ID (string) + _sceneId = sceneId; + } + + // TODO: The following isn't quite right for V2 games (it's all 0) + _artFileNum = infoStream->readUint16LE(); + _depthStyle = infoStream->readUint16LE(); + _width = infoStream->readUint16LE(); + _height = infoStream->readUint16LE(); + + // HACK for V2 games (for now) + if (_vm->getGameID() != GType_RexNebular) { + _width = 320; + _height = 156; + } + + infoStream->skip(24); + + int nodeCount = infoStream->readUint16LE(); + _yBandsEnd = infoStream->readUint16LE(); + _yBandsStart = infoStream->readUint16LE(); + _maxScale = infoStream->readUint16LE(); + _minScale = infoStream->readUint16LE(); + for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) + _depthList[i] = infoStream->readUint16LE(); + _field4A = infoStream->readUint16LE(); + + // Load the set of objects that are associated with the scene + for (int i = 0; i < 20; ++i) { + WalkNode node; + node.load(infoStream); + + if (i < nodeCount) + _nodes.push_back(node); + } + + int spriteSetsCount = infoStream->readUint16LE(); + int spriteInfoCount = infoStream->readUint16LE(); + + // Load in sprite sets + Common::StringArray setNames; + for (int i = 0; i < 10; ++i) { + char name[64]; + infoStream->read(name, 64); + + if (i < spriteSetsCount) + setNames.push_back(Common::String(name)); + } + + // Load in sprite draw information + Common::Array<SpriteInfo> spriteInfo; + // TODO: The following isn't quite right for V2 games + if (_vm->getGameID() == GType_RexNebular) { + for (int i = 0; i < 50; ++i) { + SpriteInfo info; + info.load(infoStream); + + if (i < spriteInfoCount) + spriteInfo.push_back(info); + } + } + delete infoStream; + + int width = _width; + int height = _height; + + if (!bgSurface.getPixels()) { + bgSurface.setSize(width, height); + } + + if (_depthStyle == 2) + width >>= 2; + if (!depthSurface.getPixels()) { + depthSurface.setSize(width, height); + } + + if (_vm->getGameID() == GType_RexNebular) { + // Load the depth surface with the scene codes + Common::SeekableReadStream *depthStream = infoPack.getItemStream(variant + 1); + loadCodes(depthSurface, depthStream); + delete depthStream; + } + + infoFile.close(); + + if (_vm->getGameID() == GType_RexNebular) { + loadMadsV1Background(sceneId, resName, flags, bgSurface); + loadPalette(sceneId, _artFileNum, resName, flags, bgSurface); + } else { + loadMadsV2Background(sceneId, resName, flags, bgSurface); + loadPalette(sceneId, sceneId, resName, flags, bgSurface); + } + + Common::Array<SpriteAsset *> spriteSets; + Common::Array<int> usageList; + + // TODO: The following isn't quite right for V2 games + if (_vm->getGameID() == GType_RexNebular) { + for (uint i = 0; i < setNames.size(); ++i) { + Common::String setResName; + if (sceneFlag || resName.hasPrefix("*")) + setResName += "*"; + setResName += setNames[i]; + + SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags); + spriteSets.push_back(sprites); + usageList.push_back(sprites->_usageIndex); + } + } + + _vm->_palette->_paletteUsage.updateUsage(usageList, _usageIndex); + + for (uint i = 0; i < spriteInfo.size(); ++i) { + SpriteInfo &si = spriteInfo[i]; + SpriteAsset *asset = spriteSets[si._spriteSetIndex]; + assert(asset && _depthStyle != 2); + + MSprite *spr = asset->getFrame(asset->getCount() - 1); + bgSurface.copyFromScaled(spr, si._position, si._depth, &depthSurface, + si._scale, spr->getTransparencyIndex()); + } + + // Free the sprite sets + for (int i = (int)spriteSets.size() - 1; i >= 0; --i) { + _vm->_palette->_paletteUsage.resetPalFlags(spriteSets[i]->_usageIndex); + delete spriteSets[i]; + } +} + +void SceneInfo::loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + Common::String resourceName; + bool isV2 = (_vm->getGameID() != GType_RexNebular); + Common::String extension = !isV2 ? ".ART" : ".TT"; + int paletteStream = !isV2 ? 0 : 2; + + // Get the ART resource + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, artFileNum, extension); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Load in the ART header and palette + File artFile(resourceName); + MadsPack artResource(&artFile); + Common::SeekableReadStream *stream = artResource.getItemStream(paletteStream); + + ARTHeader artHeader; + artHeader.load(stream, isV2); + delete stream; + + // Copy out the palette animation data + for (uint i = 0; i < artHeader._paletteCycles.size(); ++i) + _paletteCycles.push_back(artHeader._paletteCycles[i]); + + if (!(flags & 1)) { + if (!_vm->_palette->_paletteUsage.empty()) { + _vm->_palette->_paletteUsage.getKeyEntries(artHeader._palette); + _vm->_palette->_paletteUsage.prioritize(artHeader._palette); + } + + _usageIndex = _vm->_palette->_paletteUsage.process(artHeader._palette, + (flags & 0xF800) | 0x8000); + if (_usageIndex > 0) { + _vm->_palette->_paletteUsage.transform(artHeader._palette); + + for (uint i = 0; i < _paletteCycles.size(); ++i) { + byte listColor = _paletteCycles[i]._firstListColor; + _paletteCycles[i]._firstColorIndex = artHeader._palette[listColor]._palIndex; + } + } + } + + if (!(flags & 1)) { + // Translate the background to use the correct palette indexes + bgSurface.translate(artHeader._palette); + } +} + +void SceneInfo::loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { + bool sceneFlag = sceneId >= 0; + Common::String resourceName; + Common::SeekableReadStream *stream; + + // Get the ART resource + if (sceneFlag) { + resourceName = Resources::formatName(RESPREFIX_RM, _artFileNum, ".ART"); + } else { + resourceName = "*" + Resources::formatResource(resName, resName); + } + + // Load in the ART data + File artFile(resourceName); + MadsPack artResource(&artFile); + + // Read in the background surface data + assert(_width == bgSurface.w && _height == bgSurface.h); + stream = artResource.getItemStream(1); + stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h); + + // Close the ART file + delete stream; + artFile.close(); +} + +void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface) { + Common::String tileMapResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".MM"); + File tileMapFile(tileMapResourceName); + MadsPack tileMapPack(&tileMapFile); + Common::SeekableReadStream *mapStream = tileMapPack.getItemStream(0); + + // Get the details of the tiles and map + mapStream->readUint32LE(); + int tileCountX = mapStream->readUint16LE(); + int tileCountY = mapStream->readUint16LE(); + int tileWidthMap = mapStream->readUint16LE(); + int tileHeightMap = mapStream->readUint16LE(); + int screenWidth = mapStream->readUint16LE(); + int screenHeight = mapStream->readUint16LE(); + int tileCountMap = tileCountX * tileCountY; + delete mapStream; + + // Obtain tile map information + typedef Common::List<Common::SharedPtr<MSurface> > TileSetList; + typedef TileSetList::iterator TileSetIterator; + TileSetList tileSet; + uint16 *tileMap = new uint16[tileCountMap]; + mapStream = tileMapPack.getItemStream(1); + for (int i = 0; i < tileCountMap; ++i) + tileMap[i] = mapStream->readUint16LE(); + delete mapStream; + tileMapFile.close(); + + // -------------------------------------------------------------------------------- + + // Tile data, which needs to be kept compressed, as the tile map offsets refer to + // the compressed data. Each tile is then uncompressed separately + Common::String tileDataResourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".TT"); + File tileDataFile(tileDataResourceName); + MadsPack tileDataPack(&tileDataFile); + Common::SeekableReadStream *tileDataUncomp = tileDataPack.getItemStream(0); + + // Validate that the data matches between the tiles and tile map file and is valid + int tileCount = tileDataUncomp->readUint16LE(); + int tileWidth = tileDataUncomp->readUint16LE(); + int tileHeight = tileDataUncomp->readUint16LE(); + delete tileDataUncomp; + assert(tileCountMap == tileCount); + assert(tileWidth == tileWidthMap); + assert(tileHeight == tileHeightMap); + assert(screenWidth == _width); + assert(screenHeight <= _height); + + // -------------------------------------------------------------------------------- + + // Get tile data + + tileDataUncomp = tileDataPack.getItemStream(1); + FabDecompressor fab; + uint32 compressedTileDataSize = 0; + + for (int i = 0; i < tileCount; i++) { + tileDataUncomp->seek(i * 4, SEEK_SET); + uint32 tileOfs = tileDataUncomp->readUint32LE(); + MSurface* newTile = new MSurface(tileWidth, tileHeight); + + if (i == tileCount - 1) + compressedTileDataSize = tileDataFile.size() - tileOfs; + else + compressedTileDataSize = tileDataUncomp->readUint32LE() - tileOfs; + + //debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize); + + newTile->empty(); + + byte *compressedTileData = new byte[compressedTileDataSize]; + + tileDataFile.seek(tileDataPack.getDataOffset() + tileOfs, SEEK_SET); + tileDataFile.read(compressedTileData, compressedTileDataSize); + + fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->getPixels(), tileWidth * tileHeight); + tileSet.push_back(TileSetList::value_type(newTile)); + delete[] compressedTileData; + } + + delete tileDataUncomp; + + // -------------------------------------------------------------------------------- + + // Loop through the mapping data to place the tiles on the screen + + uint16 *tIndex = &tileMap[0]; + for (int y = 0; y < tileCountY; y++) { + for (int x = 0; x < tileCountX; x++) { + int tileIndex = *tIndex++; + assert(tileIndex < tileCount); + TileSetIterator tile = tileSet.begin(); + for (int i = 0; i < tileIndex; i++) + ++tile; + ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight)); + } + } + tileSet.clear(); + tileDataFile.close(); +} + +/*------------------------------------------------------------------------*/ + +SceneLogic::SceneLogic(MADSEngine *vm) : _vm(vm) { + _scene = &_vm->_game->_scene; +} + +} // End of namespace MADS diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h new file mode 100644 index 0000000000..783a9ab8a9 --- /dev/null +++ b/engines/mads/scene_data.h @@ -0,0 +1,224 @@ +/* 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 MADS_SCENE_DATA_H +#define MADS_SCENE_DATA_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/serializer.h" +#include "common/str.h" +#include "common/str-array.h" +#include "common/rect.h" +#include "mads/action.h" +#include "mads/assets.h" +#include "mads/events.h" +#include "mads/game_data.h" +#include "mads/hotspots.h" +#include "mads/messages.h" +#include "mads/rails.h" +#include "mads/user_interface.h" + +namespace MADS { + +class MADSEngine; +class Scene; +class SpriteSlot; + +#define MADS_INTERFACE_HEIGHT 44 +#define MADS_SCENE_HEIGHT 156 + +#define DEPTH_BANDS_SIZE 15 + +#define SPRITE_SLOTS_MAX_SIZE 50 +#define TEXT_DISPLAY_MAX_SIZE 40 +#define DIRTY_AREAS_SIZE (SPRITE_SLOTS_MAX_SIZE + TEXT_DISPLAY_MAX_SIZE) + +enum { + SCENEFLAG_DITHER = 0x01, // Dither to 16 colors + SCENEFLAG_LOAD_SHADOW = 0x10 // Load hard shadows +}; + +class VerbInit { +public: + int _id; + VerbType _verbType; + PrepType _prepType; + + VerbInit() {} + VerbInit(int id, VerbType verbType, PrepType prepType) + : _id(id), _verbType(verbType), _prepType(prepType) { + } +}; + +class SceneLogic { +protected: + MADSEngine *_vm; + Scene *_scene; +public: + /** + * Constructor + */ + SceneLogic(MADSEngine *vm); + + /** + * Destructor + */ + virtual ~SceneLogic() {} + + /** + * Called to initially setup a scene + */ + virtual void setup() = 0; + + /** + * Called as the scene is entered (made active) + */ + virtual void enter() = 0; + + /** + * Called one per frame + */ + virtual void step() {} + + /** + * Called before an action is started + */ + virtual void preActions() {} + + /** + * Handles scene actions + */ + virtual void actions() = 0; + + /** + * Post-action handling + */ + virtual void postActions() {} + + /** + * Unhandled action handling + */ + virtual void unhandledAction() {} + + /** + * Synchronize any local data for the scene + */ + virtual void synchronize(Common::Serializer &s) {} +}; + +struct ARTHeader { + int _width; + int _height; + Common::Array<RGB6> _palette; + Common::Array<PaletteCycle> _paletteCycles; + + void load(Common::SeekableReadStream *f, bool isV2); +}; + +/** + * Handles general data for a given scene + */ +class SceneInfo { + class SpriteInfo { + public: + int _spriteSetIndex; + Common::Point _position; + int _depth; + int _scale; + + void load(Common::SeekableReadStream *f); + }; +protected: + MADSEngine *_vm; + + /** + * Constructor + */ + SceneInfo(MADSEngine *vm); +public: + int _sceneId; + int _artFileNum; + int _depthStyle; + int _width; + int _height; + + int _yBandsEnd; + int _yBandsStart; + int _maxScale; + int _minScale; + int _depthList[DEPTH_BANDS_SIZE]; + int _field4A; // Useless field ? + + int _usageIndex; + Common::Array<PaletteCycle> _paletteCycles; + WalkNodeList _nodes; +public: + /** + * Destructor + */ + virtual ~SceneInfo() {} + + /** + * Instantiates the class + */ + static SceneInfo *init(MADSEngine *vm); + + /** + * loads the data + */ + void load(int sceneId, int variant, const Common::String &resName, int flags, + DepthSurface &depthSurface, MSurface &bgSurface); + + /** + * Loads the palette for a scene + */ + void loadPalette(int sceneId, int artFileNum, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads a V1 game background + */ + void loadMadsV1Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads a V2 game background + */ + void loadMadsV2Background(int sceneId, const Common::String &resName, int flags, MSurface &bgSurface); + + /** + * Loads the given surface with depth information of a given scene + * @param depthSurface Depth/walk surface + * @param variant Variant number to load + */ + virtual void loadCodes(MSurface &depthSurface, int variant) = 0; + + /** + * Loads the given surface with depth information of a given scene + * @param depthSurface Depth/walk surface + * @param stream Stream to load the data from + */ + virtual void loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) = 0; +}; + +} // End of namespace MADS + +#endif /* MADS_SCENE_DATA_H */ diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp new file mode 100644 index 0000000000..91aa3abdb0 --- /dev/null +++ b/engines/mads/screen.cpp @@ -0,0 +1,642 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/game.h" +#include "mads/screen.h" +#include "mads/palette.h" +#include "mads/user_interface.h" + +namespace MADS { + +MADSEngine *DirtyArea::_vm = nullptr; + +DirtyArea::DirtyArea() { + _active = false; + _textActive = false; + _mergedArea = nullptr; +} + +void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) { + if (_bounds.left % 2) { + --_bounds.left; + ++width; + } + + if (_bounds.left < 0) + _bounds.left = 0; + else if (_bounds.left > maxWidth) + _bounds.left = maxWidth; + int right = _bounds.left + width; + if (right < 0) + right = 0; + if (right > maxWidth) + right = maxWidth; + + _bounds.right = right; + + if (_bounds.top < 0) + _bounds.top = 0; + else if (_bounds.top > maxHeight) + _bounds.top = maxHeight; + int bottom = _bounds.top + height; + if (bottom < 0) + bottom = 0; + if (bottom > maxHeight) + bottom = maxHeight; + + _bounds.bottom = bottom; + _active = true; +} + + +void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) { + int width, height; + Scene &scene = _vm->_game->_scene; + + if (spriteSlot->_flags == IMG_REFRESH) { + // Special entry to refresh the entire screen + _bounds.left = 0; + _bounds.top = 0; + width = MADS_SCREEN_WIDTH; + height = MADS_SCENE_HEIGHT; + } else { + // Standard sprite slots + _bounds.left = spriteSlot->_position.x - scene._posAdjust.x; + _bounds.top = spriteSlot->_position.y - scene._posAdjust.y; + + SpriteAsset &spriteSet = *scene._sprites[spriteSlot->_spritesIndex]; + MSprite *frame = spriteSet.getFrame(ABS(spriteSlot->_frameNumber) - 1); + + if (spriteSlot->_scale == -1) { + width = frame->w; + height = frame->h; + } else { + width = frame->w * spriteSlot->_scale / 100; + height = frame->h * spriteSlot->_scale / 100; + + _bounds.left -= width / 2; + _bounds.top += -(height - 1); + } + } + + setArea(width, height, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); +} + +void DirtyArea::setTextDisplay(const TextDisplay *textDisplay) { + _bounds.left = textDisplay->_bounds.left; + _bounds.top = textDisplay->_bounds.top; + + setArea(textDisplay->_bounds.width(), textDisplay->_bounds.height(), + MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT); +} + +void DirtyArea::setUISlot(const UISlot *slot) { + int type = slot->_flags; + if (type <= IMG_UPDATE_ONLY) + type += -IMG_UPDATE_ONLY; + if (type >= 0x40) + type &= ~0x40; + + MSurface &intSurface = _vm->_game->_scene._userInterface; + switch (type) { + case IMG_REFRESH: + _bounds.left = 0; + _bounds.top = 0; + setArea(intSurface.w, intSurface.h, intSurface.w, intSurface.h); + break; + + case IMG_OVERPRINT: + _bounds.left = slot->_position.x; + _bounds.top = slot->_position.y; + _bounds.setWidth(slot->_width); + _bounds.setHeight(slot->_height); + setArea(slot->_width, slot->_height, intSurface.w, intSurface.h); + break; + + default: { + SpriteAsset *asset = _vm->_game->_scene._sprites[slot->_spritesIndex]; + MSprite *frame = asset->getFrame(slot->_frameNumber - 1); + int w = frame->w; + int h = frame->h; + + if (slot->_segmentId == IMG_SPINNING_OBJECT) { + _bounds.left = slot->_position.x; + _bounds.top = slot->_position.y; + } else { + _bounds.left = slot->_position.x + w / 2; + _bounds.top = slot->_position.y - h + 1; + } + + setArea(w, h, intSurface.w, intSurface.h); + break; + } + } +} + +/*------------------------------------------------------------------------*/ + +DirtyAreas::DirtyAreas(MADSEngine *vm) : _vm(vm) { + DirtyArea::_vm = vm; + + for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) { + DirtyArea rec; + rec._active = false; + push_back(rec); + } +} + +void DirtyAreas::merge(int startIndex, int count) { + if (startIndex >= count) + return; + + for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) { + if (!(*this)[outerCtr]._active) + continue; + + for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) { + if (!(*this)[innerCtr]._active || !intersects(outerCtr, innerCtr)) + continue; + + if ((*this)[outerCtr]._textActive && (*this)[innerCtr]._textActive) + mergeAreas(innerCtr, outerCtr); + } + } +} + +/** +* Returns true if two dirty areas intersect +*/ +bool DirtyAreas::intersects(int idx1, int idx2) { + return (*this)[idx1]._bounds.intersects((*this)[idx2]._bounds); +} + +void DirtyAreas::mergeAreas(int idx1, int idx2) { + DirtyArea &da1 = (*this)[idx1]; + DirtyArea &da2 = (*this)[idx2]; + + da1._bounds.extend(da2._bounds); + + da2._active = false; + da2._mergedArea = &da1; + da1._textActive = true; +} + +void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust) { + for (uint i = 0; i < size(); ++i) { + const Common::Rect &srcBounds = (*this)[i]._bounds; + + // Check if this is a sane rectangle before attempting to create it + if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom) + continue; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + + if ((*this)[i]._active && bounds.isValidRect()) { + srcSurface->copyTo(destSurface, bounds, Common::Point(bounds.left, bounds.top)); + } + } +} + +void DirtyAreas::copyToScreen(const Common::Point &posAdjust) { + for (uint i = 0; i < size(); ++i) { + const Common::Rect &srcBounds = (*this)[i]._bounds; + + // Check if this is a sane rectangle before attempting to create it + if (srcBounds.left >= srcBounds.right || srcBounds.top >= srcBounds.bottom) + continue; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + + if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) { + _vm->_screen.copyRectToScreen(bounds); + } + } +} + +void DirtyAreas::reset() { + for (uint i = 0; i < size(); ++i) + (*this)[i]._active = false; +} + +/*------------------------------------------------------------------------*/ + +ScreenObject::ScreenObject() { + _category = CAT_NONE; + _descId = 0; + _layer = 0; + _active = false; +} + +/*------------------------------------------------------------------------*/ + +ScreenObjects::ScreenObjects(MADSEngine *vm) : _vm(vm) { + _objectY = -1; + _forceRescan = false; + _inputMode = kInputBuildingSentences; + _v7FED6 = 0; + _v8332A = 0; + _category = CAT_NONE; + _spotId = 0; + _released = false; + _uiCount = 0; + _selectedObject = -1; + _eventFlag = false; + _baseTime = 0; +} + +void ScreenObjects::add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId) { + //assert(size() < 100); + + ScreenObject so; + so._bounds = bounds; + so._category = category; + so._descId = descId; + so._layer = layer; + so._active = true; + + push_back(so); +} + +void ScreenObjects::check(bool scanFlag) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + + if (!_vm->_events->_mouseButtons || _inputMode != kInputBuildingSentences) + _vm->_events->_rightMousePressed = false; + + if ((_vm->_events->_mouseMoved || userInterface._scrollbarActive + || _v8332A || _forceRescan) && scanFlag) { + _category = CAT_NONE; + _selectedObject = scanBackwards(_vm->_events->currentPos(), LAYER_GUI); + if (_selectedObject > 0) { + ScreenObject &scrObject = (*this)[_selectedObject]; + _category = (ScrCategory)(scrObject._category & 7); + _spotId = scrObject._descId; + } + + // Handling for easy mouse + ScrCategory category = scene._userInterface._category; + if (_vm->_easyMouse && _vm->_events->_mouseButtons && category != _category + && scene._userInterface._category != CAT_NONE) { + _released = true; + if (category >= CAT_COMMAND && category <= CAT_TALK_ENTRY) { + elementHighlighted(); + } + + scene._action.checkActionAtMousePos(); + } + + //_released = _vm->_events->_mouseReleased; + if (_vm->_events->_vD2 || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) + scene._userInterface._category = _category; + + if (!_vm->_events->_mouseButtons || _vm->_easyMouse) { + if (userInterface._category >= CAT_COMMAND && userInterface._category <= CAT_TALK_ENTRY) { + elementHighlighted(); + } + } + + if (_vm->_events->_mouseButtons || (_vm->_easyMouse && scene._action._interAwaiting > AWAITING_COMMAND + && scene._userInterface._category == CAT_INV_LIST) || + (_vm->_easyMouse && scene._userInterface._category == CAT_HOTSPOT)) { + scene._action.checkActionAtMousePos(); + } + + if (_vm->_events->_mouseReleased) { + scene._action.leftClick(); + scene._userInterface._category = CAT_NONE; + } + + if (_vm->_events->_mouseButtons || _vm->_easyMouse || userInterface._scrollbarActive) + scene._userInterface.updateInventoryScroller(); + + if (_vm->_events->_mouseButtons || _vm->_easyMouse) + scene._action.set(); + + _forceRescan = false; + } + + scene._action.refresh(); + + uint32 currentTicks = _vm->_events->getFrameCounter(); + if (currentTicks >= _baseTime) { + // Check the user interface slots to see if there's any slots that need to be expired + UISlots &uiSlots = userInterface._uiSlots; + for (uint idx = 0; idx < uiSlots.size(); ++idx) { + UISlot &slot = uiSlots[idx]; + + if (slot._flags != IMG_REFRESH && slot._flags > IMG_UPDATE_ONLY + && slot._segmentId != IMG_SPINNING_OBJECT) + slot._flags = IMG_ERASE; + } + + // Any background animation in the user interface + userInterface.doBackgroundAnimation(); + + // Handle animating the selected inventory item + userInterface.inventoryAnim(); + + // Set the base time + _baseTime = currentTicks + 6; + } +} + +int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) { + for (int i = (int)size(); i >= 1; --i) { + ScreenObject &sObj = (*this)[i]; + if (sObj._active && sObj._bounds.contains(pt) && sObj._layer == layer) + return i; + } + + // Entry not found + return 0; +} + +void ScreenObjects::elementHighlighted() { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + Common::Array<int> &invList = _vm->_game->_objects._inventoryList; + MADSAction &action = scene._action; + int varA; + int topIndex; + int *idxP; + int var4; + int index; + int indexEnd = -1; + int var8 = 0; + int uiCount; + + switch (userInterface._category) { + case CAT_COMMAND: + index = 10; + indexEnd = 9; + varA = 5; + topIndex = 0; + idxP = !_vm->_events->_rightMousePressed ? &userInterface._highlightedCommandIndex : + &userInterface._selectedActionIndex; + + if (_vm->_events->_rightMousePressed && userInterface._selectedItemVocabIdx >= 0) + userInterface.updateSelection(CAT_INV_VOCAB, -1, &userInterface._selectedItemVocabIdx); + + var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0; + break; + + case CAT_INV_LIST: + userInterface.scrollInventory(); + + index = MIN((int)invList.size() - userInterface._inventoryTopIndex, 5); + indexEnd = invList.size() - 1; + varA = 0; + topIndex = userInterface._inventoryTopIndex; + idxP = &userInterface._highlightedInvIndex; + var4 = (!_released || (_vm->_events->_mouseButtons && action._interAwaiting == 1)) ? 0 : 1; + break; + + case CAT_INV_VOCAB: + if (userInterface._selectedInvIndex >= 0) { + InventoryObject &invObject = _vm->_game->_objects.getItem( + userInterface._selectedInvIndex); + index = invObject._vocabCount; + indexEnd = index - 1; + } else { + index = 0; + } + + varA = 0; + topIndex = 0; + idxP = _vm->_events->_rightMousePressed ? &userInterface._selectedItemVocabIdx : &userInterface._highlightedItemVocabIndex; + + if (_vm->_events->_rightMousePressed && userInterface._selectedActionIndex >= 0) + userInterface.updateSelection(CAT_COMMAND, -1, &userInterface._selectedActionIndex); + + var4 = _released && !_vm->_events->_rightMousePressed ? 1 : 0; + break; + + case CAT_INV_ANIM: + index = 1; + indexEnd = invList.size() - 1; + varA = 0; + topIndex = userInterface._selectedInvIndex; + idxP = &var8; + var4 = -1; + break; + + case CAT_TALK_ENTRY: + index = userInterface._talkStrings.size(); + indexEnd = index - 1; + varA = 0; + topIndex = 0; + idxP = &userInterface._highlightedCommandIndex; + var4 = -1; + break; + + default: + uiCount = size() - _uiCount; + index = uiCount + scene._hotspots.size(); + indexEnd = index - 1; + varA = 0; + topIndex = 0; + idxP = &var8; + var4 = -1; + break; + } + + int newIndex = -1; + int catIndex = userInterface._categoryIndexes[userInterface._category - 1]; + int newX = 0, newY = 0; + Common::Point currentPos = _vm->_events->currentPos(); + + for (int idx = 0; idx < index && newIndex < 0; ++idx) { + int scrObjIndex = (_category == CAT_HOTSPOT) ? catIndex - idx + index - 1 : + catIndex + idx; + + ScreenObject &scrObject = (*this)[scrObjIndex]; + if (!scrObject._active) + continue; + + const Common::Rect &bounds = scrObject._bounds; + newY = MAX((int)bounds.bottom, newY); + newX = MAX((int)bounds.left, newX); + + if (currentPos.y >= bounds.top && currentPos.y < bounds.bottom) { + if (var4) { + if (currentPos.x >= bounds.left && currentPos.x < bounds.right) { + // Cursor is inside hotspot bounds + newIndex = scrObjIndex - catIndex; + if (_category == CAT_HOTSPOT && newIndex < (int)scene._hotspots.size()) + newIndex = scene._hotspots.size() - newIndex - 1; + } + } else if (!varA) { + newIndex = idx; + } else if (varA <= idx) { + if (currentPos.x > bounds.left) + newIndex = idx; + } else { + if (currentPos.x < bounds.right) + newIndex = idx; + } + } + } + + if (newIndex == -1 && index > 0 && !var4) { + if (_vm->_events->currentPos().y <= newY) { + newIndex = 0; + if (varA && _vm->_events->currentPos().x >= newX) + newIndex = varA; + } else { + newIndex = index - 1; + } + } + + if (newIndex >= 0) + newIndex = MIN(newIndex + topIndex, indexEnd); + + action._pickedWord = newIndex; + + if (_category == CAT_INV_LIST || _category == CAT_INV_ANIM) { + if (action._interAwaiting == 1 && newIndex >= 0 && _released && + (!_vm->_events->_mouseReleased || !_vm->_easyMouse)) + newIndex = -1; + } + + if (_released && !_vm->_events->_rightMousePressed && + (_vm->_events->_mouseReleased || !_vm->_easyMouse)) + newIndex = -1; + + if (_category != CAT_HOTSPOT && _category != CAT_INV_ANIM) + userInterface.updateSelection(_category, newIndex, idxP); +} + +void ScreenObjects::setActive(ScrCategory category, int descId, bool active) { + for (uint idx = 1; idx < size(); ++idx) { + ScreenObject &sObj = (*this)[idx]; + if (sObj._category == category && sObj._descId == descId) + sObj._active = active; + } +} + +void ScreenObjects::synchronize(Common::Serializer &s) { + s.syncAsSint16LE(_selectedObject); + s.syncAsSint16LE(_category); +} + +/*------------------------------------------------------------------------*/ + +ScreenSurface::ScreenSurface() { + _shakeCountdown = -1; + _random = 0x4D2; +} + +void ScreenSurface::init() { + setSize(g_system->getWidth(), g_system->getHeight()); +} + +void ScreenSurface::copyRectToScreen(const Common::Point &destPos, + const Common::Rect &bounds) { + const byte *buf = getBasePtr(destPos.x, destPos.y); + + if (bounds.width() != 0 && bounds.height() != 0) + g_system->copyRectToScreen(buf, this->pitch, bounds.left, bounds.top, + bounds.width(), bounds.height()); +} + +void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) { + copyRectToScreen(Common::Point(bounds.left, bounds.top), bounds); +} + +void ScreenSurface::updateScreen() { + if (_shakeCountdown >= 0) { + _random = _random * 5 + 1; + int offset = (_random >> 8) & 3; + if (_shakeCountdown-- <= 0) + offset = 0; + + // Copy the screen with the left hand hide side of the screen of a given + // offset width shown at the very right. The offset changes to give + // an effect of shaking the screen + offset *= 4; + const byte *buf = getBasePtr(offset, 0); + g_system->copyRectToScreen(buf, this->pitch, 0, 0, + this->pitch - offset, this->h); + if (offset > 0) + g_system->copyRectToScreen(this->pixels, this->pitch, + this->pitch - offset, 0, offset, this->h); + } + + g_system->updateScreen(); +} + +void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) { + Palette &pal = *_vm->_palette; + byte palData[PALETTE_SIZE]; + + switch (transitionType) { + case kTransitionFadeIn: + case kTransitionFadeOutIn: + Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0); + Common::fill(&pal._colorFlags[0], &pal._colorFlags[3], false); + + if (transitionType == kTransitionFadeOutIn) { + // Fade out + pal.getFullPalette(palData); + pal.fadeOut(palData, nullptr, 0, PALETTE_COUNT, 0, 0, 1, 16); + } + + // Reset palette to black + Common::fill(&palData[0], &palData[PALETTE_SIZE], 0); + pal.setFullPalette(palData); + + copyRectToScreen(getBounds()); + pal.fadeIn(palData, pal._mainPalette, 0, 256, 0, 1, 1, 16); + break; + + case kTransitionBoxInBottomLeft: + case kTransitionBoxInBottomRight: + case kTransitionBoxInTopLeft: + case kTransitionBoxInTopRight: + error("TODO: transition"); + break; + + case kTransitionPanLeftToRight: + case kTransitionPanRightToLeft: + error("TODO: transition"); + + case kTransitionCircleIn1: + case kTransitionCircleIn2: + case kTransitionCircleIn3: + case kTransitionCircleIn4: + error("TODO circle transition"); + + case kCenterVertTransition: + error("TODO: center vert transition"); + + default: + // Quick transitions + break; + } +} + +} // End of namespace MADS diff --git a/engines/mads/screen.h b/engines/mads/screen.h new file mode 100644 index 0000000000..a3653d6d62 --- /dev/null +++ b/engines/mads/screen.h @@ -0,0 +1,240 @@ +/* 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 MADS_SCREEN_H +#define MADS_SCREEN_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/msurface.h" +#include "mads/action.h" + +namespace MADS { + +#define MADS_SCREEN_WIDTH 320 +#define MADS_SCREEN_HEIGHT 200 + +enum Layer { + LAYER_GUI = 19 +}; + +enum ScreenTransition { + kTransitionNone = 0, + kTransitionFadeIn, kTransitionFadeOutIn, + kTransitionBoxInBottomLeft, kTransitionBoxInBottomRight, + kTransitionBoxInTopLeft, kTransitionBoxInTopRight, + kTransitionPanLeftToRight, kTransitionPanRightToLeft, + kTransitionCircleIn1, kTransitionCircleIn2, + kTransitionCircleIn3, kTransitionCircleIn4, + kVertTransition1, kVertTransition2, kVertTransition3, + kVertTransition4, kVertTransition5, kVertTransition6, + kVertTransition7, kCenterVertTransition +}; + +enum InputMode { + kInputBuildingSentences = 0, // Normal sentence building + kInputConversation = 1, // Conversation mode + kInputLimitedSentences = 2 // Use only scene hotspots +}; + +class SpriteSlot; +class TextDisplay; +class UISlot; + +class DirtyArea { +private: + static MADSEngine *_vm; + friend class DirtyAreas; +public: + Common::Rect _bounds; + bool _textActive; + bool _active; + DirtyArea *_mergedArea; + + DirtyArea(); + + void setArea(int width, int height, int maxWidth, int maxHeight); + + /** + * Set up a dirty area for a sprite slot + */ + void setSpriteSlot(const SpriteSlot *spriteSlot); + + /** + * Set up a dirty area for a text display + */ + void setTextDisplay(const TextDisplay *textDisplay); + + /** + * Set up a dirty area for a UI slot + */ + void setUISlot(const UISlot *slot); +}; + +class DirtyAreas : public Common::Array<DirtyArea> { +private: + MADSEngine *_vm; +public: + DirtyAreas(MADSEngine *vm); + + /** + * Merge together any designated dirty areas that overlap + * @param startIndex 1-based starting dirty area starting index + * @param count Number of entries to process + */ + void merge(int startIndex, int count); + + bool intersects(int idx1, int idx2); + void mergeAreas(int idx1, int idx2); + + /** + * Copy the data specified by the dirty rect list between surfaces + * @param srcSurface Source surface + * @param destSurface Dest surface + * @param posAdjust Position adjustment + */ + void copy(MSurface *srcSurface, MSurface *destSurface, const Common::Point &posAdjust); + + /** + * Use the lsit of dirty areas to copy areas of the screen surface to + * the physical screen + * @param posAdjust Position adjustment */ + void copyToScreen(const Common::Point &posAdjust); + + void reset(); +}; + + +class ScreenObject { +public: + bool _active; + Common::Rect _bounds; + ScrCategory _category; + int _descId; + int _layer; + + ScreenObject(); +}; + +class ScreenObjects : public Common::Array<ScreenObject> { +private: + MADSEngine *_vm; + int _objectY; + + int scanBackwards(const Common::Point &pt, int layer); +public: + InputMode _inputMode; + int _v7FED6; + int _v8332A; + int _forceRescan; + int _selectedObject; + ScrCategory _category; + bool _released; + int _uiCount; + bool _eventFlag; + uint32 _baseTime; + int _spotId; + + /* + * Constructor + */ + ScreenObjects(MADSEngine *vm); + + /** + * Add a new item to the list + */ + void add(const Common::Rect &bounds, Layer layer, ScrCategory category, int descId); + + /** + */ + void check(bool scanFlag); + + /** + * Handle an element being highlighted on the screen, and make it active. + */ + void elementHighlighted(); + + /** + * Retrieve a ScreenObject from the list + * @remarks This array is 1-based indexed by the game + */ + ScreenObject &operator[](int idx) { + assert(idx > 0); + return Common::Array<ScreenObject>::operator[](idx - 1); + } + + /** + * Sets an item identified by category and Desc Id as active or not + * @param category Screen category + * @param descId Description for item + * @param active Whether to set item as active or not + */ + void setActive(ScrCategory category, int descId, bool active); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +class ScreenSurface : public MSurface { +private: + uint16 _random; +public: + Common::Point _offset; + int _shakeCountdown; +public: + /** + * Constructor + */ + ScreenSurface(); + + /** + * Initialize the surface + */ + void init(); + + /** + * Copys an area of the screen surface to a given destination position on + * the ScummVM physical screen buffer + * @param destPos Destination position + * @param bounds Area of screen surface to copy + */ + void copyRectToScreen(const Common::Point &destPos, const Common::Rect &bounds); + + /** + * Copys an area of the screen surface to the ScmmVM physical screen buffer + * @param bounds Area of screen surface to copy + */ + void copyRectToScreen(const Common::Rect &bounds); + + /** + * Updates the screen with the contents of the surface + */ + void updateScreen(); + + void transition(ScreenTransition transitionType, bool surfaceFlag); +}; + +} // End of namespace MADS + +#endif /* MADS_SCREEN_H */ diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp new file mode 100644 index 0000000000..f987595f05 --- /dev/null +++ b/engines/mads/sequence.cpp @@ -0,0 +1,541 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/assets.h" +#include "mads/sequence.h" +#include "mads/scene.h" + +namespace MADS { + +SequenceEntry::SequenceEntry() { + _spritesIndex = 0; + _flipped = 0; + _frameIndex = 0; + _frameStart = 0; + _numSprites = 0; + _animType = ANIMTYPE_NONE; + _frameInc = 0; + _depth = 0; + _scale = 0; + _dynamicHotspotIndex = -1; + _triggerCountdown = 0; + _doneFlag = 0; + _triggerMode = SEQUENCE_TRIGGER_DAEMON; + _numTicks = 0; + _extraTicks = 0; + _timeout = 0; + _active = false; + _nonFixed = false; + _flags = 0; + for (int i = 0; i < 5; ++i) + _entries._mode[i] = SEQUENCE_TRIGGER_EXPIRE; + + _entries._count = 0; + _actionNouns._verbId = VERB_NONE; + _actionNouns._objectNameId = -1; + _actionNouns._indirectObjectId = -1; + + Common::fill(&_entries._frameIndex[0], &_entries._frameIndex[SEQUENCE_ENTRY_SUBSET_MAX], 0); + Common::fill(&_entries._trigger[0], &_entries._trigger[SEQUENCE_ENTRY_SUBSET_MAX], 0); +} + +/*------------------------------------------------------------------------*/ + +#define SEQUENCE_LIST_SIZE 30 + +SequenceList::SequenceList(MADSEngine *vm) : _vm(vm) { + // IMPORTANT: Preallocate timer slots. Note that sprite slots refer to entries + // in this list by index, so we can't just add or delete entries later + for (int i = 0; i < SEQUENCE_LIST_SIZE; ++i) { + SequenceEntry rec; + rec._active = false; + rec._dynamicHotspotIndex = -1; + _entries.push_back(rec); + } +} + +void SequenceList::clear() { + for (uint i = 0; i < _entries.size(); ++i) { + _entries[i]._active = false; + _entries[i]._dynamicHotspotIndex = -1; + } +} + +bool SequenceList::addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger) { + if (_entries[index]._entries._count >= SEQUENCE_ENTRY_SUBSET_MAX) + return true; + + int subIndex = _entries[index]._entries._count++; + _entries[index]._entries._mode[subIndex] = mode; + _entries[index]._entries._frameIndex[subIndex] = frameIndex; + _entries[index]._entries._trigger[subIndex] = trigger; + + return false; +} + +int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks, + int msgX, int msgY, bool nonFixed, int scale, int depth, int frameInc, SpriteAnimType animType, int numSprites, + int frameStart) { + Scene &scene = _vm->_game->_scene; + + // Find a free slot + uint seqIndex = 0; + while ((seqIndex < _entries.size()) && _entries[seqIndex]._active) + ++seqIndex; + if (seqIndex == _entries.size()) + error("TimerList full"); + + if (frameStart <= 0) + frameStart = 1; + if (numSprites == 0) + numSprites = scene._sprites[spriteListIndex]->getCount(); + if (frameStart == numSprites) + frameInc = 0; + + // Set the list entry fields + _entries[seqIndex]._active = true; + _entries[seqIndex]._spritesIndex = spriteListIndex; + _entries[seqIndex]._flipped = flipped; + _entries[seqIndex]._frameIndex = frameIndex; + _entries[seqIndex]._frameStart = frameStart; + _entries[seqIndex]._numSprites = numSprites; + _entries[seqIndex]._animType = animType; + _entries[seqIndex]._frameInc = frameInc; + _entries[seqIndex]._depth = depth; + _entries[seqIndex]._scale = scale; + _entries[seqIndex]._nonFixed = nonFixed; + _entries[seqIndex]._position.x = msgX; + _entries[seqIndex]._position.y = msgY; + _entries[seqIndex]._numTicks = numTicks; + _entries[seqIndex]._extraTicks = extraTicks; + + _entries[seqIndex]._timeout = scene._frameStartTime + delayTicks; + + _entries[seqIndex]._triggerCountdown = triggerCountdown; + _entries[seqIndex]._doneFlag = false; + _entries[seqIndex]._flags = 0; + _entries[seqIndex]._dynamicHotspotIndex = -1; + _entries[seqIndex]._entries._count = 0; + _entries[seqIndex]._triggerMode = _vm->_game->_triggerSetupMode; + + _entries[seqIndex]._actionNouns = _vm->_game->_scene._action._activeAction; + + return seqIndex; +} + +int SequenceList::addTimer(int timeout, int abortVal) { + Scene &scene = _vm->_game->_scene; + uint seqIndex; + for (seqIndex = 0; seqIndex < _entries.size(); ++seqIndex) { + if (!_entries[seqIndex]._active) + break; + } + assert(seqIndex < _entries.size()); + + SequenceEntry &se = _entries[seqIndex]; + se._active = true; + se._spritesIndex = -1; + se._numTicks = timeout; + se._extraTicks = 0; + se._timeout = scene._frameStartTime + timeout; + se._triggerCountdown = true; + se._doneFlag = false; + se._entries._count = 0; + se._triggerMode = _vm->_game->_triggerSetupMode; + se._actionNouns = _vm->_game->_scene._action._activeAction; + addSubEntry(seqIndex, SEQUENCE_TRIGGER_EXPIRE, 0, abortVal); + + return seqIndex; +} + +void SequenceList::remove(int seqIndex) { + Scene &scene = _vm->_game->_scene; + + if (_entries[seqIndex]._active) { + if (_entries[seqIndex]._dynamicHotspotIndex >= 0) + scene._dynamicHotspots.remove(_entries[seqIndex]._dynamicHotspotIndex); + } + + _entries[seqIndex]._active = false; + scene._spriteSlots.deleteTimer(seqIndex); +} + +void SequenceList::setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &timerEntry = _entries[seqIndex]; + SpriteAsset &spriteSet = *scene._sprites[timerEntry._spritesIndex]; + + spriteSlot._flags = spriteSet.isBackground() ? IMG_DELTA : IMG_UPDATE; + spriteSlot._seqIndex = seqIndex; + spriteSlot._spritesIndex = timerEntry._spritesIndex; + spriteSlot._frameNumber = timerEntry._flipped ? -timerEntry._frameIndex : timerEntry._frameIndex; + spriteSlot._depth = timerEntry._depth; + spriteSlot._scale = timerEntry._scale; + + if (!timerEntry._nonFixed) { + spriteSlot._position = timerEntry._position; + } else { + MSprite *sprite = spriteSet.getFrame(timerEntry._frameIndex - 1); + spriteSlot._position = sprite->_offset; + } +} + +bool SequenceList::loadSprites(int seqIndex) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &seqEntry = _entries[seqIndex]; + int slotIndex; + bool result = false; + int idx = -1; + + scene._spriteSlots.deleteTimer(seqIndex); + if (seqEntry._doneFlag) { + remove(seqIndex); + return false; + } + + if (seqEntry._spritesIndex == -1) { + // Doesn't have an associated sprite anymore, so mark as done + seqEntry._doneFlag = true; + } else if ((slotIndex = scene._spriteSlots.add()) >= 0) { + SpriteSlot &spriteSlot = scene._spriteSlots[slotIndex]; + setSpriteSlot(seqIndex, spriteSlot); + + if ((seqEntry._flags != 0) || (seqEntry._dynamicHotspotIndex >= 0)) { + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1); + int width = frame->getWidth() * seqEntry._scale / 200; + int height = frame->getHeight() * seqEntry._scale / 100; + Common::Point pt = spriteSlot._position; + + // Handle sprite movement, if present + if (seqEntry._flags & 1) { + seqEntry._posAccum.x += seqEntry._posDiff.x; + if (seqEntry._posAccum.x >= 100) { + int v = seqEntry._posAccum.x / 100; + seqEntry._position.x += v * seqEntry._posSign.x; + seqEntry._posAccum.x -= v * 100; + } + + seqEntry._posAccum.y += seqEntry._posDiff.y; + if (seqEntry._posAccum.y >= 100) { + int v = seqEntry._posAccum.y / 100; + seqEntry._position.y += v * seqEntry._posSign.y; + seqEntry._posAccum.y -= v * 100; + } + } + + if (seqEntry._flags & 2) { + // Check for object having moved off-scren + if ((pt.x + width) < 0 || (pt.x + width) >= MADS_SCREEN_WIDTH || + pt.y < 0 || (pt.y - height) >= MADS_SCENE_HEIGHT) { + result = true; + seqEntry._doneFlag = true; + } + } + + if (seqEntry._dynamicHotspotIndex >= 0) { + DynamicHotspot &dynHotspot = scene._dynamicHotspots[seqEntry._dynamicHotspotIndex]; + + dynHotspot._bounds.left = MAX(pt.x - width, 0); + dynHotspot._bounds.top = MAX(pt.y - height, 0); + dynHotspot._bounds.right = dynHotspot._bounds.left + width; + dynHotspot._bounds.bottom = dynHotspot._bounds.top + height; + + scene._dynamicHotspots._changed = true; + } + } + + // Frame adjustments + if (seqEntry._frameStart != seqEntry._numSprites) + seqEntry._frameIndex += seqEntry._frameInc; + + if (seqEntry._frameIndex >= seqEntry._frameStart) { + if (seqEntry._frameIndex > seqEntry._numSprites) { + result = true; + if (seqEntry._animType == ANIMTYPE_CYCLED) { + // back to the starting frame (cyclic) + seqEntry._frameIndex = seqEntry._frameStart; + } else { + // Switch into reverse mode + seqEntry._frameIndex = seqEntry._numSprites - 1; + seqEntry._frameInc = -1; + } + } + } else { + // Currently in reverse mode and moved past starting frame + result = true; + + if (seqEntry._animType == ANIMTYPE_CYCLED) + { + // Switch back to forward direction again + seqEntry._frameIndex = seqEntry._frameStart + 1; + seqEntry._frameInc = 1; + } else { + // Otherwise reset back to last sprite for further reverse animating + seqEntry._frameIndex = seqEntry._numSprites; + } + } + + if (result && (seqEntry._triggerCountdown != 0)) { + if (--seqEntry._triggerCountdown == 0) + seqEntry._doneFlag = true; + } + } else { + // Out of sprite display slots, so mark entry as done + seqEntry._doneFlag = true; + } + + for (int i = 0; i < seqEntry._entries._count; ++i) { + switch (seqEntry._entries._mode[i]) { + case SEQUENCE_TRIGGER_EXPIRE: + case SEQUENCE_TRIGGER_LOOP: + if (((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_EXPIRE) && seqEntry._doneFlag) || + ((seqEntry._entries._mode[i] == SEQUENCE_TRIGGER_LOOP) && result)) + idx = i; + break; + + case SEQUENCE_TRIGGER_SPRITE: { + int v = seqEntry._entries._frameIndex[i]; + if ((v == seqEntry._frameIndex) || (v == 0)) + idx = i; + break; + } + + default: + break; + } + } + + if (idx >= 0) { + _vm->_game->_trigger = seqEntry._entries._trigger[idx]; + _vm->_game->_triggerMode = seqEntry._triggerMode; + + if (seqEntry._triggerMode != SEQUENCE_TRIGGER_DAEMON) + scene._action._activeAction = seqEntry._actionNouns; + } + + return result; +} + +/** +* Handles counting down entries in the timer list for action +*/ +void SequenceList::tick() { + Scene &scene = _vm->_game->_scene; + for (uint idx = 0; idx < _entries.size(); ++idx) { + if ((_vm->_game->_fx == 0) && (_vm->_game->_trigger != 0)) + break; + + SequenceEntry &seqEntry = _entries[idx]; + uint32 currentTimer = scene._frameStartTime; + + if (!seqEntry._active || (currentTimer < seqEntry._timeout)) + continue; + + // Set the next timeout for the timer entry + seqEntry._timeout = currentTimer + seqEntry._numTicks; + + // Action the sprite + if (loadSprites(idx)) { + seqEntry._timeout += seqEntry._extraTicks; + } + } +} + +void SequenceList::delay(uint32 priorFrameTime, uint32 currentTime) { + for (uint idx = 0; idx < _entries.size(); ++idx) { + if (_entries[idx]._active) { + _entries[idx]._timeout += currentTime - priorFrameTime; + } + } +} + +void SequenceList::setAnimRange(int seqIndex, int startVal, int endVal) { + Scene &scene = _vm->_game->_scene; + SequenceEntry &seqEntry = _entries[seqIndex]; + SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex]; + int numSprites = spriteSet.getCount(); + int tempStart, tempEnd; + + switch (startVal) { + case -2: + tempStart = numSprites; + break; + case -1: + tempStart = 1; + break; + default: + tempStart = startVal; + break; + } + + switch (endVal) { + case -2: + case 0: + tempEnd = numSprites; + break; + case -1: + tempEnd = 1; + break; + default: + tempEnd = endVal; + break; + } + + seqEntry._frameStart = tempStart; + seqEntry._numSprites = tempEnd; + + seqEntry._frameIndex = (seqEntry._frameInc >= 0) ? tempStart : tempEnd; +} + +void SequenceList::scan() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < _entries.size(); ++i) { + if (_entries[i]._active && (_entries[i]._spritesIndex != -1)) { + int idx = scene._spriteSlots.add(); + setSpriteSlot(i, scene._spriteSlots[idx]); + } + } +} + +/** +* Sets the depth of the specified entry in the sequence list +*/ +void SequenceList::setDepth(int seqIndex, int depth) { + _entries[seqIndex]._depth = depth; +} + +void SequenceList::setPosition(int seqIndex, const Common::Point &pt) { + _entries[seqIndex]._position = pt; + _entries[seqIndex]._nonFixed = false; +} + +int SequenceList::addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { + Scene &scene = _vm->_game->_scene; + MSprite *spriteFrame = scene._sprites[srcSpriteIdx]->getFrame(0); + int depth = scene._depthSurface.getDepth(Common::Point( + spriteFrame->_offset.x + (spriteFrame->w / 2), + spriteFrame->_offset.y + (spriteFrame->h / 2))); + + return add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0, + true, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0); +} + +int SequenceList::addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown, int timeoutTicks, int extraTicks) { + Scene &scene = _vm->_game->_scene; + + SpriteAsset *asset = scene._sprites[srcSpriteIdx]; + MSprite *spriteFrame = asset->getFrame(0); + int depth = scene._depthSurface.getDepth(Common::Point( + spriteFrame->_offset.x + (spriteFrame->w / 2), + spriteFrame->_offset.y + (spriteFrame->h / 2))); + + return add(srcSpriteIdx, flipped, asset->getCount(), triggerCountdown, timeoutTicks, extraTicks, + numTicks, 0, 0, true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0); +} + + +int SequenceList::startCycle(int srcSpriteIndex, bool flipped, int cycleIndex) { + int result = addSpriteCycle(srcSpriteIndex, flipped, INDEFINITE_TIMEOUT, 0, 0, 0); + if (result >= 0) + setAnimRange(result, cycleIndex, cycleIndex); + + return result; +} + +int SequenceList::startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, + int triggerCountdown, int timeoutTicks, int extraTicks) { + SpriteAsset *sprites = _vm->_game->_scene._sprites[srcSpriteIndex]; + MSprite *frame = sprites->getFrame(0); + int depth = _vm->_game->_scene._depthSurface.getDepth(Common::Point( + frame->_offset.x + frame->w / 2, frame->_offset.y + frame->h / 2)); + + return add(srcSpriteIndex, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, + numTicks, 0, 0, true, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0); +} + +void SequenceList::updateTimeout(int spriteIdx, int seqIndex) { + Player &player = _vm->_game->_player; + int timeout; + + if (spriteIdx >= 0) + timeout = _entries[spriteIdx]._timeout; + else + timeout = player._priorTimer + player._ticksAmount; + + if (seqIndex >= 0) + _entries[seqIndex]._timeout = timeout; + else + player._priorTimer = timeout - player._ticksAmount; + +} + +void SequenceList::setScale(int spriteIdx, int scale) { + _entries[spriteIdx]._scale = scale; +} + +void SequenceList::setMsgLayout(int seqIndex) { + Player &player = _vm->_game->_player; + int yp = player._playerPos.y + (player._centerOfGravity * player._currentScale) / 100; + setPosition(seqIndex, Common::Point(player._playerPos.x, yp)); + setDepth(seqIndex, player._currentDepth); + setScale(seqIndex, player._currentScale); + updateTimeout(-1, seqIndex); +} + +void SequenceList::setDone(int seqIndex) { + _entries[seqIndex]._doneFlag = true; + _entries[seqIndex]._timeout = _vm->_game->_player._priorTimer; +} + +void SequenceList::setMotion(int seqIndex, int flags, int deltaX, int deltaY) { + SequenceEntry &se = _entries[seqIndex]; + se._flags = flags | 1; + + // Set the direction sign for movement + if (deltaX > 0) { + se._posSign.x = 1; + } else if (deltaX < 0) { + se._posSign.x = -1; + } else { + se._posSign.x = 0; + } + + if (deltaY > 0) { + se._posSign.y = 1; + } + else if (deltaY < 0) { + se._posSign.y = -1; + } else { + se._posSign.y = 0; + } + + se._posDiff.x = ABS(deltaX); + se._posDiff.y = ABS(deltaY); + se._posAccum.x = se._posAccum.y = 0; +} + +} // End of namespace diff --git a/engines/mads/sequence.h b/engines/mads/sequence.h new file mode 100644 index 0000000000..ee587ff02d --- /dev/null +++ b/engines/mads/sequence.h @@ -0,0 +1,131 @@ +/* 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 MADS_SEQUENCE_H +#define MADS_SEQUENCE_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "common/rect.h" +#include "mads/action.h" + +namespace MADS { + +class SpriteSlot; + +enum SequenceTrigger { + SEQUENCE_TRIGGER_EXPIRE = 0, // Trigger when the sequence finishes + SEQUENCE_TRIGGER_LOOP = 1, // Trigger when the sequence loops + SEQUENCE_TRIGGER_SPRITE = 2 // Trigger when sequence reaches specific sprite +}; + +enum SpriteAnimType { ANIMTYPE_NONE = 0, ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2 }; + +#define SEQUENCE_ENTRY_SUBSET_MAX 5 + +struct SequenceSubEntries { + int _count; + SequenceTrigger _mode[SEQUENCE_ENTRY_SUBSET_MAX]; + int _frameIndex[SEQUENCE_ENTRY_SUBSET_MAX]; + int _trigger[SEQUENCE_ENTRY_SUBSET_MAX]; +}; + +struct SequenceEntry { + bool _active; + int8 _spritesIndex; + bool _flipped; + + int _frameIndex; + int _frameStart; + int _numSprites; + + SpriteAnimType _animType; + int _frameInc; + + int _depth; + int _scale; + int _dynamicHotspotIndex; + + bool _nonFixed; + uint32 _flags; + + Common::Point _position; + Common::Point _posDiff; + Common::Point _posSign; + Common::Point _posAccum; + int _triggerCountdown; + bool _doneFlag; + SequenceSubEntries _entries; + TriggerMode _triggerMode; + + ActionDetails _actionNouns; + int _numTicks; + int _extraTicks; + uint32 _timeout; + + SequenceEntry(); +}; + +class MADSEngine; + +class SequenceList { +private: + MADSEngine *_vm; + Common::Array<SequenceEntry> _entries; +public: + SequenceList(MADSEngine *vm); + + SequenceEntry &operator[](int index) { return _entries[index]; } + void clear(); + bool addSubEntry(int index, SequenceTrigger mode, int frameIndex, int trigger); + int add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, + int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, int scale, int depth, + int frameInc, SpriteAnimType animType, int numSprites, int frameStart); + + int addTimer(int timeout, int abortVal); + void remove(int seqIndex); + void setSpriteSlot(int seqIndex, SpriteSlot &spriteSlot); + bool loadSprites(int seqIndex); + void tick(); + void delay(uint32 priorFrameTime, uint32 currentTime); + void setAnimRange(int seqIndex, int startVal, int endVal); + void scan(); + void setDepth(int seqIndex, int depth); + void setPosition(int seqIndex, const Common::Point &pt); + int addSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + int addReverseSpriteCycle(int srcSpriteIdx, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + + int startCycle(int srcSpriteIdx, bool flipped, int cycleIndex); + int startReverseCycle(int srcSpriteIndex, bool flipped, int numTicks, + int triggerCountdown = 0, int timeoutTicks = 0, int extraTicks = 0); + void updateTimeout(int spriteIdx, int seqIndex); + void setScale(int spriteIdx, int scale); + void setMsgLayout(int seqIndex); + void setDone(int seqIndex); + void setMotion(int seqIndex, int flags, int deltaX, int deltaY); +}; + +} // End of namespace MADS + +#endif /* MADS_SEQUENCE_H */ diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp new file mode 100644 index 0000000000..bd99aed2f4 --- /dev/null +++ b/engines/mads/sound.cpp @@ -0,0 +1,142 @@ +/* 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 "audio/audiostream.h" +#include "audio/decoders/raw.h" +#include "common/memstream.h" +#include "mads/sound.h" +#include "mads/mads.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) { + _vm = vm; + _mixer = mixer; + _driver = nullptr; + _pollSoundEnabled = false; + _soundPollFlag = false; + _newSoundsPaused = false; +} + +SoundManager::~SoundManager() { + delete _driver; +} + +void SoundManager::init(int sectionNumber) { + assert(sectionNumber > 0 && sectionNumber < 10); + + switch (_vm->getGameID()) { + case GType_RexNebular: + switch (sectionNumber) { + case 1: + _driver = new Nebular::ASound1(_mixer); + break; + case 2: + _driver = new Nebular::ASound2(_mixer); + break; + case 3: + _driver = new Nebular::ASound3(_mixer); + break; + case 4: + _driver = new Nebular::ASound4(_mixer); + break; + case 5: + _driver = new Nebular::ASound5(_mixer); + break; + case 6: + _driver = new Nebular::ASound6(_mixer); + break; + case 7: + _driver = new Nebular::ASound7(_mixer); + break; + case 8: + _driver = new Nebular::ASound8(_mixer); + break; + case 9: + error("Sound driver 9 not implemented"); + default: + _driver = nullptr; + break; + } + break; + + default: + warning("SoundManager: Unknown game"); + _driver = nullptr; + break; + } +} + +void SoundManager::closeDriver() { + if (_driver) { + command(0); + setEnabled(false); + stop(); + + removeDriver(); + } +} + +void SoundManager::removeDriver() { + delete _driver; + _driver = nullptr; +} + +void SoundManager::setEnabled(bool flag) { + _pollSoundEnabled = flag; + _soundPollFlag = false; +} + +void SoundManager::pauseNewCommands() { + _newSoundsPaused = true; +} + +void SoundManager::startQueuedCommands() { + _newSoundsPaused = false; + + while (!_queuedCommands.empty()) { + int commandId = _queuedCommands.pop(); + command(commandId); + } +} + +void SoundManager::command(int commandId, int param) { + if (_newSoundsPaused) { + if (_queuedCommands.size() < 8) + _queuedCommands.push(commandId); + } else if (_driver) { + _driver->command(commandId, param); + } +} + +void SoundManager::stop() { + if (_driver) + _driver->stop(); +} + +void SoundManager::noise() { + if (_driver) + _driver->noise(); +} + +} // End of namespace MADS diff --git a/engines/mads/sound.h b/engines/mads/sound.h new file mode 100644 index 0000000000..9a251f9dd0 --- /dev/null +++ b/engines/mads/sound.h @@ -0,0 +1,103 @@ +/* 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 MADS_SOUND_H +#define MADS_SOUND_H + +#include "common/scummsys.h" +#include "common/queue.h" +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "mads/nebular/sound_nebular.h" + +namespace MADS { + +class MADSEngine; + +class SoundManager { +private: + MADSEngine *_vm; + Audio::Mixer *_mixer; + Nebular::ASound *_driver; + bool _pollSoundEnabled; + bool _soundPollFlag; + bool _newSoundsPaused; + Common::Queue<int> _queuedCommands; +public: + SoundManager(MADSEngine *vm, Audio::Mixer *mixer); + ~SoundManager(); + + /** + * Initializes the sound driver for a given game section + */ + void init(int sectionNumber); + + /** + * Stop any currently active sound and remove the driver + */ + void closeDriver(); + + /** + * Remove the driver + */ + void removeDriver(); + + /** + * Sets the enabled status of the sound + * @flag True if sound should be enabled + */ + void setEnabled(bool flag); + + /** + * Temporarily pause the playback of any new sound commands + */ + void pauseNewCommands(); + + /** + * Stop queueing sound commands, and execute any previously queued ones + */ + void startQueuedCommands(); + + //@{ + /** + * Executes a command on the sound driver + * @param commandid Command Id to execute + * @param param Optional paramater specific to a few commands + */ + void command(int commandId, int param = 0); + + /** + * Stops any currently playing sound + */ + void stop(); + + /** + * Noise + * Some sort of random noise generation? + */ + void noise(); + //@} +}; + +} // End of namespace MADS + +#endif /* MADS_SOUND_H */ diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp new file mode 100644 index 0000000000..a229fccb89 --- /dev/null +++ b/engines/mads/sprites.cpp @@ -0,0 +1,417 @@ +/* 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 "common/scummsys.h" +#include "engines/util.h" +#include "graphics/palette.h" +#include "mads/mads.h" +#include "mads/screen.h" +#include "mads/msurface.h" +#include "mads/sprites.h" + +namespace MADS { + +enum { + kEndOfLine = 0, + kEndOfSprite = 1, + kMarker = 2 +}; + +#define TRANSPARENT_COLOR_INDEX 0xFF + +class DepthEntry { +public: + int depth; + int index; + + DepthEntry(int depthAmt, int indexVal) { depth = depthAmt; index = indexVal; } +}; + +bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) { + return entry1.depth < entry2.depth; +} + +typedef Common::List<DepthEntry> DepthList; + +/*------------------------------------------------------------------------*/ + +MSprite::MSprite() + : MSurface() { +} + +MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette, + const Common::Rect &bounds) + : MSurface(bounds.width(), bounds.height()), + _offset(Common::Point(bounds.left, bounds.top)) { + // Load the sprite data + loadSprite(source, palette); +} + +MSprite::~MSprite() { +} + +void MSprite::loadSprite(Common::SeekableReadStream *source, + const Common::Array<RGB6> &palette) { + byte *outp, *lineStart; + bool newLine = false; + + outp = getData(); + lineStart = getData(); + int spriteSize = this->w * this->h; + byte transIndex = getTransparencyIndex(); + Common::fill(outp, outp + spriteSize, transIndex); + + for (;;) { + byte cmd1, cmd2, count, pixel; + + if (newLine) { + outp = lineStart + getWidth(); + lineStart = outp; + newLine = false; + } + + cmd1 = source->readByte(); + + if (cmd1 == 0xFC) + break; + else if (cmd1 == 0xFF) + newLine = true; + else if (cmd1 == 0xFD) { + while (!newLine) { + count = source->readByte(); + if (count == 0xFF) { + newLine = true; + } else { + pixel = source->readByte(); + while (count--) + *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel; + } + } + } else { + while (!newLine) { + cmd2 = source->readByte(); + if (cmd2 == 0xFF) { + newLine = true; + } else if (cmd2 == 0xFE) { + count = source->readByte(); + pixel = source->readByte(); + while (count--) + *outp++ = (pixel == 0xFD) ? getTransparencyIndex() : pixel; + } else { + *outp++ = (cmd2 == 0xFD) ? getTransparencyIndex() : cmd2; + } + } + } + } + + // Do a final iteration over the sprite to convert it's pixels to + // the final positions in the main palette + for (outp = getData(); spriteSize > 0; --spriteSize, ++outp) { + if (*outp != transIndex) + *outp = palette[*outp]._palIndex; + } +} + +byte MSprite::getTransparencyIndex() const { + return TRANSPARENT_COLOR_INDEX; +} + +/*------------------------------------------------------------------------*/ + +MADSEngine *SpriteSlot::_vm = nullptr; + +SpriteSlot::SpriteSlot() { + _flags = IMG_STATIC; + _seqIndex = 0; + _spritesIndex = 0; + _frameNumber = 0; + _depth = 0; + _scale = 0; +} + +SpriteSlot::SpriteSlot(SpriteFlags type, int seqIndex) { + _flags = type; + _seqIndex = seqIndex; + _spritesIndex = 0; + _frameNumber = 0; + _depth = 0; + _scale = 0; +} + +bool SpriteSlot::operator==(const SpriteSlotSubset &other) const { + return (_spritesIndex == other._spritesIndex) && (_frameNumber == other._frameNumber) && + (_position == other._position) && (_depth == other._depth) && + (_scale == other._scale); +} + +void SpriteSlot::copy(const SpriteSlotSubset &other) { + _spritesIndex = other._spritesIndex; + _frameNumber = other._frameNumber; + _position = other._position; + _depth = other._depth; + _scale = other._scale; +} + +/*------------------------------------------------------------------------*/ + +SpriteSlots::SpriteSlots(MADSEngine *vm) : _vm(vm) { + SpriteSlot::_vm = vm; +} + +void SpriteSlots::reset(bool flag) { + _vm->_game->_scene._textDisplay.reset(); + + if (flag) + _vm->_game->_scene._sprites.clear(); + + Common::Array<SpriteSlot>::clear(); + push_back(SpriteSlot(IMG_REFRESH, -1)); +} + +void SpriteSlots::deleteEntry(int index) { + remove_at(index); +} + +void SpriteSlots::setDirtyAreas() { + Scene &scene = _vm->_game->_scene; + + for (uint i = 0; i < size(); ++i) { + if ((*this)[i]._flags >= IMG_STATIC) { + scene._dirtyAreas[i].setSpriteSlot(&(*this)[i]); + + scene._dirtyAreas[i]._textActive = ((*this)[i]._flags <= IMG_STATIC) ? 0 : 1; + (*this)[i]._flags = IMG_STATIC; + } + } +} + +void SpriteSlots::fullRefresh(bool clearAll) { + if (clearAll) + Common::Array<SpriteSlot>::clear(); + + push_back(SpriteSlot(IMG_REFRESH, -1)); +} + +void SpriteSlots::deleteTimer(int seqIndex) { + for (uint idx = 0; idx < size(); ++idx) { + SpriteSlot &slot = (*this)[idx]; + if (slot._seqIndex == seqIndex) { + slot._flags = IMG_ERASE; + return; + } + } +} + +int SpriteSlots::add() { + SpriteSlot ss; + push_back(ss); + return size() - 1; +} + +void SpriteSlots::drawBackground() { + Scene &scene = _vm->_game->_scene; + + // Initial draw loop for any active sprites in the background + for (uint i = 0; i < size(); ++i) { + SpriteSlot &spriteSlot = (*this)[i]; + DirtyArea &dirtyArea = scene._dirtyAreas[i]; + + if (spriteSlot._flags >= IMG_STATIC) { + // Foreground sprite, so we can ignore it + dirtyArea._active = false; + } else { + dirtyArea._active = true; + dirtyArea.setSpriteSlot(&spriteSlot); + + if (spriteSlot._flags == IMG_DELTA) { + // Background object, so need to draw it + assert(spriteSlot._frameNumber > 0); + SpriteAsset *asset = scene._sprites[spriteSlot._spritesIndex]; + MSprite *frame = asset->getFrame(spriteSlot._frameNumber - 1); + + Common::Point pt = spriteSlot._position; + if (spriteSlot._scale != -1) { + // Adjust the drawing position + pt.x -= frame->w / 2; + pt.y -= frame->h / 2; + } + + + if (spriteSlot._depth <= 1) { + frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex()); + } else if (scene._depthStyle == 0) { + scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface, + 100, frame->getTransparencyIndex()); + } else { + error("Unsupported depth style"); + } + } + } + } + + // Mark any remaning sprite slot dirty areas as inactive + for (uint i = size(); i < SPRITE_SLOTS_MAX_SIZE; ++i) + scene._dirtyAreas[i]._active = false; + + // Flag any active text display + for (uint i = 0; i < scene._textDisplay.size(); ++i) { + TextDisplay &textDisplay = scene._textDisplay[i]; + DirtyArea &dirtyArea = scene._dirtyAreas[i + SPRITE_SLOTS_MAX_SIZE]; + + if (textDisplay._expire >= 0 || !textDisplay._active) { + dirtyArea._active = false; + } else { + dirtyArea._active = true; + dirtyArea.setTextDisplay(&textDisplay); + } + } +} + +void SpriteSlots::drawSprites(MSurface *s) { + DepthList depthList; + Scene &scene = _vm->_game->_scene; + + // Get a list of sprite object depths for active objects + for (uint i = 0; i < size(); ++i) { + SpriteSlot &spriteSlot = (*this)[i]; + if (spriteSlot._flags >= IMG_STATIC) { + DepthEntry rec(16 - spriteSlot._depth, i); + depthList.push_back(rec); + } + } + + // Sort the list in order of the depth + Common::sort(depthList.begin(), depthList.end(), sortHelper); + + // Loop through each of the objects + DepthList::iterator i; + for (i = depthList.begin(); i != depthList.end(); ++i) { + DepthEntry &de = *i; + SpriteSlot &slot = (*this)[de.index]; + assert(slot._spritesIndex < (int)scene._sprites.size()); + SpriteAsset &spriteSet = *scene._sprites[slot._spritesIndex]; + + // Get the sprite frame + int frameNumber = ABS(slot._frameNumber); + bool flipped = slot._frameNumber < 0; + + assert(frameNumber > 0); + MSprite *sprite = spriteSet.getFrame(frameNumber - 1); + + MSurface *spr = sprite; + if (flipped) { + // Create a flipped copy of the sprite temporarily + spr = sprite->flipHorizontal(); + } + + if ((slot._scale < 100) && (slot._scale != -1)) { + // Minimalized drawing + s->copyFrom(spr, slot._position, slot._depth, &scene._depthSurface, + slot._scale, sprite->getTransparencyIndex()); + } else { + int xp, yp; + + if (slot._scale == -1) { + xp = slot._position.x - scene._posAdjust.x; + yp = slot._position.y - scene._posAdjust.y; + } else { + xp = slot._position.x - (spr->w / 2) - scene._posAdjust.x; + yp = slot._position.y - spr->h - scene._posAdjust.y + 1; + } + + if (slot._depth > 1) { + // Draw the frame with depth processing + s->copyFrom(spr, Common::Point(xp, yp), slot._depth, &scene._depthSurface, + 100, sprite->getTransparencyIndex()); + } else { + // No depth, so simply draw the image + spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex()); + } + } + + // Free sprite if it was a flipped one + if (flipped) + delete spr; + } +} + +void SpriteSlots::cleanUp() { + for (int i = (int)size() - 1; i >= 0; --i) { + if ((*this)[i]._flags < IMG_STATIC) + remove_at(i); + } +} + +/*------------------------------------------------------------------------*/ + +SpriteSets::~SpriteSets() { + clear(); +} + +int SpriteSets::add(SpriteAsset *asset, int idx) { + if (idx) + idx = idx + 49; + else + idx = size(); + + if (idx >= (int)size()) + resize(idx + 1); + + if ((*this)[idx]) { + delete (*this)[idx]; + } else { + ++_assetCount; + } + + (*this)[idx] = asset; + return idx; +} + +int SpriteSets::addSprites(const Common::String &resName, int flags) { + return add(new SpriteAsset(_vm, resName, flags)); +} + +void SpriteSets::clear() { + for (uint i = 0; i < size(); ++i) + delete (*this)[i]; + + _assetCount = 0; + Common::Array<SpriteAsset *>::clear(); +} + +void SpriteSets::remove(int idx) { + if (idx >= 0) { + if (idx < ((int)size() - 1)) { + delete (*this)[idx]; + (*this)[idx] = nullptr; + } else { + while (size() > 0 && (*this)[size() - 1] == nullptr) { + remove_at(size() - 1); + } + } + + if (_assetCount > 0) + --_assetCount; + } +} + +} // End of namespace MADS diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h new file mode 100644 index 0000000000..324122e348 --- /dev/null +++ b/engines/mads/sprites.h @@ -0,0 +1,239 @@ +/* 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 MADS_SPRITES_H +#define MADS_SPRITES_H + +#include "common/scummsys.h" +#include "common/array.h" +#include "mads/assets.h" +#include "mads/msurface.h" + +namespace MADS { + +enum SpriteFlags { + IMG_STATIC = 0, // Item should remain fixed on the screen + IMG_UPDATE = 1, // Item needs to be redrawn + IMG_ERASE = -1, // Erase image and remove it + IMG_REFRESH = -2, // Full refresh + IMG_OVERPRINT = -3, // Interface overprint + IMG_DELTA = -4, // Delta change + IMG_FULL_UPDATE = -5, // Interface refresh + IMG_UPDATE_ONLY = -20 // Update the active screen area only +}; + +class MADSEngine; + +struct BGR8 { + uint8 b, g, r; +}; + +typedef struct { + int32 x; // x position relative to GrBuff(0, 0) + int32 y; // y position relative to GrBuff(0, 0) + int32 scale_x; // x scale factor (can be negative for reverse draw) + int32 scale_y; // y scale factor (can't be negative) + uint8* depth_map; // depth code array for destination (doesn't care if srcDepth is 0) + BGR8* Pal; // palette for shadow draw (doesn't care if SHADOW bit is not set in Src.encoding) + uint8* ICT; // Inverse Color Table (doesn't care if SHADOW bit is not set in Src.encoding) + uint8 depth; // depth code for source (0 if no depth processing) +} DrawRequestX; + +typedef struct { + uint32 Pack; + uint32 Stream; + long hot_x; + long hot_y; + uint32 Width; + uint32 Height; + uint32 Comp; + uint32 Reserved[8]; + uint8* data; +} RendCell; + +#define SS_HEADER_NUM_FIELDS 14 +struct SpriteSeriesHeader { + uint32 header; + uint32 size; + uint32 packing; + uint32 frameRate; + uint32 pixSpeed; + uint32 maxWidth; + uint32 maxHeight; + uint32 reserved3; + uint32 reserved4; + uint32 reserved5; + uint32 reserved6; + uint32 reserved7; + uint32 reserved8; + uint32 count; +}; + +#define SF_HEADER_NUM_FIELDS 15 +struct SpriteFrameHeader { + uint32 pack; + uint32 stream; + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 comp; + uint32 reserved1; + uint32 reserved2; + uint32 reserved3; + uint32 reserved4; + uint32 reserved5; + uint32 reserved6; + uint32 reserved7; + uint32 reserved8; +}; + +class MSprite : public MSurface { +private: + void loadSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette); +public: + MSprite(); + MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette, + const Common::Rect &bounds); + virtual ~MSprite(); + + Common::Point _offset; + + byte getTransparencyIndex() const; +}; + +class SpriteSlotSubset { +public: + int _spritesIndex; + int _frameNumber; + Common::Point _position; + int _depth; + int _scale; +}; + +class SpriteSlot : public SpriteSlotSubset { +private: + static MADSEngine *_vm; + friend class SpriteSlots; +public: + SpriteFlags _flags; + int _seqIndex; +public: + SpriteSlot(); + SpriteSlot(SpriteFlags type, int seqIndex); + + void setup(int dirtyAreaIndex); + bool operator==(const SpriteSlotSubset &other) const; + void copy(const SpriteSlotSubset &other); +}; + +class SpriteSlots : public Common::Array<SpriteSlot> { +private: + MADSEngine *_vm; +public: + SpriteSlots(MADSEngine *vm); + + /** + * Clears any pending slot data and schedules a full screen refresh. + * @param flag Also reset sprite list + */ + void reset(bool flag = true); + + /** + * Delete a sprite entry + * @param index Specifies the index in the array + */ + void deleteEntry(int index); + + /** + * Setup dirty areas for the sprite slots + */ + void setDirtyAreas(); + + /** + * Adds a full screen refresh to the sprite slots + */ + void fullRefresh(bool clearAll = false); + + /** + * Delete a timer entry with the given Id + */ + void deleteTimer(int seqIndex); + + /** + * Add a new slot entry and return it's index + */ + int add(); + + /** + * Draw any sprites into the background of the scene + */ + void drawBackground(); + + /** + * Draw any sprites into the foreground of the scene + */ + void drawSprites(MSurface *s); + + void cleanUp(); +}; + +class SpriteSets : public Common::Array<SpriteAsset *> { +private: + MADSEngine *_vm; +public: + int _assetCount; + + /** + * Constructor + */ + SpriteSets(MADSEngine *vm) : _vm(vm), _assetCount(0) {} + + /** + * Destructor + */ + ~SpriteSets(); + + /** + * Clears the current list, freeing any laoded assets + */ + void clear(); + + /** + * Add a sprite asset to the list + */ + int add(SpriteAsset *asset, int idx = 0); + + /** + * Adds a sprite asset to the list by name + */ + int addSprites(const Common::String &resName, int flags = 0); + + /** + * Remove an asset from the list + */ + void remove(int idx); +}; + +} // End of namespace MADS + +#endif /* MADS_SPRITES_H */ diff --git a/engines/mads/staticres.cpp b/engines/mads/staticres.cpp new file mode 100644 index 0000000000..189e5f72e7 --- /dev/null +++ b/engines/mads/staticres.cpp @@ -0,0 +1,58 @@ +/* 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 "common/scummsys.h" +#include "mads/staticres.h" + +namespace MADS { + +const char *const kArticleList[9] = { + nullptr, "with", "to", "at", "from", "on", "in", "under", "behind" +}; + +const char *const kCheatingEnabledDesc[3] = { + "CHEATING ENABLED", + "(For your convenience).", + nullptr +}; + +const char *const kLookAroundStr = "Look around"; +const char *const kToStr = "to "; +const char *const kUseStr = "Use "; +const char *const kWalkToStr = "Walk to "; +const char *const kFenceStr = "fence"; +const char *const kOverStr = "over"; + +const char *const kGameReleaseInfoStr = "ScummVM rev: 8.43 14-Sept-92"; +const char *const kGameReleaseTitleStr = "GAME RELASE VERSION INFO"; + +const uint32 DEFAULT_VGA_LOW_PALETTE[16] = { + 0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400, 0xa8a8a8, + 0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc, 0xfcfc54, 0xfcfcfc +}; + +const uint32 DEFAULT_VGA_HIGH_PALETTE[16] = { + 0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040, 0x2c3c40, 0x2c3440, 0x2c3040, + 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 +}; + +} // End of namespace MADS diff --git a/engines/mads/staticres.h b/engines/mads/staticres.h new file mode 100644 index 0000000000..560fd12e67 --- /dev/null +++ b/engines/mads/staticres.h @@ -0,0 +1,47 @@ +/* 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 MADS_STATICRES_H +#define MADS_STATICRES_H + +namespace MADS { + +extern const char *const kArticleList[9]; + +extern const char *const kCheatingEnabledDesc[3]; + +extern const char *const kLookAroundStr; +extern const char *const kToStr; +extern const char *const kUseStr; +extern const char *const kWalkToStr; +extern const char *const kFenceStr; +extern const char *const kOverStr; + +extern const char *const kGameReleaseInfoStr; +extern const char *const kGameReleaseTitleStr; + +extern const uint32 DEFAULT_VGA_LOW_PALETTE[16]; +extern const uint32 DEFAULT_VGA_HIGH_PALETTE[16]; + +} // End of namespace MADS + +#endif /* MADS_STATICRES_H */ diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp new file mode 100644 index 0000000000..e410d173d7 --- /dev/null +++ b/engines/mads/user_interface.cpp @@ -0,0 +1,1096 @@ +/* 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 "common/scummsys.h" +#include "mads/mads.h" +#include "mads/compression.h" +#include "mads/user_interface.h" +#include "mads/nebular/game_nebular.h" + +namespace MADS { + +UISlot::UISlot() { + _flags = IMG_STATIC; + _segmentId = 0; + _spritesIndex = 0; + _frameNumber = 0; + _width = _height = 0; +} + +/*------------------------------------------------------------------------*/ + +void UISlots::fullRefresh() { + UISlot slot; + slot._flags = IMG_REFRESH; + slot._segmentId = -1; + + push_back(slot); +} + +void UISlots::add(const Common::Rect &bounds) { + assert(size() < 50); + + UISlot ie; + ie._flags = IMG_OVERPRINT; + ie._segmentId = IMG_TEXT_UPDATE; + ie._position = Common::Point(bounds.left, bounds.top); + ie._width = bounds.width(); + ie._height = bounds.height(); + + push_back(ie); +} + +void UISlots::add(const AnimFrameEntry &frameEntry) { + assert(size() < 50); + + UISlot ie; + ie._flags = IMG_UPDATE; + ie._segmentId = frameEntry._seqIndex; + ie._spritesIndex = frameEntry._spriteSlot._spritesIndex; + ie._frameNumber = frameEntry._spriteSlot._frameNumber; + ie._position = frameEntry._spriteSlot._position; + + push_back(ie); +} + +void UISlots::draw(bool updateFlag, bool delFlag) { + Scene &scene = _vm->_game->_scene; + UserInterface &userInterface = scene._userInterface; + DirtyArea *dirtyAreaPtr = nullptr; + + // Loop through setting up the dirty areas + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (slot._flags >= IMG_STATIC) { + dirtyArea._active = false; + } else { + dirtyArea.setUISlot(&slot); + dirtyArea._textActive = true; + if (slot._segmentId == IMG_SPINNING_OBJECT && slot._flags == IMG_FULL_UPDATE) { + dirtyArea._active = false; + dirtyAreaPtr = &dirtyArea; + } + } + } + + userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); + if (dirtyAreaPtr) + dirtyAreaPtr->_active = true; + + // Copy parts of the user interface background that need to be erased + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (dirtyArea._active && dirtyArea._bounds.width() > 0 + && dirtyArea._bounds.height() > 0 && slot._flags > -20) { + + if (slot._flags >= IMG_ERASE) { + // Merge area + userInterface.mergeFrom(&userInterface._surface, dirtyArea._bounds, + Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); + } else { + // Copy area + userInterface._surface.copyTo(&userInterface, dirtyArea._bounds, + Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top)); + } + } + } + + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + int slotType = slot._flags; + if (slotType >= IMG_STATIC) { + dirtyArea.setUISlot(&slot); + if (!updateFlag) + slotType &= ~0x40; + + dirtyArea._textActive = slotType > 0; + slot._flags &= 0x40; + } + } + + userInterface._dirtyAreas.merge(1, userInterface._uiSlots.size()); + + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea *dirtyArea = &userInterface._dirtyAreas[idx]; + UISlot &slot = (*this)[idx]; + + if (slot._flags >= IMG_STATIC && !(slot._flags & 0x40)) { + if (!dirtyArea->_active) { + do { + dirtyArea = dirtyArea->_mergedArea; + } while (!dirtyArea->_active); + } + + if (dirtyArea->_textActive) { + SpriteAsset *asset = scene._sprites[slot._spritesIndex]; + + // Get the frame details + int frameNumber = ABS(slot._frameNumber); + bool flipped = slot._frameNumber < 0; + + if (slot._segmentId == IMG_SPINNING_OBJECT) { + MSprite *sprite = asset->getFrame(frameNumber); + sprite->copyTo(&userInterface, slot._position, + sprite->getTransparencyIndex()); + } else { + MSprite *sprite = asset->getFrame(frameNumber - 1); + + if (flipped) { + MSurface *spr = sprite->flipHorizontal(); + userInterface.mergeFrom(spr, spr->getBounds(), slot._position, + sprite->getTransparencyIndex()); + delete spr; + } else { + userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position, + sprite->getTransparencyIndex()); + } + } + } + } + } + + // Mark areas of the screen surface for updating + if (updateFlag) { + for (uint idx = 0; idx < size(); ++idx) { + DirtyArea &dirtyArea = userInterface._dirtyAreas[idx]; + + if (dirtyArea._active && dirtyArea._textActive && + dirtyArea._bounds.width() > 0 && dirtyArea._bounds.height() > 0) { + // Flag area of screen as needing update + Common::Rect r = dirtyArea._bounds; + r.translate(0, scene._interfaceY); + _vm->_screen.copyRectToScreen(r); + } + } + } + + // Post-processing to remove slots no longer needed + for (int idx = (int)size() - 1; idx >= 0; --idx) { + UISlot &slot = (*this)[idx]; + + if (slot._flags < IMG_STATIC) { + if (delFlag || updateFlag) + remove_at(idx); + else if (slot._flags > -20) + slot._flags -= 20; + } else { + if (updateFlag) + slot._flags &= ~0x40; + else + slot._flags |= 0x40; + } + } +} + +/*------------------------------------------------------------------------*/ + +MADSEngine *Conversation::_vm; + +void Conversation::init(MADSEngine *vm) { + _vm = vm; +} + +void Conversation::setup(int globalId, ...) { + va_list va; + va_start(va, globalId); + + // Load the list of conversation quotes + _quotes.clear(); + int quoteId = va_arg(va, int); + while (quoteId > 0) { + _quotes.push_back(quoteId); + quoteId = va_arg(va, int); + } + va_end(va); + + if (quoteId < 0) { + // For an ending value of -1, also initial the bitflags for the global + // associated with the conversation entry, which enables all the quote Ids + _vm->_game->globals()[globalId] = (int16)0xffff; + } + + _globalId = globalId; +} + +void Conversation::set(int quoteId, ...) { + _vm->_game->globals()[_globalId] = 0; + + va_list va; + va_start(va, quoteId); + + // Loop through handling each quote + while (quoteId > 0) { + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (_quotes[idx] == quoteId) { + // Found index, so set that bit in the global keeping track of conversation state + _vm->_game->globals()[_globalId] |= 1 << idx; + break; + } + } + + quoteId = va_arg(va, int); + } + va_end(va); +} + +int Conversation::read(int quoteId) { + uint16 flags = _vm->_game->globals()[_globalId]; + int count = 0; + + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (flags & (1 << idx)) + ++count; + + if (_quotes[idx] == quoteId) + return flags & (1 << idx); + } + + // Could not find it, simply return number of active quotes + return count; +} + +void Conversation::write(int quoteId, bool flag) { + for (uint idx = 0; idx < _quotes.size(); ++idx) { + if (_quotes[idx] == quoteId) { + // Found index, so set or clear the flag + if (flag) { + // Set bit + _vm->_game->globals()[_globalId] |= 1 << idx; + } else { + // Clear bit + _vm->_game->globals()[_globalId] &= ~(1 << idx); + } + return; + } + } +} + +void Conversation::start() { + UserInterface &userInterface = _vm->_game->_scene._userInterface; + userInterface.emptyConversationList(); + + // Loop through each of the quotes loaded into the conversation + for (uint idx = 0; idx < _quotes.size(); ++idx) { + // Check whether the given quote is enabled or not + if (_vm->_game->globals()[_globalId] & (1 << idx)) { + // Quote enabled, so add it to the list of talk selections + Common::String msg = _vm->_game->getQuote(_quotes[idx]); + userInterface.addConversationMessage(_quotes[idx], msg); + } + } + + userInterface.setup(kInputConversation); +} + +/*------------------------------------------------------------------------*/ + +UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm), + _uiSlots(vm) { + _invSpritesIndex = -1; + _invFrameNumber = 1; + _scrollMilli = 0; + _scrollFlag = false; + _category = CAT_NONE; + _inventoryTopIndex = 0; + _selectedInvIndex = -1; + _selectedActionIndex = 0; + _selectedItemVocabIdx = -1; + _scrollbarActive = SCROLLBAR_NONE; + _scrollbarOldActive = SCROLLBAR_NONE; + _scrollbarStrokeType = SCROLLBAR_NONE; + _scrollbarQuickly = false; + _scrollbarMilliTime = 0; + _scrollbarElevator = _scrollbarOldElevator = 0; + _highlightedCommandIndex = -1; + _highlightedInvIndex = -1; + _highlightedItemVocabIndex = -1; + _dirtyAreas.resize(50); + _inventoryChanged = false; + _noSegmentsActive = 0; + _someSegmentsActive = 0; + _rectP = nullptr; + + Common::fill(&_categoryIndexes[0], &_categoryIndexes[7], 0); + + // Map the user interface to the bottom of the game's screen surface + byte *pData = _vm->_screen.getBasePtr(0, MADS_SCENE_HEIGHT); + setPixels(pData, MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT); + + _surface.setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT); +} + +void UserInterface::load(const Common::String &resName) { + File f(resName); + MadsPack madsPack(&f); + + // Load in the palette + Common::SeekableReadStream *palStream = madsPack.getItemStream(0); + + uint32 *gamePalP = &_vm->_palette->_palFlags[0]; + byte *palP = &_vm->_palette->_mainPalette[0]; + + for (int i = 0; i < 16; ++i, gamePalP++, palP += 3) { + RGB6 rgb; + rgb.load(palStream); + palP[0] = rgb.r; + palP[1] = rgb.g; + palP[2] = rgb.b; + *gamePalP |= 1; + } + delete palStream; + + // Read in the surface data + Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1); + pixelsStream->read(_surface.getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT); + delete pixelsStream; +} + +void UserInterface::setup(InputMode inputMode) { + Scene &scene = _vm->_game->_scene; + + if (_vm->_game->_screenObjects._inputMode != inputMode) { + Common::String resName = _vm->_game->_aaName; + + // Strip off any extension + const char *p = strchr(resName.c_str(), '.'); + if (p) { + resName = Common::String(resName.c_str(), p); + } + + // Add on suffix if necessary + if (inputMode != kInputBuildingSentences) + resName += "A"; + + resName += ".INT"; + + load(resName); + _surface.copyTo(this); + } + _vm->_game->_screenObjects._inputMode = inputMode; + + scene._userInterface._uiSlots.clear(); + scene._userInterface._uiSlots.fullRefresh(); + _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter(); + _highlightedCommandIndex = -1; + _highlightedItemVocabIndex = -1; + _highlightedInvIndex = -1; + + if (_vm->_game->_kernelMode == KERNEL_ACTIVE_CODE) + scene._userInterface._uiSlots.draw(false, false); + + scene._action.clear(); + drawTextElements(); + loadElements(); + scene._dynamicHotspots.refresh(); +} + +void UserInterface::drawTextElements() { + if (_vm->_game->_screenObjects._inputMode) { + drawConversationList(); + } else { + // Draw the actions + drawActions(); + drawInventoryList(); + drawItemVocabList(); + } +} + +void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds, + const Common::Point &destPos, int transparencyIndex) { + // Validation of the rectangle and position + int destX = destPos.x, destY = destPos.y; + if ((destX >= w) || (destY >= h)) + return; + + Common::Rect copyRect = srcBounds; + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } + + if (!copyRect.isValidRect()) + return; + + // Copy the specified area + + byte *data = src->getData(); + byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX; + + for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { + // Process each line of the area + for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) { + // Check for the range used for the user interface background, + // which are the only pixels that can be replaced + if ((destPtr[xCtr] >= 8 && destPtr[xCtr] <= 15) && (int)srcPtr[xCtr] != transparencyIndex) + destPtr[xCtr] = srcPtr[xCtr]; + } + + srcPtr += src->getWidth(); + destPtr += getWidth(); + } +} + +void UserInterface::drawActions() { + for (int idx = 0; idx < 10; ++idx) { + writeVocab(CAT_COMMAND, idx); + } +} + +void UserInterface::drawInventoryList() { + int endIndex = MIN((int)_vm->_game->_objects._inventoryList.size(), _inventoryTopIndex + 5); + for (int idx = _inventoryTopIndex; idx < endIndex; ++idx) { + writeVocab(CAT_INV_LIST, idx); + } +} + +void UserInterface::drawItemVocabList() { + if (_selectedInvIndex >= 0) { + InventoryObject &io = _vm->_game->_objects[ + _vm->_game->_objects._inventoryList[_selectedInvIndex]]; + for (int idx = 0; idx < io._vocabCount; ++idx) { + writeVocab(CAT_INV_VOCAB, idx); + } + } +} + +void UserInterface::drawScrolller() { + if (_scrollbarActive) + writeVocab(CAT_INV_SCROLLER, _scrollbarActive); + writeVocab(CAT_INV_SCROLLER, 4); +} + +void UserInterface::updateInventoryScroller() { + ScreenObjects &screenObjects = _vm->_game->_screenObjects; + Common::Array<int> &inventoryList = _vm->_game->_objects._inventoryList; + + if (screenObjects._inputMode != kInputBuildingSentences) + return; + + _scrollbarActive = SCROLLBAR_NONE; + + if ((screenObjects._category == CAT_INV_SCROLLER) || (screenObjects._category != CAT_INV_SCROLLER + && _scrollbarOldActive == SCROLLBAR_ELEVATOR && _vm->_events->_mouseStatusCopy)) { + if (_vm->_events->_mouseStatusCopy || _vm->_easyMouse) { + if ((_vm->_events->_mouseClicked || (_vm->_easyMouse && !_vm->_events->_mouseStatusCopy)) + && (screenObjects._category == CAT_INV_SCROLLER)) + _scrollbarStrokeType = (ScrollbarActive)screenObjects._spotId; + + if (screenObjects._spotId == _scrollbarStrokeType || _scrollbarOldActive == SCROLLBAR_ELEVATOR) { + _scrollbarActive = _scrollbarStrokeType; + uint32 currentMilli = g_system->getMillis(); + uint32 timeInc = _scrollbarQuickly ? 100 : 380; + + if (_vm->_events->_mouseStatus && (_scrollbarMilliTime + timeInc) <= currentMilli) { + _scrollbarQuickly = _vm->_events->_vD2 < 1; + _scrollbarMilliTime = currentMilli; + + switch (_scrollbarStrokeType) { + case SCROLLBAR_UP: + // Scroll up + if (_inventoryTopIndex > 0 && inventoryList.size() > 0) { + --_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_DOWN: + // Scroll down + if (_inventoryTopIndex < ((int)inventoryList.size() - 1) && inventoryList.size() > 1) { + ++_inventoryTopIndex; + _inventoryChanged = true; + } + break; + + case SCROLLBAR_ELEVATOR: { + // Inventory slider + int newIndex = CLIP((int)_vm->_events->currentPos().y - 170, 0, 17) + * inventoryList.size() / 10; + if (newIndex >= (int)inventoryList.size()) + newIndex = inventoryList.size() - 1; + + if (inventoryList.size() > 0) { + _inventoryChanged = newIndex != _inventoryTopIndex; + _inventoryTopIndex = newIndex; + } + break; + } + + default: + break; + } + + if (_inventoryChanged) { + int dummy; + updateSelection(CAT_INV_LIST, 0, &dummy); + } + } + } + } + } + + if (_scrollbarActive != _scrollbarOldActive || _scrollbarElevator != _scrollbarOldElevator) + scrollbarChanged(); + + _scrollbarOldActive = _scrollbarActive; + _scrollbarOldElevator = _scrollbarElevator; +} + +void UserInterface::scrollbarChanged() { + Common::Rect r(73, 4, 73 + 9, 4 + 38); + _uiSlots.add(r); + _uiSlots.draw(false, false); + drawScrolller(); + updateRect(r); +} + +void UserInterface::writeVocab(ScrCategory category, int id) { + Common::Rect bounds; + if (!getBounds(category, id, bounds)) + return; + + Scene &scene = _vm->_game->_scene; + Font *font = nullptr; + + int vocabId; + Common::String vocabStr; + switch (category) { + case CAT_COMMAND: + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = scene._verbList[id]._id; + if (id == _highlightedCommandIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedActionIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + } + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + + case CAT_INV_LIST: + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = _vm->_game->_objects.getItem(id)._descId; + if (id == _highlightedInvIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + } + + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + + case CAT_TALK_ENTRY: + font = _vm->_font->getFont(FONT_INTERFACE); + font->setColorMode(id == _highlightedCommandIndex ? SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED); + font->writeString(this, _talkStrings[id], Common::Point(bounds.left, bounds.top)); + break; + + case CAT_INV_SCROLLER: + font = _vm->_font->getFont(FONT_MISC); + + switch (id) { + case 1: + vocabStr = "a"; + break; + case 2: + vocabStr = "b"; + break; + case 3: + vocabStr = "d"; + break; + case 4: + vocabStr = "c"; + break; + default: + break; + } + + font->setColorMode((id == 4) || (_scrollbarActive == SCROLLBAR_ELEVATOR) ? + SELMODE_HIGHLIGHTED : SELMODE_UNSELECTED); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + default: + // Item specific verbs + font = _vm->_font->getFont(FONT_INTERFACE); + vocabId = _vm->_game->_objects.getItem(_selectedInvIndex)._vocabList[id]._vocabId; + if (id == _highlightedItemVocabIndex) { + _vm->_font->setColorMode(SELMODE_HIGHLIGHTED); + } else { + _vm->_font->setColorMode(id == _selectedInvIndex ? SELMODE_SELECTED : SELMODE_UNSELECTED); + vocabStr = scene.getVocab(vocabId); + vocabStr.setChar(toupper(vocabStr[0]), 0); + font->writeString(this, vocabStr, Common::Point(bounds.left, bounds.top)); + break; + } + break; + } +} + +void UserInterface::loadElements() { + Scene &scene = _vm->_game->_scene; + Common::Rect bounds; + _vm->_game->_screenObjects.clear(); + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) { + // Set up screen objects for the inventory scroller + for (int idx = 1; idx <= 3; ++idx) { + getBounds(CAT_INV_SCROLLER, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_SCROLLER, idx); + } + + // Set up actions + _categoryIndexes[CAT_COMMAND - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 10; ++idx) { + getBounds(CAT_COMMAND, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_COMMAND, idx); + } + + // Set up inventory list + _categoryIndexes[CAT_INV_LIST - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_INV_LIST, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_LIST, idx); + } + + // Set up the inventory vocab list + _categoryIndexes[CAT_INV_VOCAB - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_INV_VOCAB, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_INV_VOCAB, idx); + } + + // Set up the inventory item picture + _categoryIndexes[CAT_INV_ANIM - 1] = _vm->_game->_screenObjects.size() + 1; + _vm->_game->_screenObjects.add(Common::Rect(160, 159, 231, 194), LAYER_GUI, + CAT_INV_ANIM, 0); + } + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences) { + _categoryIndexes[CAT_HOTSPOT - 1] = _vm->_game->_screenObjects.size() + 1; + for (int hotspotIdx = scene._hotspots.size() - 1; hotspotIdx >= 0; --hotspotIdx) { + Hotspot &hs = scene._hotspots[hotspotIdx]; + _vm->_game->_screenObjects.add(hs._bounds, LAYER_GUI, CAT_HOTSPOT, hotspotIdx); + } + } + + if (_vm->_game->_screenObjects._inputMode == kInputConversation) { + // setup areas for talk entries + _categoryIndexes[CAT_TALK_ENTRY - 1] = _vm->_game->_screenObjects.size() + 1; + for (int idx = 0; idx < 5; ++idx) { + getBounds(CAT_TALK_ENTRY, idx, bounds); + moveRect(bounds); + + _vm->_game->_screenObjects.add(bounds, LAYER_GUI, CAT_TALK_ENTRY, idx); + } + } + + // Store the number of UI elements loaded for easy nuking/refreshing hotspots added later + _vm->_game->_screenObjects._uiCount = _vm->_game->_screenObjects.size(); +} + +bool UserInterface::getBounds(ScrCategory category, int v, Common::Rect &bounds) { + int heightMultiplier, widthMultiplier; + int leftStart, yOffset, widthAmt; + + switch (category) { + case CAT_COMMAND: + heightMultiplier = v % 5; + widthMultiplier = v / 5; + leftStart = 2; + yOffset = 3; + widthAmt = 32; + break; + + case CAT_INV_LIST: + if (v < _inventoryTopIndex || v >= (_inventoryTopIndex + 5)) + return false; + + heightMultiplier = v - _inventoryTopIndex; + widthMultiplier = 0; + leftStart = 90; + yOffset = 3; + widthAmt = 69; + break; + + case CAT_TALK_ENTRY: + heightMultiplier = v; + widthMultiplier = 0; + leftStart = 2; + yOffset = 3; + widthAmt = 310; + break; + + case CAT_INV_SCROLLER: + heightMultiplier = 0; + widthMultiplier = 0; + yOffset = 0; + widthAmt = 9; + leftStart = (v != 73) ? 73 : 75; + break; + + default: + heightMultiplier = v; + widthMultiplier = 0; + leftStart = 240; + yOffset = 3; + widthAmt = 80; + break; + } + + bounds.left = (widthMultiplier > 0) ? widthMultiplier * widthAmt + leftStart : leftStart; + bounds.setWidth(widthAmt); + bounds.top = heightMultiplier * 8 + yOffset; + bounds.setHeight(8); + + if (category == CAT_INV_SCROLLER) { + switch (v) { + case SCROLLBAR_UP: + // Arrow up + bounds.top = 4; + bounds.setHeight(7); + break; + case SCROLLBAR_DOWN: + // Arrow down + bounds.top = 35; + bounds.setHeight(7); + break; + case SCROLLBAR_ELEVATOR: + // Scroller + bounds.top = 12; + bounds.setHeight(22); + break; + case SCROLLBAR_THUMB: + // Thumb + bounds.top = _scrollbarElevator + 14; + bounds.setHeight(1); + break; + default: + break; + } + } + + return true; +} + +void UserInterface::moveRect(Common::Rect &bounds) { + bounds.translate(0, MADS_SCENE_HEIGHT); +} + +void UserInterface::drawConversationList() { + for (uint idx = 0; idx < _talkStrings.size(); ++idx) { + writeVocab(CAT_TALK_ENTRY, idx); + } +} + +void UserInterface::emptyConversationList() { + _talkStrings.clear(); + _talkIds.clear(); +} + +void UserInterface::addConversationMessage(int vocabId, const Common::String &msg) { + assert(_talkStrings.size() < 5); + + _talkStrings.push_back(msg); + _talkIds.push_back(vocabId); +} + +void UserInterface::loadInventoryAnim(int objectId) { + Scene &scene = _vm->_game->_scene; + noInventoryAnim(); + + if (_vm->_invObjectsAnimated) { + Common::String resName = Common::String::format("*OB%.3dI", objectId); + SpriteAsset *asset = new SpriteAsset(_vm, resName, 8); + _invSpritesIndex = scene._sprites.add(asset, 1); + if (_invSpritesIndex >= 0) { + _invFrameNumber = 1; + } + } +} + +void UserInterface::noInventoryAnim() { + Scene &scene = _vm->_game->_scene; + + if (_invSpritesIndex >= 0) { + scene._sprites.remove(_invSpritesIndex); + _vm->_game->_screenObjects._baseTime = _vm->_events->getFrameCounter(); + _invSpritesIndex = -1; + } + + if (_vm->_game->_screenObjects._inputMode == kInputBuildingSentences) + refresh(); +} + +void UserInterface::refresh() { + _uiSlots.clear(); + _uiSlots.fullRefresh(); + _uiSlots.draw(false, false); + + drawTextElements(); +} + +void UserInterface::inventoryAnim() { + Scene &scene = _vm->_game->_scene; + if (_vm->_game->_screenObjects._inputMode == kInputConversation || + _vm->_game->_screenObjects._inputMode == kInputLimitedSentences || + _invSpritesIndex < 0) + return; + + // Move to the next frame number in the sequence, resetting if at the end + SpriteAsset *asset = scene._sprites[_invSpritesIndex]; + if (++_invFrameNumber > asset->getCount()) + _invFrameNumber = 1; + + // Loop through the slots list for inventory animation entry + for (uint i = 0; i < _uiSlots.size(); ++i) { + if (_uiSlots[i]._segmentId == IMG_SPINNING_OBJECT) + _uiSlots[i]._flags = IMG_FULL_UPDATE; + } + + // Add a new slot entry for the inventory animation + UISlot slot; + slot._flags = IMG_UPDATE; + slot._segmentId = IMG_SPINNING_OBJECT; + slot._frameNumber = _invFrameNumber; + slot._spritesIndex = _invSpritesIndex; + slot._position = Common::Point(160, 3); + + _uiSlots.push_back(slot); +} + +void UserInterface::doBackgroundAnimation() { + Scene &scene = _vm->_game->_scene; + Common::Array<AnimUIEntry> &uiEntries = scene._animationData->_uiEntries; + Common::Array<AnimFrameEntry> &frameEntries = scene._animationData->_frameEntries; + + _noSegmentsActive = !_someSegmentsActive; + _someSegmentsActive = false; + + for (int idx = 0; idx < (int)uiEntries.size(); ++idx) { + AnimUIEntry &uiEntry = uiEntries[idx]; + + if (uiEntry._counter < 0) { + if (uiEntry._counter == -1) { + int probabilityRandom = _vm->getRandomNumber(1, 30000); + int probability = uiEntry._probability; + if (uiEntry._probability > 30000) { + if (_noSegmentsActive) { + probability -= 30000; + } else { + probability = -1; + } + } + if (probabilityRandom <= probability) { + uiEntry._counter = uiEntry._firstImage; + _someSegmentsActive = true; + } + } else { + uiEntry._counter = uiEntry._firstImage; + _someSegmentsActive = true; + } + } else { + for (int idx2 = 0; idx2 < ANIM_SPAWN_COUNT; idx2++) { + if (uiEntry._spawnFrame[idx2] == (uiEntry._counter - uiEntry._firstImage)) { + int tempIndex = uiEntry._spawn[idx2]; + if (idx >= tempIndex) { + uiEntries[tempIndex]._counter = uiEntries[tempIndex]._firstImage; + } else { + uiEntries[tempIndex]._counter = -2; + } + _someSegmentsActive = true; + } + } + + ++uiEntry._counter; + if (uiEntry._counter > uiEntry._lastImage) { + uiEntry._counter = -1; + } else { + _someSegmentsActive = true; + } + } + } + + for (uint idx = 0; idx < uiEntries.size(); ++idx) { + int imgScan = uiEntries[idx]._counter; + if (imgScan >= 0) { + _uiSlots.add(frameEntries[imgScan]); + } + } +} + +void UserInterface::categoryChanged() { + _highlightedInvIndex = -1; + _vm->_events->initVars(); + _category = CAT_NONE; +} + +void UserInterface::selectObject(int invIndex) { + if (_selectedInvIndex != invIndex || _inventoryChanged) { + int oldVocabCount = _selectedInvIndex < 0 ? 0 : _vm->_game->_objects.getItem(_selectedInvIndex)._vocabCount; + int newVocabCount = invIndex < 0 ? 0 : _vm->_game->_objects.getItem(invIndex)._vocabCount; + int maxVocab = MAX(oldVocabCount, newVocabCount); + + updateSelection(CAT_INV_LIST, invIndex, &_selectedInvIndex); + _highlightedItemVocabIndex = -1; + _selectedItemVocabIdx = -1; + + if (maxVocab) { + assert(_uiSlots.size() < 50); + int vocabHeight = maxVocab * 8; + + Common::Rect bounds(240, 3, 240 + 80, 3 + vocabHeight); + _uiSlots.add(bounds); + _uiSlots.draw(false, false); + drawItemVocabList(); + updateRect(bounds); + } + } + + if (invIndex == -1) { + noInventoryAnim(); + } else { + loadInventoryAnim(_vm->_game->_objects._inventoryList[invIndex]); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 7, 1); + _vm->_palette->setPalette(_vm->_palette->_mainPalette, 246, 2); + } +} + +void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx) { + Game &game = *_vm->_game; + Common::Array<int> &invList = game._objects._inventoryList; + Common::Rect bounds; + + if (category == CAT_INV_LIST && _inventoryChanged) { + *idx = newIndex; + bounds = Common::Rect(90, 3, 90 + 69, 3 + 40); + _uiSlots.add(bounds); + _uiSlots.draw(false, false); + drawInventoryList(); + updateRect(bounds); + _inventoryChanged = false; + + if (invList.size() < 2) { + _scrollbarElevator = 0; + } else { + int v = _inventoryTopIndex * 18 / (invList.size() - 1); + _scrollbarElevator = MIN(v, 17); + } + } else { + int oldIndex = *idx; + *idx = newIndex; + + if (oldIndex >= 0) { + writeVocab(category, oldIndex); + + if (getBounds(category, oldIndex, bounds)) + updateRect(bounds); + } + + if (newIndex >= 0) { + writeVocab(category, newIndex); + + if (getBounds(category, newIndex, bounds)) + updateRect(bounds); + } + } +} + +void UserInterface::updateRect(const Common::Rect &bounds) { + Common::Rect r = bounds; + r.translate(0, MADS_SCENE_HEIGHT); + _vm->_screen.copyRectToScreen(r); +} + +void UserInterface::scrollerChanged() { + warning("TODO: scrollerChanged"); +} + +void UserInterface::scrollInventory() { + Common::Array<int> &invList = _vm->_game->_objects._inventoryList; + + if (_vm->_events->_mouseButtons) { + int yp = _vm->_events->currentPos().y; + if (yp < MADS_SCENE_HEIGHT || yp == (MADS_SCREEN_HEIGHT - 1)) { + uint32 timeDiff = _scrollFlag ? 100 : 380; + uint32 currentMilli = g_system->getMillis(); + _vm->_game->_screenObjects._v8332A = -1; + + if (currentMilli >= (_scrollMilli + timeDiff)) { + _scrollMilli = currentMilli; + _scrollFlag = true; + + if (yp == (MADS_SCREEN_HEIGHT - 1)) { + if (_inventoryTopIndex < ((int)invList.size() - 1)) { + ++_inventoryTopIndex; + _inventoryChanged = true; + } + } else { + if (_inventoryTopIndex > 0) { + --_inventoryTopIndex; + _inventoryChanged = true; + } + } + } + } + } + + _vm->_game->_screenObjects._v8332A = 0; +} + +void UserInterface::synchronize(Common::Serializer &s) { + InventoryObjects &invObjects = _vm->_game->_objects; + + if (s.isLoading()) { + _selectedInvIndex = invObjects._inventoryList.empty() ? -1 : 0; + } + + for (int i = 0; i < 8; ++i) + s.syncAsSint16LE(_categoryIndexes[i]); +} + +} // End of namespace MADS diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h new file mode 100644 index 0000000000..827fa3041f --- /dev/null +++ b/engines/mads/user_interface.h @@ -0,0 +1,306 @@ +/* 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 MADS_USER_INTERFACE_H +#define MADS_USER_INTERFACE_H + +#include "common/scummsys.h" +#include "common/rect.h" +#include "common/str.h" +#include "mads/msurface.h" +#include "mads/screen.h" + +namespace MADS { + +enum { IMG_SPINNING_OBJECT = 200, IMG_TEXT_UPDATE = 201 }; + +enum ScrollbarActive { + SCROLLBAR_NONE = 0, // No state + SCROLLBAR_UP = 1, // Up butotn + SCROLLBAR_DOWN = 2, // Down button + SCROLLBAR_ELEVATOR = 3, // Elevator bar + SCROLLBAR_THUMB = 4 // Scrollbar thumb +}; + +class AnimFrameEntry; +class MADSEngine; + +class UISlot { +public: + int _flags; + int _segmentId; + int _spritesIndex; + int _frameNumber; + Common::Point _position; + + // Only used for IMG_OVERPRINT + int _width; + int _height; + + UISlot(); +}; + +/** + * Sprite list for the user interface + */ +class UISlots : public Common::Array<UISlot> { +private: + MADSEngine *_vm; +public: + /** + * Constructor + */ + UISlots(MADSEngine *vm) : _vm(vm) {} + + /** + * Add an overprint (text) entry to the list + */ + void add(const Common::Rect &bounds); + + /** + * Loads the data from an aimation frame entry + */ + void add(const AnimFrameEntry &frameEntry); + + /** + * Adds a special entry for full refresh of the user interface + */ + void fullRefresh(); + + /** + * Draw all the sprites in the list on the user interface. + * @param updateFlag Flag drawn areas to be updated on physical screen + * @param delFlag Controls how used slots are deleted after drawing + */ + void draw(bool updateFlag, bool delFlag); +}; + +class Conversation { +private: + static MADSEngine *_vm; +public: + static void init(MADSEngine *vm); +public: + int _globalId; + Common::Array<int> _quotes; + + /** + * Set up a conversation sequence + */ + void setup(int globalId, ...); + + /** + * Activates the passed set of quotes in the given conversation node + */ + void set(int quoteId, ...); + + /** + * Returns the bit for a given quote to indicate whether it's active or not or, + * if 0 is passed, returns the number of currently active quotes + */ + int read(int quoteId); + + /** + * Activates or deactivates the specified quote in the given conversation node + */ + void write(int quoteId, bool flag); + + /** + * Starts the conversation + */ + void start(); +}; + +class UserInterface : public MSurface { + friend class UISlots; +private: + MADSEngine *_vm; + int _invSpritesIndex; + int _invFrameNumber; + uint32 _scrollMilli; + bool _scrollFlag; + int _noSegmentsActive; + int _someSegmentsActive; + ScrollbarActive _scrollbarStrokeType; + + /** + * Loads the elements of the user interface + */ + void loadElements(); + + /** + * Returns the area within the user interface a given element falls + */ + bool getBounds(ScrCategory category, int invIndex, Common::Rect &bounds); + + /** + * Reposition a bounding rectangle to physical co-ordinates + */ + void moveRect(Common::Rect &bounds); + + /** + * Draw options during a conversation. + */ + void drawConversationList(); + + /** + * Draw the action list + */ + void drawActions(); + + /** + * Draw the inventory list + */ + void drawInventoryList(); + + /** + * Draw the inventory item vocab list + */ + void drawItemVocabList(); + + /** + * Draw the inventory scroller + */ + void drawScrolller(); + + /** + * Called when the inventory scrollbar has changed + */ + void scrollbarChanged(); + + /** + * Draw a UI textual element + */ + void writeVocab(ScrCategory category, int id); + + void refresh(); + + void updateRect(const Common::Rect &bounds); +public: + MSurface _surface; + UISlots _uiSlots; + DirtyAreas _dirtyAreas; + ScrCategory _category; + Common::Rect *_rectP; + int _inventoryTopIndex; + int _selectedInvIndex; + int _selectedActionIndex; + int _selectedItemVocabIdx; + ScrollbarActive _scrollbarActive, _scrollbarOldActive; + int _highlightedCommandIndex; + int _highlightedInvIndex; + int _highlightedItemVocabIndex; + bool _inventoryChanged; + int _categoryIndexes[8]; + Common::StringArray _talkStrings; + Common::Array<int> _talkIds; + bool _scrollbarQuickly; + uint32 _scrollbarMilliTime; + int _scrollbarElevator, _scrollbarOldElevator; +public: + /** + * Constructor + */ + UserInterface(MADSEngine *vm); + + /** + * Loads an interface from a specified resource + */ + void load(const Common::String &resName); + + /** + * Set up the interface + */ + void setup(InputMode inputMode); + + void drawTextElements(); + + /** + * Merges a sub-section of another surface into the user interface without + * destroying any on-screen text + * @param src Source surface + * @param srcBounds Area to copy/merge from + * @param destPos Destination position to draw in current surface + * @param transparencyIndex Transparency color + */ + void mergeFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos, + int transparencyIndex = -1); + + /** + * Loads the animation sprite data for a given inventory object + */ + void loadInventoryAnim(int objectId); + + /** + * Resets the inventory animation when no inventory item is selected + */ + void noInventoryAnim(); + + /** + * Handles any animation that occurs in the background of the user interface + */ + void doBackgroundAnimation(); + + /** + * Handles queuing a new frame of an inventory animation for drawing + */ + void inventoryAnim(); + + void categoryChanged(); + + /** + * Select an item from the inventory list + * @param invIndex Index in the inventory list of the item to select + */ + void selectObject(int invIndex); + + void updateSelection(ScrCategory category, int newIndex, int *idx); + + void scrollerChanged(); + + void scrollInventory(); + + /** + * Checks for the mouse being on the user interface inventory scroller, + * and update the scroller highlight and selected inventory object as necessary + */ + void updateInventoryScroller(); + + /** + * Empties the current conversation talk list + */ + void emptyConversationList(); + + /** + * Add a msesage to the list of conversation items to select from + */ + void addConversationMessage(int vocabId, const Common::String &msg); + + /** + * Synchronize the data + */ + void synchronize(Common::Serializer &s); +}; + +} // End of namespace MADS + +#endif /* MADS_USER_INTERFACE_H */ diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 2e83eb3328..d49f3e8637 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -49,20 +49,20 @@ namespace Mohawk { #ifdef ENABLE_MYST MystConsole::MystConsole(MohawkEngine_Myst *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard)); - DCmd_Register("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard)); - DCmd_Register("var", WRAP_METHOD(MystConsole, Cmd_Var)); - DCmd_Register("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack)); - DCmd_Register("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack)); - DCmd_Register("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage)); - DCmd_Register("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect)); - DCmd_Register("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable)); - DCmd_Register("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound)); - DCmd_Register("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie)); - DCmd_Register("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes)); - DCmd_Register("cache", WRAP_METHOD(MystConsole, Cmd_Cache)); - DCmd_Register("resources", WRAP_METHOD(MystConsole, Cmd_Resources)); + registerCmd("changeCard", WRAP_METHOD(MystConsole, Cmd_ChangeCard)); + registerCmd("curCard", WRAP_METHOD(MystConsole, Cmd_CurCard)); + registerCmd("var", WRAP_METHOD(MystConsole, Cmd_Var)); + registerCmd("curStack", WRAP_METHOD(MystConsole, Cmd_CurStack)); + registerCmd("changeStack", WRAP_METHOD(MystConsole, Cmd_ChangeStack)); + registerCmd("drawImage", WRAP_METHOD(MystConsole, Cmd_DrawImage)); + registerCmd("drawRect", WRAP_METHOD(MystConsole, Cmd_DrawRect)); + registerCmd("setResourceEnable", WRAP_METHOD(MystConsole, Cmd_SetResourceEnable)); + registerCmd("playSound", WRAP_METHOD(MystConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(MystConsole, Cmd_StopSound)); + registerCmd("playMovie", WRAP_METHOD(MystConsole, Cmd_PlayMovie)); + registerCmd("disableInitOpcodes", WRAP_METHOD(MystConsole, Cmd_DisableInitOpcodes)); + registerCmd("cache", WRAP_METHOD(MystConsole, Cmd_Cache)); + registerCmd("resources", WRAP_METHOD(MystConsole, Cmd_Resources)); } MystConsole::~MystConsole() { @@ -70,7 +70,7 @@ MystConsole::~MystConsole() { bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCard <card>\n"); + debugPrintf("Usage: changeCard <card>\n"); return true; } @@ -81,20 +81,20 @@ bool MystConsole::Cmd_ChangeCard(int argc, const char **argv) { } bool MystConsole::Cmd_CurCard(int argc, const char **argv) { - DebugPrintf("Current Card: %d\n", _vm->getCurCard()); + debugPrintf("Current Card: %d\n", _vm->getCurCard()); return true; } bool MystConsole::Cmd_Var(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var <var> (<value>)\n"); + debugPrintf("Usage: var <var> (<value>)\n"); return true; } if (argc > 2) _vm->_scriptParser->setVarValue((uint16)atoi(argv[1]), (uint16)atoi(argv[2])); - DebugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1]))); + debugPrintf("%d = %d\n", (uint16)atoi(argv[1]), _vm->_scriptParser->getVar((uint16)atoi(argv[1]))); return true; } @@ -130,19 +130,19 @@ static const uint16 default_start_card[12] = { }; bool MystConsole::Cmd_CurStack(int argc, const char **argv) { - DebugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]); + debugPrintf("Current Stack: %s\n", mystStackNames[_vm->getCurStack()]); return true; } bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { if (argc != 2 && argc != 3) { - DebugPrintf("Usage: changeStack <stack> [<card>]\n\n"); - DebugPrintf("Stacks:\n=======\n"); + debugPrintf("Usage: changeStack <stack> [<card>]\n\n"); + debugPrintf("Stacks:\n=======\n"); for (byte i = 0; i < ARRAYSIZE(mystStackNames); i++) - DebugPrintf(" %s\n", mystStackNames[i]); + debugPrintf(" %s\n", mystStackNames[i]); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -156,7 +156,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { } if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } @@ -177,7 +177,7 @@ bool MystConsole::Cmd_ChangeStack(int argc, const char **argv) { bool MystConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc != 2 && argc != 6) { - DebugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n"); + debugPrintf("Usage: drawImage <image> [<left> <top> <right> <bottom>]\n"); return true; } @@ -195,8 +195,8 @@ bool MystConsole::Cmd_DrawImage(int argc, const char **argv) { bool MystConsole::Cmd_DrawRect(int argc, const char **argv) { if (argc != 5 && argc != 2) { - DebugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n"); - DebugPrintf("Usage: drawRect <resource id>\n"); + debugPrintf("Usage: drawRect <left> <top> <right> <bottom>\n"); + debugPrintf("Usage: drawRect <resource id>\n"); return true; } @@ -213,7 +213,7 @@ bool MystConsole::Cmd_DrawRect(int argc, const char **argv) { bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: setResourceEnable <resource id> <bool>\n"); + debugPrintf("Usage: setResourceEnable <resource id> <bool>\n"); return true; } @@ -223,7 +223,7 @@ bool MystConsole::Cmd_SetResourceEnable(int argc, const char **argv) { bool MystConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -234,7 +234,7 @@ bool MystConsole::Cmd_PlaySound(int argc, const char **argv) { } bool MystConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); @@ -243,8 +243,8 @@ bool MystConsole::Cmd_StopSound(int argc, const char **argv) { bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n"); - DebugPrintf("NOTE: The movie will play *once* in the background.\n"); + debugPrintf("Usage: playMovie <name> [<stack>] [<left> <top>]\n"); + debugPrintf("NOTE: The movie will play *once* in the background.\n"); return true; } @@ -258,7 +258,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { } if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[2]); + debugPrintf("\'%s\' is not a stack name!\n", argv[2]); return true; } } @@ -277,7 +277,7 @@ bool MystConsole::Cmd_PlayMovie(int argc, const char **argv) { bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: disableInitOpcodes\n"); + debugPrintf("Usage: disableInitOpcodes\n"); return true; } @@ -289,7 +289,7 @@ bool MystConsole::Cmd_DisableInitOpcodes(int argc, const char **argv) { bool MystConsole::Cmd_Cache(int argc, const char **argv) { if (argc > 2) { - DebugPrintf("Usage: cache on/off - Omit parameter to get current state\n"); + debugPrintf("Usage: cache on/off - Omit parameter to get current state\n"); return true; } @@ -304,15 +304,15 @@ bool MystConsole::Cmd_Cache(int argc, const char **argv) { _vm->setCacheState(state); } - DebugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled"); + debugPrintf("Cache: %s\n", state ? "Enabled" : "Disabled"); return true; } bool MystConsole::Cmd_Resources(int argc, const char **argv) { - DebugPrintf("Resources in card %d:\n", _vm->getCurCard()); + debugPrintf("Resources in card %d:\n", _vm->getCurCard()); for (uint i = 0; i < _vm->_resources.size(); i++) { - DebugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str()); + debugPrintf("#%2d %s\n", i, _vm->_resources[i]->describe().c_str()); } return true; @@ -323,21 +323,21 @@ bool MystConsole::Cmd_Resources(int argc, const char **argv) { #ifdef ENABLE_RIVEN RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard)); - DCmd_Register("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard)); - DCmd_Register("var", WRAP_METHOD(RivenConsole, Cmd_Var)); - DCmd_Register("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound)); - DCmd_Register("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST)); - DCmd_Register("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound)); - DCmd_Register("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack)); - DCmd_Register("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack)); - DCmd_Register("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots)); - DCmd_Register("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode)); - DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); - DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); - DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); - DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); - DCmd_Register("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState)); + registerCmd("changeCard", WRAP_METHOD(RivenConsole, Cmd_ChangeCard)); + registerCmd("curCard", WRAP_METHOD(RivenConsole, Cmd_CurCard)); + registerCmd("var", WRAP_METHOD(RivenConsole, Cmd_Var)); + registerCmd("playSound", WRAP_METHOD(RivenConsole, Cmd_PlaySound)); + registerCmd("playSLST", WRAP_METHOD(RivenConsole, Cmd_PlaySLST)); + registerCmd("stopSound", WRAP_METHOD(RivenConsole, Cmd_StopSound)); + registerCmd("curStack", WRAP_METHOD(RivenConsole, Cmd_CurStack)); + registerCmd("changeStack", WRAP_METHOD(RivenConsole, Cmd_ChangeStack)); + registerCmd("hotspots", WRAP_METHOD(RivenConsole, Cmd_Hotspots)); + registerCmd("zipMode", WRAP_METHOD(RivenConsole, Cmd_ZipMode)); + registerCmd("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); + registerCmd("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); + registerCmd("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); + registerCmd("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); + registerCmd("sliderState", WRAP_METHOD(RivenConsole, Cmd_SliderState)); } RivenConsole::~RivenConsole() { @@ -346,7 +346,7 @@ RivenConsole::~RivenConsole() { bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCard <card>\n"); + debugPrintf("Usage: changeCard <card>\n"); return true; } @@ -358,19 +358,19 @@ bool RivenConsole::Cmd_ChangeCard(int argc, const char **argv) { } bool RivenConsole::Cmd_CurCard(int argc, const char **argv) { - DebugPrintf("Current Card: %d\n", _vm->getCurCard()); + debugPrintf("Current Card: %d\n", _vm->getCurCard()); return true; } bool RivenConsole::Cmd_Var(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: var <var name> (<value>)\n"); + debugPrintf("Usage: var <var name> (<value>)\n"); return true; } if (!_vm->_vars.contains(argv[1])) { - DebugPrintf("Unknown variable '%s'\n", argv[1]); + debugPrintf("Unknown variable '%s'\n", argv[1]); return true; } @@ -379,13 +379,13 @@ bool RivenConsole::Cmd_Var(int argc, const char **argv) { if (argc > 2) var = (uint32)atoi(argv[2]); - DebugPrintf("%s = %d\n", argv[1], var); + debugPrintf("%s = %d\n", argv[1], var); return true; } bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -397,7 +397,7 @@ bool RivenConsole::Cmd_PlaySound(int argc, const char **argv) { bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: playSLST <slst index> <card, default = current>\n"); + debugPrintf("Usage: playSLST <slst index> <card, default = current>\n"); return true; } @@ -412,7 +412,7 @@ bool RivenConsole::Cmd_PlaySLST(int argc, const char **argv) { } bool RivenConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); _vm->_sound->stopAllSLST(); @@ -420,58 +420,57 @@ bool RivenConsole::Cmd_StopSound(int argc, const char **argv) { } bool RivenConsole::Cmd_CurStack(int argc, const char **argv) { - DebugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str()); + debugPrintf("Current Stack: %s\n", _vm->getStackName(_vm->getCurStack()).c_str()); return true; } bool RivenConsole::Cmd_ChangeStack(int argc, const char **argv) { - byte i; - if (argc < 3) { - DebugPrintf("Usage: changeStack <stack> <card>\n\n"); - DebugPrintf("Stacks:\n=======\n"); + debugPrintf("Usage: changeStack <stack> <card>\n\n"); + debugPrintf("Stacks:\n=======\n"); - for (i = 0; i <= tspit; i++) - DebugPrintf(" %s\n", _vm->getStackName(i).c_str()); + for (uint i = kStackFirst; i <= kStackLast; i++) + debugPrintf(" %s\n", _vm->getStackName(i).c_str()); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } - byte stackNum = 0; + uint stack = kStackUnknown; - for (i = 1; i <= tspit + 1; i++) - if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) { - stackNum = i; + for (uint i = kStackFirst; i <= kStackLast; i++) { + if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) { + stack = i; break; } + } - if (!stackNum) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + if (stack == kStackUnknown) { + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } - _vm->changeToStack(stackNum - 1); + _vm->changeToStack(stack); _vm->changeToCard((uint16)atoi(argv[2])); return false; } bool RivenConsole::Cmd_Hotspots(int argc, const char **argv) { - DebugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount()); + debugPrintf("Current card (%d) has %d hotspots:\n", _vm->getCurCard(), _vm->getHotspotCount()); for (uint16 i = 0; i < _vm->getHotspotCount(); i++) { - DebugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID); + debugPrintf("Hotspot %d, index %d, BLST ID %d (", i, _vm->_hotspots[i].index, _vm->_hotspots[i].blstID); if (_vm->_hotspots[i].enabled) - DebugPrintf("enabled"); + debugPrintf("enabled"); else - DebugPrintf("disabled"); + debugPrintf("disabled"); - DebugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom); - DebugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str()); + debugPrintf(") - (%d, %d, %d, %d)\n", _vm->_hotspots[i].rect.left, _vm->_hotspots[i].rect.top, _vm->_hotspots[i].rect.right, _vm->_hotspots[i].rect.bottom); + debugPrintf(" Name = %s\n", _vm->getHotspotName(i).c_str()); } return true; @@ -481,34 +480,33 @@ bool RivenConsole::Cmd_ZipMode(int argc, const char **argv) { uint32 &zipModeActive = _vm->_vars["azip"]; zipModeActive = !zipModeActive; - DebugPrintf("Zip Mode is "); - DebugPrintf(zipModeActive ? "Enabled" : "Disabled"); - DebugPrintf("\n"); + debugPrintf("Zip Mode is "); + debugPrintf(zipModeActive ? "Enabled" : "Disabled"); + debugPrintf("\n"); return true; } bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); + debugPrintf("Usage: dumpScript <stack> <CARD or HSPT> <card>\n"); return true; } uint16 oldStack = _vm->getCurStack(); + uint newStack = kStackUnknown; - byte newStack = 0; - - for (byte i = 1; i <= tspit + 1; i++) - if (!scumm_stricmp(argv[1], _vm->getStackName(i - 1).c_str())) { + for (uint i = kStackFirst; i <= kStackLast; i++) { + if (!scumm_stricmp(argv[1], _vm->getStackName(i).c_str())) { newStack = i; break; } + } - if (!newStack) { - DebugPrintf("\'%s\' is not a stack name!\n", argv[1]); + if (newStack == kStackUnknown) { + debugPrintf("\'%s\' is not a stack name!\n", argv[1]); return true; } - newStack--; _vm->changeToStack(newStack); // Load in Variable Names @@ -594,7 +592,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { delete hsptStream; } else { - DebugPrintf("%s doesn't have any scripts!\n", argv[2]); + debugPrintf("%s doesn't have any scripts!\n", argv[2]); } // See above for why this is printed via debugN @@ -602,18 +600,18 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { _vm->changeToStack(oldStack); - DebugPrintf("Script dump complete.\n"); + debugPrintf("Script dump complete.\n"); return true; } bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) { if (_vm->_zipModeData.size() == 0) { - DebugPrintf("No zip card data.\n"); + debugPrintf("No zip card data.\n"); } else { - DebugPrintf("Listing zip cards:\n"); + debugPrintf("Listing zip cards:\n"); for (uint32 i = 0; i < _vm->_zipModeData.size(); i++) - DebugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str()); + debugPrintf("ID = %d, Name = %s\n", _vm->_zipModeData[i].id, _vm->_zipModeData[i].name.c_str()); } return true; @@ -621,7 +619,7 @@ bool RivenConsole::Cmd_ListZipCards(int argc, const char **argv) { bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) { uint32 rmapCode = _vm->getCurCardRMAP(); - DebugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode); + debugPrintf("RMAP for %s %d = %08x\n", _vm->getStackName(_vm->getCurStack()).c_str(), _vm->getCurCard(), rmapCode); return true; } @@ -635,20 +633,20 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) { uint32 prisonCombo = _vm->_vars["pcorrectorder"]; uint32 domeCombo = _vm->_vars["adomecombo"]; - DebugPrintf("Telescope Combo:\n "); + debugPrintf("Telescope Combo:\n "); for (int i = 0; i < 5; i++) - DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); + debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); - DebugPrintf("\nPrison Combo:\n "); + debugPrintf("\nPrison Combo:\n "); for (int i = 0; i < 5; i++) - DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); + debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); - DebugPrintf("\nDome Combo:\n "); + debugPrintf("\nDome Combo:\n "); for (int i = 1; i <= 25; i++) if (domeCombo & (1 << (25 - i))) - DebugPrintf("%d ", i); + debugPrintf("%d ", i); - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -656,17 +654,17 @@ bool RivenConsole::Cmd_SliderState(int argc, const char **argv) { if (argc > 1) _vm->_externalScriptHandler->setDomeSliderState((uint32)atoi(argv[1])); - DebugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState()); + debugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState()); return true; } #endif // ENABLE_RIVEN LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); - DCmd_Register("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage)); - DCmd_Register("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage)); + registerCmd("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); + registerCmd("drawImage", WRAP_METHOD(LivingBooksConsole, Cmd_DrawImage)); + registerCmd("changePage", WRAP_METHOD(LivingBooksConsole, Cmd_ChangePage)); } LivingBooksConsole::~LivingBooksConsole() { @@ -674,7 +672,7 @@ LivingBooksConsole::~LivingBooksConsole() { bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -684,7 +682,7 @@ bool LivingBooksConsole::Cmd_PlaySound(int argc, const char **argv) { } bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); return true; @@ -692,7 +690,7 @@ bool LivingBooksConsole::Cmd_StopSound(int argc, const char **argv) { bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: drawImage <value>\n"); + debugPrintf("Usage: drawImage <value>\n"); return true; } @@ -703,13 +701,13 @@ bool LivingBooksConsole::Cmd_DrawImage(int argc, const char **argv) { bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) { if (argc < 2 || argc > 3) { - DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); + debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); return true; } int page, subpage = 0; if (sscanf(argv[1], "%d.%d", &page, &subpage) == 0) { - DebugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); + debugPrintf("Usage: changePage <page>[.<subpage>] [<mode>]\n"); return true; } LBMode mode = argc == 2 ? _vm->getCurMode() : (LBMode)atoi(argv[2]); @@ -720,21 +718,21 @@ bool LivingBooksConsole::Cmd_ChangePage(int argc, const char **argv) { if (_vm->loadPage(mode, page, subpage)) return false; } - DebugPrintf("no such page %d.%d\n", page, subpage); + debugPrintf("no such page %d.%d\n", page, subpage); return true; } #ifdef ENABLE_CSTIME CSTimeConsole::CSTimeConsole(MohawkEngine_CSTime *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound)); - DCmd_Register("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound)); - DCmd_Register("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage)); - DCmd_Register("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage)); - DCmd_Register("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase)); - DCmd_Register("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene)); - DCmd_Register("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable)); - DCmd_Register("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem)); + registerCmd("playSound", WRAP_METHOD(CSTimeConsole, Cmd_PlaySound)); + registerCmd("stopSound", WRAP_METHOD(CSTimeConsole, Cmd_StopSound)); + registerCmd("drawImage", WRAP_METHOD(CSTimeConsole, Cmd_DrawImage)); + registerCmd("drawSubimage", WRAP_METHOD(CSTimeConsole, Cmd_DrawSubimage)); + registerCmd("changeCase", WRAP_METHOD(CSTimeConsole, Cmd_ChangeCase)); + registerCmd("changeScene", WRAP_METHOD(CSTimeConsole, Cmd_ChangeScene)); + registerCmd("caseVariable", WRAP_METHOD(CSTimeConsole, Cmd_CaseVariable)); + registerCmd("invItem", WRAP_METHOD(CSTimeConsole, Cmd_InvItem)); } CSTimeConsole::~CSTimeConsole() { @@ -742,7 +740,7 @@ CSTimeConsole::~CSTimeConsole() { bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: playSound <value>\n"); + debugPrintf("Usage: playSound <value>\n"); return true; } @@ -752,7 +750,7 @@ bool CSTimeConsole::Cmd_PlaySound(int argc, const char **argv) { } bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) { - DebugPrintf("Stopping Sound\n"); + debugPrintf("Stopping Sound\n"); _vm->_sound->stopSound(); return true; @@ -760,7 +758,7 @@ bool CSTimeConsole::Cmd_StopSound(int argc, const char **argv) { bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: drawImage <value>\n"); + debugPrintf("Usage: drawImage <value>\n"); return true; } @@ -771,7 +769,7 @@ bool CSTimeConsole::Cmd_DrawImage(int argc, const char **argv) { bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: drawSubimage <value> <subimage>\n"); + debugPrintf("Usage: drawSubimage <value> <subimage>\n"); return true; } @@ -782,7 +780,7 @@ bool CSTimeConsole::Cmd_DrawSubimage(int argc, const char **argv) { bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeCase <value>\n"); + debugPrintf("Usage: changeCase <value>\n"); return true; } @@ -792,7 +790,7 @@ bool CSTimeConsole::Cmd_ChangeCase(int argc, const char **argv) { bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: changeScene <value>\n"); + debugPrintf("Usage: changeScene <value>\n"); return true; } @@ -802,12 +800,12 @@ bool CSTimeConsole::Cmd_ChangeScene(int argc, const char **argv) { bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: caseVariable <id> [<value>]\n"); + debugPrintf("Usage: caseVariable <id> [<value>]\n"); return true; } if (argc == 2) { - DebugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]); + debugPrintf("case variable %d has value %d\n", atoi(argv[1]), _vm->_caseVariable[atoi(argv[1])]); } else { _vm->_caseVariable[atoi(argv[1])] = atoi(argv[2]); } @@ -816,7 +814,7 @@ bool CSTimeConsole::Cmd_CaseVariable(int argc, const char **argv) { bool CSTimeConsole::Cmd_InvItem(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Usage: invItem <id> <0 or 1>\n"); + debugPrintf("Usage: invItem <id> <0 or 1>\n"); return true; } diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index e1059bebaa..a7fe12b9e1 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -55,7 +55,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _activatedSLST = false; _ignoreNextMouseUp = false; _extrasFile = 0; - _curStack = aspit; + _curStack = kStackUnknown; _hotspots = 0; removeTimer(); @@ -161,7 +161,7 @@ Common::Error MohawkEngine_Riven::run() { // Let's begin, shall we? if (getFeatures() & GF_DEMO) { // Start the demo off with the videos - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } else if (ConfMan.hasKey("save_slot")) { // Load game from launcher/command line if requested @@ -172,12 +172,12 @@ Common::Error MohawkEngine_Riven::run() { // Attempt to load the game. On failure, just send us to the main menu. if (_saveLoad->loadGame(savedGamesList[gameToLoad]).getCode() != Common::kNoError) { - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(1); } } else { // Otherwise, start us off at aspit's card 1 (the main menu) - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(1); } @@ -255,16 +255,16 @@ void MohawkEngine_Riven::handleEvents() { case Common::KEYCODE_r: // Return to the main menu in the demo on ctrl+r if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) { - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(1); } break; case Common::KEYCODE_p: // Play the intro videos in the demo on ctrl+p if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) { - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(6); } break; @@ -343,20 +343,22 @@ struct RivenSpecialChange { uint32 startCardRMAP; byte targetStack; uint32 targetCardRMAP; -} rivenSpecialChange[] = { - { aspit, 0x1f04, ospit, 0x44ad }, // Trap Book - { bspit, 0x1c0e7, ospit, 0x2e76 }, // Dome Linking Book - { gspit, 0x111b1, ospit, 0x2e76 }, // Dome Linking Book - { jspit, 0x28a18, rspit, 0xf94 }, // Tay Linking Book - { jspit, 0x26228, ospit, 0x2e76 }, // Dome Linking Book - { ospit, 0x5f0d, pspit, 0x3bf0 }, // Return from 233rd Age - { ospit, 0x470a, jspit, 0x1508e }, // Return from 233rd Age - { ospit, 0x5c52, gspit, 0x10bea }, // Return from 233rd Age - { ospit, 0x5d68, bspit, 0x1adfd }, // Return from 233rd Age - { ospit, 0x5e49, tspit, 0xe87 }, // Return from 233rd Age - { pspit, 0x4108, ospit, 0x2e76 }, // Dome Linking Book - { rspit, 0x32d8, jspit, 0x1c474 }, // Return from Tay - { tspit, 0x21b69, ospit, 0x2e76 } // Dome Linking Book +}; + +static const RivenSpecialChange rivenSpecialChange[] = { + { kStackAspit, 0x1f04, kStackOspit, 0x44ad }, // Trap Book + { kStackBspit, 0x1c0e7, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackGspit, 0x111b1, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackJspit, 0x28a18, kStackRspit, 0xf94 }, // Tay Linking Book + { kStackJspit, 0x26228, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackOspit, 0x5f0d, kStackPspit, 0x3bf0 }, // Return from 233rd Age + { kStackOspit, 0x470a, kStackJspit, 0x1508e }, // Return from 233rd Age + { kStackOspit, 0x5c52, kStackGspit, 0x10bea }, // Return from 233rd Age + { kStackOspit, 0x5d68, kStackBspit, 0x1adfd }, // Return from 233rd Age + { kStackOspit, 0x5e49, kStackTspit, 0xe87 }, // Return from 233rd Age + { kStackPspit, 0x4108, kStackOspit, 0x2e76 }, // Dome Linking Book + { kStackRspit, 0x32d8, kStackJspit, 0x1c474 }, // Return from Tay + { kStackTspit, 0x21b69, kStackOspit, 0x2e76 } // Dome Linking Book }; void MohawkEngine_Riven::changeToCard(uint16 dest) { @@ -556,16 +558,16 @@ void MohawkEngine_Riven::checkInventoryClick() { // In the demo, check if we've clicked the exit button if (getFeatures() & GF_DEMO) { if (g_demoExitRect->contains(mousePos)) { - if (_curStack == aspit && _curCard == 1) { + if (_curStack == kStackAspit && _curCard == 1) { // From the main menu, go to the "quit" screen changeToCard(12); - } else if (_curStack == aspit && _curCard == 12) { + } else if (_curStack == kStackAspit && _curCard == 12) { // From the "quit" screen, just quit _gameOver = true; } else { // Otherwise, return to the main menu - if (_curStack != aspit) - changeToStack(aspit); + if (_curStack != kStackAspit) + changeToStack(kStackAspit); changeToCard(1); } } @@ -573,7 +575,7 @@ void MohawkEngine_Riven::checkInventoryClick() { } // No inventory shown on aspit - if (_curStack == aspit) + if (_curStack == kStackAspit) return; // Set the return stack/card id's. @@ -589,31 +591,31 @@ void MohawkEngine_Riven::checkInventoryClick() { if (!hasCathBook) { if (g_atrusJournalRect1->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } } else if (!hasTrapBook) { if (g_atrusJournalRect2->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } else if (g_cathJournalRect2->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } } else { if (g_atrusJournalRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(5); } else if (g_cathJournalRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(6); } else if (g_trapBookRect3->contains(mousePos)) { _gfx->hideInventory(); - changeToStack(aspit); + changeToStack(kStackAspit); changeToCard(7); } } @@ -735,16 +737,20 @@ Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String & Common::String MohawkEngine_Riven::getStackName(uint16 stack) const { static const char *rivenStackNames[] = { - "aspit", - "bspit", - "gspit", - "jspit", + "<unknown>", "ospit", "pspit", "rspit", - "tspit" + "tspit", + "bspit", + "gspit", + "jspit", + "aspit" }; + // Sanity check. + assert(stack < ARRAYSIZE(rivenStackNames)); + return rivenStackNames[stack]; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index c22b9f7f87..9c23d07c52 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -44,18 +44,20 @@ class RivenConsole; class RivenSaveLoad; class RivenOptionsDialog; -#define RIVEN_STACKS 8 - // Riven Stack Types enum { - aspit = 0, // Main Menu, Books, Setup - bspit = 1, // Book-Making Island - gspit = 2, // Garden Island - jspit = 3, // Jungle Island - ospit = 4, // 233rd Age (Gehn's Office) - pspit = 5, // Prison Island - rspit = 6, // Rebel Age (Tay) - tspit = 7 // Temple Island + kStackUnknown = 0, // Default value for ReturnStackID + kStackOspit = 1, // 233rd Age (Gehn's Office) + kStackPspit = 2, // Prison Island + kStackRspit = 3, // Temple Island + kStackTspit = 4, // Rebel Age (Tay) + kStackBspit = 5, // Book-Making Island + kStackGspit = 6, // Garden Island + kStackJspit = 7, // Jungle Island + kStackAspit = 8, // Main Menu, Books, Setup + + kStackFirst = kStackOspit, + kStackLast = kStackAspit }; // NAME Resource ID's diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 10dcfd9fa7..3d0bccc47f 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -405,7 +405,7 @@ void RivenExternal::drawDomeSliders(uint16 startHotspot) { // On pspit, the rect is different by two pixels // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this) - if (_vm->getCurStack() == pspit) + if (_vm->getCurStack() == kStackPspit) dstAreaRect.translate(-2, 0); // Find out bitmap id @@ -2016,8 +2016,8 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) { // WORKAROUND: The special change stuff only handles one destination and it would // be messy to modify the way that currently works. If we use the trap book on Tay, // we should be using the Tay end game sequences. - if (_vm->_vars["returnstackid"] == rspit) { - _vm->changeToStack(rspit); + if (_vm->_vars["returnstackid"] == kStackRspit) { + _vm->changeToStack(kStackRspit); _vm->changeToCard(2); return; } diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp index 615b2fdadb..b44fbb828e 100644 --- a/engines/mohawk/riven_graphics.cpp +++ b/engines/mohawk/riven_graphics.cpp @@ -289,7 +289,7 @@ void RivenGraphics::showInventory() { drawInventoryImage(101, g_demoExitRect); } else { // We don't want to show the inventory on setup screens or in other journals. - if (_vm->getCurStack() == aspit) + if (_vm->getCurStack() == kStackAspit) return; // There are three books and three vars. We have three different diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp index d97d0e174b..6af66f7a2d 100644 --- a/engines/mohawk/riven_saveload.cpp +++ b/engines/mohawk/riven_saveload.cpp @@ -38,56 +38,6 @@ Common::StringArray RivenSaveLoad::generateSaveGameList() { return _saveFileMan->listSavefiles("*.rvn"); } -// Note: The stack numbers we use do not match up to what the original executable, -// so, match them ;) -static uint16 mapOldStackIDToNew(uint16 oldID) { - switch (oldID) { - case 1: - return ospit; - case 2: - return pspit; - case 3: - return rspit; - case 4: - return tspit; - case 5: - return bspit; - case 6: - return gspit; - case 7: - return jspit; - case 8: - return aspit; - } - - error("Unknown old stack ID %d", oldID); - return 0; -} - -static uint16 mapNewStackIDToOld(uint16 newID) { - switch (newID) { - case aspit: - return 8; - case bspit: - return 5; - case gspit: - return 6; - case jspit: - return 7; - case ospit: - return 1; - case pspit: - return 2; - case rspit: - return 3; - case tspit: - return 4; - } - - error("Unknown new stack ID %d", newID); - return 0; -} - Common::Error RivenSaveLoad::loadGame(Common::String filename) { if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo return Common::kNoError; @@ -141,9 +91,6 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) { names->readUint16BE(); // Skip unknown values uint32 curNamesPos = names->pos(); - uint16 stackID = 0; - uint16 cardID = 0; - for (uint32 i = 0; i < namesCount && !names->eos(); i++) { names->seek(curNamesPos); names->seek(stringOffsets[i], SEEK_CUR); @@ -165,25 +112,18 @@ Common::Error RivenSaveLoad::loadGame(Common::String filename) { uint32 &var = _vm->_vars[name]; name.toLowercase(); - // Handle any special variables here // WORKAROUND: time variables are reset here for one main reason: // The save does not store any start point for the time, so we don't know the real time. // Because of this, in many cases, the original would just give a 'free' Ytram upon saving // since the time would be used in a new (improper) time frame. - if (name.equalsIgnoreCase("CurrentStackID")) // Remap to our definitions, store for later - stackID = mapOldStackIDToNew(rawVariables[i]); - else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later - cardID = rawVariables[i]; - else if (name.equalsIgnoreCase("ReturnStackID") && var != 0) // if 0, the game did not use the variable yet - var = mapOldStackIDToNew(rawVariables[i]); - else if (name.contains("time")) // WORKAROUND: See above + if (name.contains("time")) var = 0; - else // Otherwise, just store it + else var = rawVariables[i]; } - _vm->changeToStack(stackID); - _vm->changeToCard(cardID); + _vm->changeToStack(_vm->_vars["CurrentStackID"]); + _vm->changeToCard(_vm->_vars["CurrentCardID"]); delete names; delete[] stringOffsets; @@ -224,14 +164,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() { for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) { stream->writeUint32BE(0); // Unknown stream->writeUint32BE(0); // Unknown - - // Remap returnstackid here because we don't actually want to change - // our internal returnstackid. - uint32 variable = it->_value; - if (it->_key == "returnstackid") - variable = mapNewStackIDToOld(variable); - - stream->writeUint32BE(variable); + stream->writeUint32BE(it->_value); } return stream; @@ -290,7 +223,7 @@ Common::Error RivenSaveLoad::saveGame(Common::String filename) { filename += ".rvn"; // Convert class variables to variable numbers - _vm->_vars["currentstackid"] = mapNewStackIDToOld(_vm->getCurStack()); + _vm->_vars["currentstackid"] = _vm->getCurStack(); _vm->_vars["currentcardid"] = _vm->getCurCard(); Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index 06b6afdf30..29ee5cd50b 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -403,7 +403,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) { // would cause all ambient sounds not to play. An alternative // fix would be to stop all scripts on a stack change, but this // does fine for now. - if (_vm->getCurStack() == tspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb)) + if (_vm->getCurStack() == kStackTspit && (_vm->getCurCardRMAP() == 0x6e9a || _vm->getCurCardRMAP() == 0xfeeb)) return; // The argument is a bitflag for the setting. @@ -586,7 +586,7 @@ void RivenScript::activatePLST(uint16 op, uint16 argc, uint16 *argv) { void RivenScript::activateSLST(uint16 op, uint16 argc, uint16 *argv) { // WORKAROUND: Disable the SLST that is played during Riven's intro. // Riven X does this too (spoke this over with Jeff) - if (_vm->getCurStack() == tspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2) + if (_vm->getCurStack() == kStackTspit && _vm->getCurCardRMAP() == 0x6e9a && argv[0] == 2) return; _vm->_sound->playSLST(argv[0], _vm->getCurCard()); diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index 1cd748d8d6..f09aba7f90 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -31,240 +31,240 @@ namespace Mohawk { static const char *variableNames[] = { // aspit - "aatrusbook", - "aatruspage", - "acathbook", - "acathpage", - "acathstate", - "adoit", - "adomecombo", - "agehn", - "ainventory", - "aova", - "apower", - "araw", - "atemp", - "atrap", - "atrapbook", - "auservolume", - "azip", + "aAtrusBook", + "aAtrusPage", + "aCathBook", + "aCathPage", + "aCathState", + "aDoIt", + "aDomeCombo", + "aGehn", + "aInventory", + "aOva", + "aPower", + "aRaw", + "aTemp", + "aTrap", + "aTrapBook", + "aUserVolume", + "aZip", // bspit - "bbacklock", - "bbait", - "bbigbridge", - "bbirds", - "bblrarm", - "bblrdoor", - "bblrgrt", - "bblrsw", - "bblrvalve", - "bblrwtr", - "bbook", - "bbrlever", - "bcavedoor", + "bBackLock", + "bBait", + "bBigBridge", + "bBirds", + "bBlrArm", + "bBlrDoor", + "bBlrGrt", + "bBlrSw", + "bBlrValve", + "bBlrWtr", + "bBook", + "bBrLever", + "bCaveDoor", "bcombo", - "bcpipegr", - "bcratergg", - "bdome", - "bdrwr", - "bfans", - "bfmdoor", - "bidvlv", - "blab", - "blabbackdr", - "blabbook", - "blabeye", - "blabfrontdr", - "blabpage", - "blever", - "bfrontlock", - "bheat", - "bmagcar", - "bpipdr", - "bprs", - "bstove", - "btrap", - "bvalve", - "bvise", - "bytram", - "bytramtime", - "bytrap", - "bytrapped", + "bCPipeGr", + "bCraterGg", + "bDome", + "bDrwr", + "bFans", + "bFMDoor", + "bIdVlv", + "bLab", + "bLabBackDr", + "bLabBook", + "bLabEye", + "bLabFrontDr", + "bLabPage", + "bLever", + "bFrontLock", + "bHeat", + "bMagCar", + "bPipDr", + "bPrs", + "bStove", + "bTrap", + "bValve", + "bVise", + "bYtram", + "bYtramTime", + "bYtrap", + "bYtrapped", // gspit - "gbook", - "gcathtime", - "gcathstate", - "gcombo", - "gdome", - "gemagcar", - "gimagecurr", + "gBook", + "gCathTime", + "gCathState", + "gCombo", + "gDome", + "gEmagCar", + "gImageCurr", "gimagemax", - "gimagerot", - "glkbtns", - "glkbridge", - "glkelev", - "glview", - "glviewmpos", - "glviewpos", - "gnmagrot", - "gnmagcar", - "gpinup", - "gpinpos", - "gpinsmpos", - "grview", - "grviewmpos", - "grviewpos", - "gscribe", - "gscribetime", - "gsubelev", - "gsubdr", - "gupmoov", - "gwhark", - "gwharktime", + "gImageRot", + "gLkBtns", + "gLkBridge", + "gLkElev", + "gLView", + "gLViewMPos", + "gLViewPos", + "gNmagRot", + "gNmagCar", + "gPinUp", + "gPinPos", + "gPinsMPos", + "gRView", + "gRViewMPos", + "gRViewPos", + "gScribe", + "gScribeTime", + "gSubElev", + "gSubDr", + "gUpMoov", + "gWhark", + "gWharkTime", // jspit - "jwmagcar", - "jbeetle", - "jbeetlepool", - "jbook", - "jbridge1", - "jbridge2", - "jbridge3", - "jbridge4", - "jbridge5", - "jccb", - "jcombo", - "jcrg", - "jdome", - "jdrain", - "jgallows", - "jgate", - "jgirl", - "jiconcorrectorder", - "jiconorder", - "jicons", - "jladder", - "jleftpos", - "jpeek", - "jplaybeetle", - "jprebel", - "jprisondr", - "jprisonsecdr", - "jrbook", - "jrightpos", - "jsouthpathdr", - "jschooldr", - "jsub", - "jsubdir", - "jsubhatch", - "jsubsw", - "jsunners", - "jsunnertime", - "jthronedr", - "jtunneldr", - "jtunnellamps", - "jvillagepeople", - "jwarning", - "jwharkpos", - "jwharkram", - "jwmouth", - "jwmagcar", - "jymagcar", + "jWMagCar", + "jBeetle", + "jBeetlePool", + "jBook", + "jBridge1", + "jBridge2", + "jBridge3", + "jBridge4", + "jBridge5", + "jCCB", + "jCombo", + "jCrg", + "jDome", + "jDrain", + "jGallows", + "jGate", + "jGirl", + "jIconCorrectOrder", + "jIconOrder", + "jIcons", + "jLadder", + "jLeftPos", + "jPeek", + "jPlayBeetle", + "jPRebel", + "jPrisonDr", + "jPrisonSecDr", + "jrBook", + "jRightPos", + "jSouthPathDr", + "jSchoolDr", + "jSub", + "jSubDir", + "jSubHatch", + "jSubSw", + "jSunners", + "jSunnerTime", + "jThroneDr", + "jTunnelDr", + "jTunnelLamps", + "jVillagePeople", + "jWarning", + "jWharkPos", + "jWharkRam", + "jWMouth", + "jWMagCar", + "jYMagCar", // ospit "oambient", - "obutton", + "oButton", "ocage", - "odeskbook", - "ogehnpage", - "omusicplayer", - "ostanddrawer", - "ostove", + "oDeskBook", + "oGehnPage", + "oMusicPlayer", + "oStandDrawer", + "oStove", // pspit - "pbook", - "pcage", - "pcathcheck", - "pcathstate", - "pcathtime", - "pcombo", - "pcorrectorder", + "pBook", + "pCage", + "pCathCheck", + "pCathState", + "pCathTime", + "pCombo", + "pCorrectOrder", "pdome", - "pelevcombo", - "pleftpos", - "prightpos", - "ptemp", - "pwharkpos", + "pElevCombo", + "pLeftPos", + "pRightPos", + "pTemp", + "pWharkPos", // rspit - "rrebel", - "rrebelview", - "rrichard", - "rvillagetime", + "rRebel", + "rRebelView", + "rRichard", + "rVillageTime", // tspit - "tbars", - "tbeetle", - "tblue", - "tbook", - "tbookvalve", - "tcage", - "tcombo", - "tcorrectorder", - "tcovercombo", - "tdl", - "tdome", - "tdomeelev", - "tdomeelevbtn", - "tgatebrhandle", - "tgatebridge", - "tgatestate", - "tgreen", - "tgridoor", - "tgrodoor", - "tgrmdoor", - "tguard", - "timagedoor", - "tmagcar", - "torange", - "tred", - "tsecdoor", - "tsubbridge", - "ttelecover", - "ttelehandle", - "ttelepin", - "ttelescope", - "ttelevalve", - "ttemple", - "ttempledoor", - "ttunneldoor", - "tviewer", - "tviolet", - "twabrvalve", - "twaffle", - "tyellow", + "tBars", + "tBeetle", + "tBlue", + "tBook", + "tBookValve", + "tCage", + "tCombo", + "tCorrectOrder", + "tCoverCombo", + "tDL", + "tDome", + "tDomeElev", + "tDomeElevBtn", + "tGateBrHandle", + "tGateBridge", + "tGateState", + "tGreen", + "tGRIDoor", + "tGRODoor", + "tGRMDoor", + "tGuard", + "tImageDoor", + "tMagCar", + "tOrange", + "tRed", + "tSecDoor", + "tSubBridge", + "tTeleCover", + "tTeleHandle", + "tTelePin", + "tTelescope", + "tTeleValve", + "tTemple", + "tTempleDoor", + "tTunnelDoor", + "tViewer", + "tViolet", + "tWaBrValve", + "tWaffle", + "tYellow", // Miscellaneous "elevbtn1", "elevbtn2", "elevbtn3", - "domecheck", - "transitionsenabled", - "transitionmode", - "waterenabled", - "rivenambients", - "stackvarsinitialized", - "doingsetupscreens", + "domeCheck", + "transitionsEnabled", + "transitionMode", + "waterEnabled", + "RivenAmbients", + "stackVarsInitialized", + "DoingSetupScreens", "all_book", - "playerhasbook", - "returnstackid", - "returncardid", - "newpos", - "themarble", - "currentstackid", - "currentcardid" + "playerHasBook", + "returnStackID", + "returnCardID", + "NewPos", + "theMarble", + "CurrentStackID", + "CurrentCardID" }; uint32 &MohawkEngine_Riven::getStackVar(uint32 index) { diff --git a/engines/mortevielle/debugger.cpp b/engines/mortevielle/debugger.cpp index c8f75918ab..b2c99b894a 100644 --- a/engines/mortevielle/debugger.cpp +++ b/engines/mortevielle/debugger.cpp @@ -27,9 +27,9 @@ namespace Mortevielle { Debugger::Debugger(MortevielleEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions)); - DCmd_Register("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions)); + registerCmd("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano)); } bool Debugger::Cmd_showAllQuestions(int argc, const char **argv) { diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp index a4d1366880..91ab3e767a 100644 --- a/engines/neverhood/console.cpp +++ b/engines/neverhood/console.cpp @@ -34,13 +34,13 @@ namespace Neverhood { Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("cheat", WRAP_METHOD(Console, Cmd_Cheat)); - DCmd_Register("checkresource", WRAP_METHOD(Console, Cmd_CheckResource)); - DCmd_Register("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource)); - DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars)); - DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound)); - DCmd_Register("scene", WRAP_METHOD(Console, Cmd_Scene)); - DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces)); + registerCmd("cheat", WRAP_METHOD(Console, Cmd_Cheat)); + registerCmd("checkresource", WRAP_METHOD(Console, Cmd_CheckResource)); + registerCmd("dumpresource", WRAP_METHOD(Console, Cmd_DumpResource)); + registerCmd("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars)); + registerCmd("playsound", WRAP_METHOD(Console, Cmd_PlaySound)); + registerCmd("scene", WRAP_METHOD(Console, Cmd_Scene)); + registerCmd("surfaces", WRAP_METHOD(Console, Cmd_Surfaces)); } Console::~Console() { @@ -55,33 +55,33 @@ bool Console::Cmd_Scene(int argc, const char **argv) { const char *sceneTypes[] = { "normal", "smacker", "navigation" }; - DebugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]); + debugPrintf("Current module: %d, previous module: %d, scene %d (%s scene)\n", currentModule, previousModule, scenenNum, sceneTypes[sceneType]); if (sceneType == kSceneTypeNormal) { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Normal scenes have a background and a cursor file hash - DebugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash()); + debugPrintf("Background hash: 0x%x, cursor hash: 0x%x\n", scene->getBackgroundFileHash(), scene->getCursorFileHash()); } else if (sceneType == kSceneTypeSmacker) { SmackerScene *scene = (SmackerScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Smacker scenes have a file hash, or a list of hashes // TODO: Only the first file hash is shown - any additional hashes, found in // scenes with a list of hashes (two scenes in module 1100 and the making of // video) aren't shown yet - DebugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash()); + debugPrintf("File hash: 0x%x\n", scene->getSmackerFileHash()); } else if (sceneType == kSceneTypeNavigation) { NavigationScene *scene = (NavigationScene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; // Navigation scenes have a navigation list and its index NavigationList *navigationList = _vm->_staticData->getNavigationList(scene->getNavigationListId()); int navigationIndex = scene->getGlobalVar(V_NAVIGATION_INDEX); NavigationItem curNavigation = (*navigationList)[navigationIndex]; - DebugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex); - DebugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n", + debugPrintf("Navigation list ID: 0x%x, index: %d\n", scene->getNavigationListId(), navigationIndex); + debugPrintf("File hash: 0x%x, cursor hash: 0x%x, Smacker hashes: [left: 0x%x, middle: 0x%x, right: 0x%x\n", curNavigation.fileHash, curNavigation.mouseCursorFileHash, curNavigation.leftSmackerFileHash, curNavigation.middleSmackerFileHash, curNavigation.rightSmackerFileHash); } - DebugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]); - DebugPrintf("Modules are incremental by 100, from 1000 to 3000\n"); + debugPrintf("Use %s <module> <scene> to change scenes\n", argv[0]); + debugPrintf("Modules are incremental by 100, from 1000 to 3000\n"); } else { int newModule = atoi(argv[1]); int newScene = atoi(argv[2]); @@ -102,17 +102,17 @@ bool Console::Cmd_Surfaces(int argc, const char **argv) { bool Console::Cmd_Cheat(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Cheats for various puzzles in the game\n"); - DebugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]); - DebugPrintf("Cheats:\n-------\n"); - DebugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n"); - DebugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n"); - DebugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n"); - DebugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n"); - DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n"); - DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n"); - DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n"); - DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n"); + debugPrintf("Cheats for various puzzles in the game\n"); + debugPrintf("Use %s <cheatname> to use a cheat.\n", argv[0]); + debugPrintf("Cheats:\n-------\n"); + debugPrintf(" buttons - enables all 3 buttons on the door in the purple building, module 3000, scene 9\n"); + debugPrintf(" cannon - sets the correct cannon combination in module 3000, scene 8\n"); + debugPrintf(" dice - shows the correct dice combination in the teddy bear puzzle, module 1100, scene 6\n"); + debugPrintf(" memory - solves the memory puzzle, module 1400, scene 4\n"); + debugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n"); + debugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n"); + debugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n"); + debugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n"); return true; } @@ -127,7 +127,7 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { scene->setSubVar(VA_LOCKS_DISABLED, 0x40119852, 1); // kScene3010ButtonNameHashes[1] scene->setSubVar(VA_LOCKS_DISABLED, 0x01180951, 1); // kScene3010ButtonNameHashes[2] - DebugPrintf("All 3 door buttons have been enabled\n"); + debugPrintf("All 3 door buttons have been enabled\n"); } else if (cheatName == "cannon") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; @@ -137,10 +137,10 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { for (int i = 3; i < 6; i++) scene->setSubVar(VA_CURR_CANNON_SYMBOLS, i, scene->getSubVar(VA_GOOD_CANNON_SYMBOLS_2, i - 3)); - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else if (cheatName == "dice") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Good: (%d %d %d), current: (%d %d %d)\n", + debugPrintf("Good: (%d %d %d), current: (%d %d %d)\n", scene->getSubVar(VA_GOOD_DICE_NUMBERS, 0), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 1), scene->getSubVar(VA_GOOD_DICE_NUMBERS, 2), scene->getSubVar(VA_CURR_DICE_NUMBERS, 0), scene->getSubVar(VA_CURR_DICE_NUMBERS, 1), scene->getSubVar(VA_CURR_DICE_NUMBERS, 2) ); @@ -162,15 +162,15 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { } } - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else if (cheatName == "music") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); + debugPrintf("Good music index: %d, current radio music index: %d\n", scene->getGlobalVar(V_CURR_RADIO_MUSIC_INDEX), scene->getGlobalVar(V_GOOD_RADIO_MUSIC_INDEX)); } else if (cheatName == "radio") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; scene->setGlobalVar(V_RADIO_ENABLED, 1); - DebugPrintf("The radio has been enabled\n"); + debugPrintf("The radio has been enabled\n"); } else if (cheatName == "symbols") { if (moduleNum == 1600 && sceneNum == 8) { Scene1609 *scene = ((Scene1609 *)((Module1600 *)_vm->_gameModule->_childObject)->_childObject); @@ -183,14 +183,14 @@ bool Console::Cmd_Cheat(int argc, const char **argv) { scene->_symbolPosition = 11; scene->_countdown1 = 36; - DebugPrintf("Puzzle solved\n"); + debugPrintf("Puzzle solved\n"); } else { - DebugPrintf("Only available in module 1600, scene 8\n"); + debugPrintf("Only available in module 1600, scene 8\n"); } } else if (cheatName == "tubes") { Scene *scene = (Scene *)((GameModule *)_vm->_gameModule->_childObject)->_childObject; - DebugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); - DebugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); + debugPrintf("Tube set 1: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2)); + debugPrintf("Tube set 2: %d %d %d\n", scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 0), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 1), scene->getSubVar(VA_GOOD_TEST_TUBES_LEVEL_2, 2)); } return true; @@ -204,7 +204,7 @@ bool Console::Cmd_Dumpvars(int argc, const char **argv) { bool Console::Cmd_PlaySound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <sound hash>\n", argv[0]); + debugPrintf("Usage: %s <sound hash>\n", argv[0]); } else { uint32 soundHash = strtol(argv[1], NULL, 0); AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash); @@ -223,17 +223,17 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) { const char *resourceNames[] = { "unknown", "unknown", "bitmap", "palette", "animation", "data", "text", "sound", "music", "unknown", "video" }; if (argc < 2) { - DebugPrintf("Gets information about a resource\n"); - DebugPrintf("Usage: %s <resource hash>\n", argv[0]); + debugPrintf("Gets information about a resource\n"); + debugPrintf("Usage: %s <resource hash>\n", argv[0]); } else { uint32 resourceHash = strtol(argv[1], NULL, 0); ResourceHandle handle; _vm->_res->queryResource(resourceHash, handle); if (!handle.isValid()) { - DebugPrintf("Invalid resource hash\n"); + debugPrintf("Invalid resource hash\n"); } else { - DebugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size()); + debugPrintf("Resource type: %d (%s). Size: %d bytes\n", handle.type(), resourceNames[handle.type()], handle.size()); } } @@ -242,8 +242,8 @@ bool Console::Cmd_CheckResource(int argc, const char **argv) { bool Console::Cmd_DumpResource(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Dumps a resource to disk\n"); - DebugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]); + debugPrintf("Dumps a resource to disk\n"); + debugPrintf("Usage: %s <resource hash> <output file>\n", argv[0]); } else { uint32 resourceHash = strtol(argv[1], NULL, 0); const char *outFileName = argv[2]; @@ -251,7 +251,7 @@ bool Console::Cmd_DumpResource(int argc, const char **argv) { _vm->_res->queryResource(resourceHash, handle); if (!handle.isValid()) { - DebugPrintf("Invalid resource hash\n"); + debugPrintf("Invalid resource hash\n"); } else { _vm->_res->loadResource(handle, _vm->applyResourceFixes()); Common::DumpFile outFile; diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp index 72b688c194..dcbe5583de 100644 --- a/engines/neverhood/gamevars.cpp +++ b/engines/neverhood/gamevars.cpp @@ -127,7 +127,7 @@ int16 GameVars::getSubVarIndex(int16 varIndex, uint32 subNameHash) { void GameVars::dumpVars(Console *con) { for (Common::Array<GameVar>::iterator it = _vars.begin(); it != _vars.end(); ++it) { GameVar gameVar = *it; - con->DebugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); + con->debugPrintf("hash: %08X, var: %08X, first index: %3d, next index: %3d\n", gameVar.nameHash, gameVar.value, gameVar.firstIndex, gameVar.nextIndex); } } diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp index 3d1724ed8a..939428ed19 100644 --- a/engines/neverhood/graphics.cpp +++ b/engines/neverhood/graphics.cpp @@ -47,6 +47,7 @@ BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 h } BaseSurface::~BaseSurface() { + _surface->free(); delete _surface; } diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp index b19ba05b32..5e4d67d2bc 100644 --- a/engines/neverhood/modules/module1000.cpp +++ b/engines/neverhood/modules/module1000.cpp @@ -693,22 +693,18 @@ uint32 Scene1005::getTextIndex1() { uint32 Scene1005::getKloggsTextIndex() { uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX1); if (textIndex + 1 > 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX1, 0); textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); } + setGlobalVar(V_TEXT_COUNTING_INDEX1, textIndex + 1); return textIndex + 40; } uint32 Scene1005::getTextIndex3() { uint32 textIndex = getGlobalVar(V_TEXT_COUNTING_INDEX2); - if (textIndex + 1 >= 10) { - setGlobalVar(V_TEXT_COUNTING_INDEX2, 0); + if (textIndex + 1 > 10) { textIndex = 0; - } else { - setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); } + setGlobalVar(V_TEXT_COUNTING_INDEX2, textIndex + 1); return textIndex + 30; } diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp index 58056b65a9..1a8e74da38 100644 --- a/engines/neverhood/scene.cpp +++ b/engines/neverhood/scene.cpp @@ -148,7 +148,7 @@ void Scene::printSurfaces(Console *con) { NDrawRect drawRect = _surfaces[index]->getDrawRect(); NRect clipRect = _surfaces[index]->getClipRect(); int priority = _surfaces[index]->getPriority(); - con->DebugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n", + con->debugPrintf("%d ('%s'): Priority %d, draw rect (%d, %d, %d, %d), clip rect (%d, %d, %d, %d)\n", index, _surfaces[index]->getName().c_str(), priority, drawRect.x, drawRect.y, drawRect.x2(), drawRect.y2(), clipRect.x1, clipRect.y1, clipRect.x2, clipRect.y2); diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp index 552ea92604..03af44b2a5 100644 --- a/engines/neverhood/staticdata.cpp +++ b/engines/neverhood/staticdata.cpp @@ -28,6 +28,18 @@ StaticData::StaticData() { } StaticData::~StaticData() { + for (Common::HashMap<uint32, HitRectList*>::iterator i = _hitRectLists.begin(); i != _hitRectLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, RectList*>::iterator i = _rectLists.begin(); i != _rectLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, MessageList*>::iterator i = _messageLists.begin(); i != _messageLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, NavigationList*>::iterator i = _navigationLists.begin(); i != _navigationLists.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, HallOfRecordsInfo*>::iterator i = _hallOfRecordsInfoItems.begin(); i != _hallOfRecordsInfoItems.end(); ++i) + delete i->_value; + for (Common::HashMap<uint32, TrackInfo*>::iterator i = _trackInfoItems.begin(); i != _trackInfoItems.end(); ++i) + delete i->_value; } void StaticData::load(const char *filename) { @@ -69,6 +81,11 @@ void StaticData::load(const char *filename) { messageList->push_back(messageItem); } + if(_messageLists.contains(id)) { + warning("Duplicate id %d in _messageLists - freeing older entry", id); + delete _messageLists[id]; + } + _messageLists[id] = messageList; } @@ -98,6 +115,12 @@ void StaticData::load(const char *filename) { } rectList->push_back(rectItem); } + + if(_rectLists.contains(id)) { + warning("Duplicate id %d in _rectLists - freeing older entry", id); + delete _rectLists[id]; + } + _rectLists[id] = rectList; } @@ -117,6 +140,12 @@ void StaticData::load(const char *filename) { hitRect.type = fd.readUint16LE(); hitRectList->push_back(hitRect); } + + if(_hitRectLists.contains(id)) { + warning("Duplicate id %d in _hitRectLists - freeing older entry", id); + delete _hitRectLists[id]; + } + _hitRectLists[id] = hitRectList; } @@ -138,6 +167,12 @@ void StaticData::load(const char *filename) { navigationItem.mouseCursorFileHash = fd.readUint32LE(); navigationList->push_back(navigationItem); } + + if(_navigationLists.contains(id)) { + warning("Duplicate id %d in _navigationLists - freeing older entry", id); + delete _navigationLists[id]; + } + _navigationLists[id] = navigationList; } @@ -153,6 +188,12 @@ void StaticData::load(const char *filename) { hallOfRecordsInfo->bgFilename3 = fd.readUint32LE(); hallOfRecordsInfo->xPosIndex = fd.readByte(); hallOfRecordsInfo->count = fd.readByte(); + + if(_hallOfRecordsInfoItems.contains(id)) { + warning("Duplicate id %d in _hallOfRecordsInfoItems - freeing older entry", id); + delete _hallOfRecordsInfoItems[id]; + } + _hallOfRecordsInfoItems[id] = hallOfRecordsInfo; } @@ -172,6 +213,12 @@ void StaticData::load(const char *filename) { trackInfo->mouseCursorFilename = fd.readUint32LE(); trackInfo->which1 = fd.readUint16LE(); trackInfo->which2 = fd.readUint16LE(); + + if(_trackInfoItems.contains(id)) { + warning("Duplicate id %d in _trackInfoItems - freeing older entry", id); + delete _trackInfoItems[id]; + } + _trackInfoItems[id] = trackInfo; } diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp index 1fea73a326..a7087c64d7 100644 --- a/engines/parallaction/debug.cpp +++ b/engines/parallaction/debug.cpp @@ -33,18 +33,18 @@ Debugger::Debugger(Parallaction *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("location", WRAP_METHOD(Debugger, Cmd_Location)); - DCmd_Register("give", WRAP_METHOD(Debugger, Cmd_Give)); - DCmd_Register("zones", WRAP_METHOD(Debugger, Cmd_Zones)); - DCmd_Register("animations", WRAP_METHOD(Debugger, Cmd_Animations)); - DCmd_Register("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags)); - DCmd_Register("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag)); - DCmd_Register("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags)); - DCmd_Register("locations", WRAP_METHOD(Debugger, Cmd_Locations)); - DCmd_Register("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects)); - DCmd_Register("programs", WRAP_METHOD(Debugger, Cmd_Programs)); - DCmd_Register("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("location", WRAP_METHOD(Debugger, Cmd_Location)); + registerCmd("give", WRAP_METHOD(Debugger, Cmd_Give)); + registerCmd("zones", WRAP_METHOD(Debugger, Cmd_Zones)); + registerCmd("animations", WRAP_METHOD(Debugger, Cmd_Animations)); + registerCmd("globalflags",WRAP_METHOD(Debugger, Cmd_GlobalFlags)); + registerCmd("toggleglobalflag",WRAP_METHOD(Debugger, Cmd_ToggleGlobalFlag)); + registerCmd("localflags", WRAP_METHOD(Debugger, Cmd_LocalFlags)); + registerCmd("locations", WRAP_METHOD(Debugger, Cmd_Locations)); + registerCmd("gfxobjects", WRAP_METHOD(Debugger, Cmd_GfxObjects)); + registerCmd("programs", WRAP_METHOD(Debugger, Cmd_Programs)); + registerCmd("showmouse", WRAP_METHOD(Debugger, Cmd_ShowMouse)); } @@ -81,7 +81,7 @@ bool Debugger::Cmd_Location(int argc, const char **argv) { break; case 1: - DebugPrintf("location <location name> [character name]\n"); + debugPrintf("location <location name> [character name]\n"); } @@ -90,13 +90,13 @@ bool Debugger::Cmd_Location(int argc, const char **argv) { bool Debugger::Cmd_Locations(int argc, const char **argv) { - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| location name | flags |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_numLocations; i++) { - DebugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]); + debugPrintf("|%-30s| %08x|\n", _vm->_locationNames[i], _vm->_localFlags[i]); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -105,14 +105,14 @@ bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) { uint32 flags = g_globalFlags; - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| flag name | value |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_globalFlagsNames->count(); i++) { const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON"; - DebugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value); + debugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -125,7 +125,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) { case 2: i = _vm->_globalFlagsNames->lookup(argv[1]); if (i == Table::notFound) { - DebugPrintf("invalid flag '%s'\n", argv[1]); + debugPrintf("invalid flag '%s'\n", argv[1]); } else { i--; if ((g_globalFlags & (1 << i)) == 0) @@ -136,7 +136,7 @@ bool Debugger::Cmd_ToggleGlobalFlag(int argc, const char **argv) { break; default: - DebugPrintf("toggleglobalflag <flag name>\n"); + debugPrintf("toggleglobalflag <flag name>\n"); } @@ -147,14 +147,14 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) { uint32 flags = _vm->getLocationFlags(); - DebugPrintf("+------------------------------+---------+\n" + debugPrintf("+------------------------------+---------+\n" "| flag name | value |\n" "+------------------------------+---------+\n"); for (uint i = 0; i < _vm->_localFlagNames->count(); i++) { const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON"; - DebugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value); + debugPrintf("|%-30s| %-6s|\n", _vm->_localFlagNames->item(i), value); } - DebugPrintf("+------------------------------+---------+\n"); + debugPrintf("+------------------------------+---------+\n"); return true; } @@ -162,13 +162,13 @@ bool Debugger::Cmd_LocalFlags(int argc, const char **argv) { bool Debugger::Cmd_Give(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("give <item name>\n"); + debugPrintf("give <item name>\n"); } else { int index = _vm->_objectsNames->lookup(argv[1]); if (index != Table::notFound) _vm->addInventoryItem(index + 4); else - DebugPrintf("invalid item name '%s'\n", argv[1]); + debugPrintf("invalid item name '%s'\n", argv[1]); } return true; @@ -181,15 +181,15 @@ bool Debugger::Cmd_Zones(int argc, const char **argv) { ZoneList::iterator e = _vm->_location._zones.end(); Common::Rect r; - DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n" + debugPrintf("+--------------------+---+---+---+---+--------+--------+\n" "| name | l | t | r | b | type | flag |\n" "+--------------------+---+---+---+---+--------+--------+\n"); for ( ; b != e; ++b) { ZonePtr z = *b; z->getRect(r); - DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags ); + debugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, r.left, r.top, r.right, r.bottom, z->_type, z->_flags ); } - DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n"); + debugPrintf("+--------------------+---+---+---+---+--------+--------+\n"); return true; @@ -260,15 +260,15 @@ bool Debugger::Cmd_Animations(int argc, const char **argv) { AnimationList::iterator e = _vm->_location._animations.end(); Common::String flags; - DebugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n" + debugPrintf("+--------------------+----+----+----+---+--------+----------------------------------------+\n" "| name | x | y | z | f | type | flags | \n" "+--------------------+----+----+----+---+--------+----------------------------------------+\n"); for ( ; b != e; ++b) { AnimationPtr a = *b; flags = decodeZoneFlags(a->_flags); - DebugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() ); + debugPrintf("|%-20s|%4i|%4i|%4i|%3i|%8x|%-40s|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, flags.c_str() ); } - DebugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n"); + debugPrintf("+--------------------+---+---+---+---+--------+----------------------------------------+\n"); return true; @@ -278,7 +278,7 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { const char *objType[] = { "DOOR", "GET", "ANIM" }; - DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n" + debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n" "| name | x | y | w | h | z | layer | f | type |\n" "+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); @@ -289,11 +289,11 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) { for ( ; b != e; ++b) { GfxObj *obj = *b; obj->getRect(obj->frame, r); - DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(), + debugPrintf("|%-20s|%5i|%5i|%5i|%5i|%5i|%7i|%5i|%8s|\n", obj->getName(), r.left, r.top, r.width(), r.height(), obj->z, obj->layer, obj->frame, objType[obj->type]); } - DebugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); + debugPrintf("+--------------------+-----+-----+-----+-----+-----+-------+-----+--------+\n"); return true; } @@ -307,14 +307,14 @@ bool Debugger::Cmd_Programs(int argc, const char** argv) { int i = 1; - DebugPrintf("+---+--------------------+--------+----------+\n" + debugPrintf("+---+--------------------+--------+----------+\n" "| # | bound animation | size | status |\n" "+---+--------------------+--------+----------+\n"); for ( ; b != e; b++, i++) { ProgramPtr p = *b; - DebugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] ); + debugPrintf("|%3i|%-20s|%8i|%-10s|\n", i, p->_anim->_name, p->_instructions.size(), status[p->_status] ); } - DebugPrintf("+---+--------------------+--------+----------+\n"); + debugPrintf("+---+--------------------+--------+----------+\n"); return true; } diff --git a/engines/parallaction/debug.h b/engines/parallaction/debug.h index 887d08e945..551d746edf 100644 --- a/engines/parallaction/debug.h +++ b/engines/parallaction/debug.h @@ -22,7 +22,6 @@ private: Parallaction *_vm; MouseTriState _mouseState; - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_Location(int argc, const char **argv); bool Cmd_Give(int argc, const char **argv); bool Cmd_Zones(int argc, const char **argv); diff --git a/engines/pegasus/console.cpp b/engines/pegasus/console.cpp index 64bd0ba5f2..e5a0cfec98 100644 --- a/engines/pegasus/console.cpp +++ b/engines/pegasus/console.cpp @@ -28,11 +28,11 @@ namespace Pegasus { PegasusConsole::PegasusConsole(PegasusEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); + registerCmd("die", WRAP_METHOD(PegasusConsole, Cmd_Die)); // These functions are non-demo specific if (!_vm->isDemo()) - DCmd_Register("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); + registerCmd("jump", WRAP_METHOD(PegasusConsole, Cmd_Jump)); } PegasusConsole::~PegasusConsole() { @@ -40,7 +40,7 @@ PegasusConsole::~PegasusConsole() { bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (argc == 1) { - DebugPrintf("Usage: die <death reason>\n"); + debugPrintf("Usage: die <death reason>\n"); return true; } @@ -54,7 +54,7 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { if (invalidReason) { - DebugPrintf("Invalid death reason %d\n", reason); + debugPrintf("Invalid death reason %d\n", reason); return true; } @@ -65,14 +65,14 @@ bool PegasusConsole::Cmd_Die(int argc, const char **argv) { bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if (!g_interface) { // TODO - DebugPrintf("Cannot jump without interface set up\n"); + debugPrintf("Cannot jump without interface set up\n"); return true; } // TODO: Default room/direction for each neighborhood if (argc < 4) { - DebugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); + debugPrintf("Usage: jump <neighborhood> <room> <direction>\n"); return true; } @@ -82,14 +82,14 @@ bool PegasusConsole::Cmd_Jump(int argc, const char **argv) { if ((neighborhood < kCaldoriaID || neighborhood > kNoradDeltaID || neighborhood == kFinalTSAID) && neighborhood != kNoradSubChaseID) { - DebugPrintf("Invalid neighborhood %d", neighborhood); + debugPrintf("Invalid neighborhood %d", neighborhood); return true; } // No real way to check room validity at this point if (direction > kWest) { - DebugPrintf("Invalid direction %d", direction); + debugPrintf("Invalid direction %d", direction); return true; } diff --git a/engines/queen/debug.cpp b/engines/queen/debug.cpp index 3706806ac2..125ddf30c6 100644 --- a/engines/queen/debug.cpp +++ b/engines/queen/debug.cpp @@ -36,15 +36,15 @@ namespace Queen { Debugger::Debugger(QueenEngine *vm) : _vm(vm), _flags(0) { - DCmd_Register("areas", WRAP_METHOD(Debugger, Cmd_Areas)); - DCmd_Register("asm", WRAP_METHOD(Debugger, Cmd_Asm)); - DCmd_Register("bob", WRAP_METHOD(Debugger, Cmd_Bob)); - DCmd_Register("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs)); - DCmd_Register("gs", WRAP_METHOD(Debugger, Cmd_GameState)); - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("items", WRAP_METHOD(Debugger, Cmd_Items)); - DCmd_Register("room", WRAP_METHOD(Debugger, Cmd_Room)); - DCmd_Register("song", WRAP_METHOD(Debugger, Cmd_Song)); + registerCmd("areas", WRAP_METHOD(Debugger, Cmd_Areas)); + registerCmd("asm", WRAP_METHOD(Debugger, Cmd_Asm)); + registerCmd("bob", WRAP_METHOD(Debugger, Cmd_Bob)); + registerCmd("bobs", WRAP_METHOD(Debugger, Cmd_PrintBobs)); + registerCmd("gs", WRAP_METHOD(Debugger, Cmd_GameState)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("items", WRAP_METHOD(Debugger, Cmd_Items)); + registerCmd("room", WRAP_METHOD(Debugger, Cmd_Room)); + registerCmd("song", WRAP_METHOD(Debugger, Cmd_Song)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -73,14 +73,14 @@ bool Debugger::Cmd_Asm(int argc, const char **argv) { _vm->logic()->executeSpecialMove(sm); return false; } else { - DebugPrintf("Usage: %s smnum\n", argv[0]); + debugPrintf("Usage: %s smnum\n", argv[0]); } return true; } bool Debugger::Cmd_Areas(int argc, const char **argv) { _flags ^= DF_DRAW_AREAS; - DebugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off"); + debugPrintf("Room areas display %s\n", (_flags & DF_DRAW_AREAS) != 0 ? "on" : "off"); return true; } @@ -88,36 +88,36 @@ bool Debugger::Cmd_Bob(int argc, const char **argv) { if (argc >= 3 && isNumeric(argv[1])) { int bobNum = atoi(argv[1]); if (bobNum >= Graphics::MAX_BOBS_NUMBER) { - DebugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER); + debugPrintf("Bob %d is out of range (range: 0 - %d)\n", bobNum, Graphics::MAX_BOBS_NUMBER); } else { int param = 0; if (argc > 3 && isNumeric(argv[3])) { param = atoi(argv[3]); } else { - DebugPrintf("Invalid parameter for bob command '%s'\n", argv[2]); + debugPrintf("Invalid parameter for bob command '%s'\n", argv[2]); } BobSlot *bob = _vm->graphics()->bob(bobNum); if (!strcmp(argv[2], "toggle")) { bob->active = !bob->active; - DebugPrintf("bob[%d].active = %d\n", bobNum, bob->active); + debugPrintf("bob[%d].active = %d\n", bobNum, bob->active); } else if (!strcmp(argv[2], "x")) { bob->x = param; - DebugPrintf("bob[%d].x = %d\n", bobNum, bob->x); + debugPrintf("bob[%d].x = %d\n", bobNum, bob->x); } else if (!strcmp(argv[2], "y")) { bob->y = param; - DebugPrintf("bob[%d].y = %d\n", bobNum, bob->y); + debugPrintf("bob[%d].y = %d\n", bobNum, bob->y); } else if (!strcmp(argv[2], "frame")) { bob->frameNum = param; - DebugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum); + debugPrintf("bob[%d].frameNum = %d\n", bobNum, bob->frameNum); } else if (!strcmp(argv[2], "speed")) { bob->speed = param; - DebugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed); + debugPrintf("bob[%d].speed = %d\n", bobNum, bob->speed); } else { - DebugPrintf("Unknown bob command '%s'\n", argv[2]); + debugPrintf("Unknown bob command '%s'\n", argv[2]); } } } else { - DebugPrintf("Usage: %s bobnum command parameter\n", argv[0]); + debugPrintf("Usage: %s bobnum command parameter\n", argv[0]); } return true; } @@ -126,26 +126,26 @@ bool Debugger::Cmd_GameState(int argc, const char **argv) { uint16 slot; if ((argc == 2 || argc == 3) && isNumeric(argv[1])) { slot = atoi(argv[1]); - DebugPrintf("GAMESTATE[%d] ", slot); - DebugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot)); + debugPrintf("GAMESTATE[%d] ", slot); + debugPrintf("%s %d\n", (argc == 2) ? "is" : "was", _vm->logic()->gameState(slot)); if (argc == 3) { if (isNumeric(argv[1])) { _vm->logic()->gameState(slot, atoi(argv[2])); - DebugPrintf("now %d\n", _vm->logic()->gameState(slot)); + debugPrintf("now %d\n", _vm->logic()->gameState(slot)); } else { - DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); + debugPrintf("Usage: %s slotnum <value>\n", argv[0]); } } } else { - DebugPrintf("Usage: %s slotnum <value>\n", argv[0]); + debugPrintf("Usage: %s slotnum <value>\n", argv[0]); } return true; } bool Debugger::Cmd_Info(int argc, const char **argv) { - DebugPrintf("Version: %s\n", _vm->resource()->getJASVersion()); - DebugPrintf("Audio compression: %d\n", _vm->resource()->getCompression()); + debugPrintf("Version: %s\n", _vm->resource()->getJASVersion()); + debugPrintf("Audio compression: %d\n", _vm->resource()->getCompression()); return true; } @@ -156,24 +156,24 @@ bool Debugger::Cmd_Items(int argc, const char **argv) { item->name = ABS(item->name); ++item; } - DebugPrintf("Enabled all inventory items\n"); + debugPrintf("Enabled all inventory items\n"); return true; } bool Debugger::Cmd_PrintBobs(int argc, const char**argv) { int i; BobSlot *bob = _vm->graphics()->bob(0); - DebugPrintf("+------------------------------------+\n"); - DebugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n"); - DebugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n"); + debugPrintf("+------------------------------------+\n"); + debugPrintf("|# | x| y|f|scl|frm|a|m|spd| ex| ey|\n"); + debugPrintf("+--+---+---+-+---+---+-+-+---+---+---+\n"); for (i = 0; i < Graphics::MAX_BOBS_NUMBER; ++i, ++bob) { if (bob->active) { - DebugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n", + debugPrintf("|%2d|%3d|%3d|%1d|%3d|%3d|%1d|%1d|%3d|%3d|%3d|\n", i, bob->x, bob->y, bob->xflip, bob->scale, bob->frameNum, bob->animating, bob->moving, bob->speed, bob->endx, bob->endy); } } - DebugPrintf("+--------------------------------+\n"); + debugPrintf("+--------------------------------+\n"); return true; } @@ -185,7 +185,7 @@ bool Debugger::Cmd_Room(int argc, const char **argv) { _vm->logic()->entryObj(_vm->logic()->roomData(roomNum) + 1); return false; } else { - DebugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n", + debugPrintf("Current room: %d (%s), use '%s <roomnum>' to switch\n", _vm->logic()->currentRoom(), _vm->logic()->roomName(_vm->logic()->currentRoom()), argv[0]); @@ -197,9 +197,9 @@ bool Debugger::Cmd_Song(int argc, const char **argv) { if (argc == 2 && isNumeric(argv[1])) { int16 songNum = atoi(argv[1]); _vm->sound()->playSong(songNum); - DebugPrintf("Playing song %d\n", songNum); + debugPrintf("Playing song %d\n", songNum); } else { - DebugPrintf("Usage: %s songnum\n", argv[0]); + debugPrintf("Usage: %s songnum\n", argv[0]); } return true; } diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp index a5345261c5..04741da2cd 100644 --- a/engines/saga/actor_walk.cpp +++ b/engines/saga/actor_walk.cpp @@ -1378,7 +1378,7 @@ void Actor::cmdActorWalkTo(int argc, const char **argv) { location.fromScreenPoint(movePoint); if (!validActorId(actorId)) { - _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId); + _vm->_console->debugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId); return; } diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index 9e0bcf52ad..25119c6407 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -914,14 +914,14 @@ void Anim::animInfo() { animCount = getAnimationCount(); - _vm->_console->DebugPrintf("There are %d animations loaded:\n", animCount); + _vm->_console->debugPrintf("There are %d animations loaded:\n", animCount); for (i = 0; i < MAX_ANIMATIONS; i++) { if (_animations[i] == NULL) { continue; } - _vm->_console->DebugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags); + _vm->_console->debugPrintf("%02d: Frames: %u Flags: %u\n", i, _animations[i]->maxFrame, _animations[i]->flags); } } @@ -929,10 +929,10 @@ void Anim::animInfo() { void Anim::cutawayInfo() { uint16 i; - _vm->_console->DebugPrintf("There are %d cutaways loaded:\n", _cutawayList.size()); + _vm->_console->debugPrintf("There are %d cutaways loaded:\n", _cutawayList.size()); for (i = 0; i < _cutawayList.size(); i++) { - _vm->_console->DebugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i, + _vm->_console->debugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i, _cutawayList[i].backgroundResourceId, _cutawayList[i].animResourceId, _cutawayList[i].cycles, _cutawayList[i].frameRate); } diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp index eab615b33f..0b801eef3e 100644 --- a/engines/saga/console.cpp +++ b/engines/saga/console.cpp @@ -35,15 +35,15 @@ namespace Saga { Console::Console(SagaEngine *vm) : GUI::Debugger() { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit)); + registerCmd("continue", WRAP_METHOD(Console, cmdExit)); // Actor commands - DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); + registerCmd("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); // Animation commands - DCmd_Register("anim_info", WRAP_METHOD(Console, cmdAnimInfo)); - DCmd_Register("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo)); - DCmd_Register("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway)); + registerCmd("anim_info", WRAP_METHOD(Console, cmdAnimInfo)); + registerCmd("cutaway_info", WRAP_METHOD(Console, cmdCutawayInfo)); + registerCmd("play_cutaway", WRAP_METHOD(Console, cmdPlayCutaway)); // Game stuff @@ -60,28 +60,28 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() { #endif // Scene commands - DCmd_Register("current_scene", WRAP_METHOD(Console, cmdCurrentScene)); - DCmd_Register("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter)); - DCmd_Register("scene_change", WRAP_METHOD(Console, cmdSceneChange)); - DCmd_Register("chapter_change", WRAP_METHOD(Console, cmdChapterChange)); + registerCmd("current_scene", WRAP_METHOD(Console, cmdCurrentScene)); + registerCmd("current_chapter", WRAP_METHOD(Console, cmdCurrentChapter)); + registerCmd("scene_change", WRAP_METHOD(Console, cmdSceneChange)); + registerCmd("chapter_change", WRAP_METHOD(Console, cmdChapterChange)); - DCmd_Register("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo)); - DCmd_Register("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo)); + registerCmd("action_map_info", WRAP_METHOD(Console, cmdActionMapInfo)); + registerCmd("object_map_info", WRAP_METHOD(Console, cmdObjectMapInfo)); // Script commands - DCmd_Register("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads)); + registerCmd("wake_up_threads", WRAP_METHOD(Console, cmdWakeUpThreads)); // Panel commands - DCmd_Register("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode)); - DCmd_Register("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode)); + registerCmd("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode)); + registerCmd("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode)); // Font commands - DCmd_Register("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping)); + registerCmd("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping)); // Global flags commands - DCmd_Register("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo)); - DCmd_Register("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag)); - DCmd_Register("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag)); + registerCmd("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo)); + registerCmd("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag)); + registerCmd("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag)); } Console::~Console() { @@ -89,7 +89,7 @@ Console::~Console() { bool Console::cmdActorWalkTo(int argc, const char **argv) { if (argc != 4) - DebugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); + debugPrintf("Usage: %s <Actor id> <lx> <ly>\n", argv[0]); else _vm->_actor->cmdActorWalkTo(argc, argv); return true; @@ -110,7 +110,7 @@ bool Console::cmdCutawayInfo(int argc, const char **argv) { bool Console::cmdPlayCutaway(int argc, const char **argv) { #ifdef ENABLE_IHNM if (argc != 2) - DebugPrintf("Usage: %s <Cutaway number>\n", argv[0]); + debugPrintf("Usage: %s <Cutaway number>\n", argv[0]); else _vm->_anim->playCutaway(atoi(argv[1]), false); #endif @@ -118,19 +118,19 @@ bool Console::cmdPlayCutaway(int argc, const char **argv) { } bool Console::cmdCurrentScene(int argc, const char **argv) { - DebugPrintf("Current Scene is: %i, scene resource id: %i\n", + debugPrintf("Current Scene is: %i, scene resource id: %i\n", _vm->_scene->currentSceneNumber(), _vm->_scene->currentSceneResourceId()); return true; } bool Console::cmdCurrentChapter(int argc, const char **argv) { - DebugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber()); + debugPrintf("Current Chapter is: %i\n", _vm->_scene->currentChapterNumber()); return true; } bool Console::cmdSceneChange(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Scene number>\n", argv[0]); + debugPrintf("Usage: %s <Scene number>\n", argv[0]); else _vm->_scene->cmdSceneChange(argc, argv); return true; @@ -138,7 +138,7 @@ bool Console::cmdSceneChange(int argc, const char **argv) { bool Console::cmdChapterChange(int argc, const char **argv) { if (argc != 3) - DebugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]); + debugPrintf("Usage: %s <Chapter number> <Scene number>\n", argv[0]); else { _vm->_scene->setChapterNumber(atoi(argv[2])); _vm->_scene->cmdSceneChange(argc, argv); @@ -158,9 +158,9 @@ bool Console::cmdObjectMapInfo(int argc, const char **argv) { bool Console::cmdWakeUpThreads(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <wait type>\n", argv[0]); - DebugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames"); - DebugPrintf("Refer to saga/script.h for additional types"); + debugPrintf("Usage: %s <wait type>\n", argv[0]); + debugPrintf("e.g.: 1 for kWaitTypeDelay, 2 for kWaitTypeSpeech, 10 for kWaitTypeWaitFrames"); + debugPrintf("Refer to saga/script.h for additional types"); } else { _vm->_script->wakeUpThreads(atoi(argv[1])); } @@ -168,13 +168,13 @@ bool Console::cmdWakeUpThreads(int argc, const char **argv) { } bool Console::cmdCurrentPanelMode(int argc, const char **argv) { - DebugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode()); + debugPrintf("Current Panel Mode is: %i\n", _vm->_interface->getMode()); return true; } bool Console::cmdSetPanelMode(int argc, const char **argv) { if (argc != 2) - DebugPrintf("Usage: %s <Panel mode number>\n", argv[0]); + debugPrintf("Usage: %s <Panel mode number>\n", argv[0]); else _vm->_interface->setMode(atoi(argv[1])); return true; @@ -182,8 +182,8 @@ bool Console::cmdSetPanelMode(int argc, const char **argv) { bool Console::cmdSetFontMapping(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]); - DebugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n"); + debugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]); + debugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n"); } else { _vm->_font->setFontMapping(atoi(argv[1])); } @@ -191,7 +191,7 @@ bool Console::cmdSetFontMapping(int argc, const char **argv) { } bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { - DebugPrintf("Global flags status for IHNM:\n"); + debugPrintf("Global flags status for IHNM:\n"); // Global flags in IHNM: // 00: Tested when Gorrister's chapter ends. 0: Gorrister failed, 1: Gorrister won @@ -232,9 +232,9 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { for (i = 0; i < 32; i += 8) { for (k = i; k < i + 8; k ++) { flagStatus = _vm->_globalFlags & (1 << k) ? 1 : 0; - _vm->_console->DebugPrintf("%02d: %u |", k, flagStatus); + _vm->_console->debugPrintf("%02d: %u |", k, flagStatus); } - _vm->_console->DebugPrintf("\n"); + _vm->_console->debugPrintf("\n"); } return true; @@ -242,13 +242,13 @@ bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) { bool Console::cmdSetGlobalFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); + debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); } else { int flagNumber = atoi(argv[1]); if (flagNumber >= 0 && flagNumber <= 31) { _vm->_globalFlags |= (1 << flagNumber); } else { - DebugPrintf("Valid flag numbers are 0 - 31\n"); + debugPrintf("Valid flag numbers are 0 - 31\n"); } } return true; @@ -256,13 +256,13 @@ bool Console::cmdSetGlobalFlag(int argc, const char **argv) { bool Console::cmdClearGlobalFlag(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); + debugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]); } else { int flagNumber = atoi(argv[1]); if (flagNumber >= 0 && flagNumber <= 31) { _vm->_globalFlags &= ~(1 << flagNumber); } else { - DebugPrintf("Valid flag numbers are 0 - 31\n"); + debugPrintf("Valid flag numbers are 0 - 31\n"); } } return true; diff --git a/engines/saga/objectmap.cpp b/engines/saga/objectmap.cpp index f27c888a61..ad5167209c 100644 --- a/engines/saga/objectmap.cpp +++ b/engines/saga/objectmap.cpp @@ -231,7 +231,7 @@ int ObjectMap::hitTest(const Point& testPoint) { } void ObjectMap::cmdInfo() { - _vm->_console->DebugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size()); + _vm->_console->debugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size()); } } // End of namespace Saga diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 7f77cbab38..04776bd5dc 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1220,7 +1220,7 @@ void Scene::cmdSceneChange(int argc, const char **argv) { scene_num = atoi(argv[1]); if ((scene_num < 1) || (uint(scene_num) >= _sceneLUT.size())) { - _vm->_console->DebugPrintf("Invalid scene number.\n"); + _vm->_console->debugPrintf("Invalid scene number.\n"); return; } diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 91e39c54b6..cb963e23ac 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -139,7 +139,7 @@ void Script::setupITEScriptFuncList() { void Script::sfPutString(SCRIPTFUNC_PARAMS) { const char *str = thread->_strings->getString(thread->pop()); - _vm->_console->DebugPrintf("sfPutString: %s\n",str); + _vm->_console->debugPrintf("sfPutString: %s\n",str); debug(0, "sfPutString: %s", str); } diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 1bc0dd067c..1c4228eb7d 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -79,148 +79,151 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), assert(_engine->_gamestate); // Variables - DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); - DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0); - DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); - DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); - DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0); + registerVar("sleeptime_factor", &g_debug_sleeptime_factor); + registerVar("gc_interval", &engine->_gamestate->scriptGCInterval); + registerVar("simulated_key", &g_debug_simulated_key); + registerVar("track_mouse_clicks", &g_debug_track_mouse_clicks); + // FIXME: This actually passes an enum type instead of an integer but no + // precaution is taken to assure that all assigned values are in the range + // of the enum type. We should handle this more carefully... + registerVar("script_abort_flag", (int *)&_engine->_gamestate->abortScriptProcessing); // General - DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); + registerCmd("help", WRAP_METHOD(Console, cmdHelp)); // Kernel -// DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO - DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes)); - DCmd_Register("selector", WRAP_METHOD(Console, cmdSelector)); - DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors)); - DCmd_Register("functions", WRAP_METHOD(Console, cmdKernelFunctions)); - DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable)); +// registerCmd("classes", WRAP_METHOD(Console, cmdClasses)); // TODO + registerCmd("opcodes", WRAP_METHOD(Console, cmdOpcodes)); + registerCmd("selector", WRAP_METHOD(Console, cmdSelector)); + registerCmd("selectors", WRAP_METHOD(Console, cmdSelectors)); + registerCmd("functions", WRAP_METHOD(Console, cmdKernelFunctions)); + registerCmd("class_table", WRAP_METHOD(Console, cmdClassTable)); // Parser - DCmd_Register("suffixes", WRAP_METHOD(Console, cmdSuffixes)); - DCmd_Register("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar)); - DCmd_Register("parser_nodes", WRAP_METHOD(Console, cmdParserNodes)); - DCmd_Register("parser_words", WRAP_METHOD(Console, cmdParserWords)); - DCmd_Register("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); - DCmd_Register("parse", WRAP_METHOD(Console, cmdParse)); - DCmd_Register("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes)); - DCmd_Register("said", WRAP_METHOD(Console, cmdSaid)); + registerCmd("suffixes", WRAP_METHOD(Console, cmdSuffixes)); + registerCmd("parse_grammar", WRAP_METHOD(Console, cmdParseGrammar)); + registerCmd("parser_nodes", WRAP_METHOD(Console, cmdParserNodes)); + registerCmd("parser_words", WRAP_METHOD(Console, cmdParserWords)); + registerCmd("sentence_fragments", WRAP_METHOD(Console, cmdSentenceFragments)); + registerCmd("parse", WRAP_METHOD(Console, cmdParse)); + registerCmd("set_parse_nodes", WRAP_METHOD(Console, cmdSetParseNodes)); + registerCmd("said", WRAP_METHOD(Console, cmdSaid)); // Resources - DCmd_Register("diskdump", WRAP_METHOD(Console, cmdDiskDump)); - DCmd_Register("hexdump", WRAP_METHOD(Console, cmdHexDump)); - DCmd_Register("resource_id", WRAP_METHOD(Console, cmdResourceId)); - DCmd_Register("resource_info", WRAP_METHOD(Console, cmdResourceInfo)); - DCmd_Register("resource_types", WRAP_METHOD(Console, cmdResourceTypes)); - DCmd_Register("list", WRAP_METHOD(Console, cmdList)); - DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); - DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); + registerCmd("diskdump", WRAP_METHOD(Console, cmdDiskDump)); + registerCmd("hexdump", WRAP_METHOD(Console, cmdHexDump)); + registerCmd("resource_id", WRAP_METHOD(Console, cmdResourceId)); + registerCmd("resource_info", WRAP_METHOD(Console, cmdResourceInfo)); + registerCmd("resource_types", WRAP_METHOD(Console, cmdResourceTypes)); + registerCmd("list", WRAP_METHOD(Console, cmdList)); + registerCmd("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); + registerCmd("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); // Game - DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); - DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); - DCmd_Register("restart_game", WRAP_METHOD(Console, cmdRestartGame)); - DCmd_Register("version", WRAP_METHOD(Console, cmdGetVersion)); - DCmd_Register("room", WRAP_METHOD(Console, cmdRoomNumber)); - DCmd_Register("quit", WRAP_METHOD(Console, cmdQuit)); - DCmd_Register("list_saves", WRAP_METHOD(Console, cmdListSaves)); + registerCmd("save_game", WRAP_METHOD(Console, cmdSaveGame)); + registerCmd("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); + registerCmd("restart_game", WRAP_METHOD(Console, cmdRestartGame)); + registerCmd("version", WRAP_METHOD(Console, cmdGetVersion)); + registerCmd("room", WRAP_METHOD(Console, cmdRoomNumber)); + registerCmd("quit", WRAP_METHOD(Console, cmdQuit)); + registerCmd("list_saves", WRAP_METHOD(Console, cmdListSaves)); // Graphics - DCmd_Register("show_map", WRAP_METHOD(Console, cmdShowMap)); - DCmd_Register("set_palette", WRAP_METHOD(Console, cmdSetPalette)); - DCmd_Register("draw_pic", WRAP_METHOD(Console, cmdDrawPic)); - DCmd_Register("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); - DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither)); - DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); - DCmd_Register("play_video", WRAP_METHOD(Console, cmdPlayVideo)); - DCmd_Register("animate_list", WRAP_METHOD(Console, cmdAnimateList)); - DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias - DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList)); - DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias - DCmd_Register("plane_list", WRAP_METHOD(Console, cmdPlaneList)); - DCmd_Register("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias - DCmd_Register("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); - DCmd_Register("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias - DCmd_Register("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); - DCmd_Register("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); + registerCmd("show_map", WRAP_METHOD(Console, cmdShowMap)); + registerCmd("set_palette", WRAP_METHOD(Console, cmdSetPalette)); + registerCmd("draw_pic", WRAP_METHOD(Console, cmdDrawPic)); + registerCmd("draw_cel", WRAP_METHOD(Console, cmdDrawCel)); + registerCmd("undither", WRAP_METHOD(Console, cmdUndither)); + registerCmd("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); + registerCmd("play_video", WRAP_METHOD(Console, cmdPlayVideo)); + registerCmd("animate_list", WRAP_METHOD(Console, cmdAnimateList)); + registerCmd("al", WRAP_METHOD(Console, cmdAnimateList)); // alias + registerCmd("window_list", WRAP_METHOD(Console, cmdWindowList)); + registerCmd("wl", WRAP_METHOD(Console, cmdWindowList)); // alias + registerCmd("plane_list", WRAP_METHOD(Console, cmdPlaneList)); + registerCmd("pl", WRAP_METHOD(Console, cmdPlaneList)); // alias + registerCmd("plane_items", WRAP_METHOD(Console, cmdPlaneItemList)); + registerCmd("pi", WRAP_METHOD(Console, cmdPlaneItemList)); // alias + registerCmd("saved_bits", WRAP_METHOD(Console, cmdSavedBits)); + registerCmd("show_saved_bits", WRAP_METHOD(Console, cmdShowSavedBits)); // Segments - DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); - DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias - DCmd_Register("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); - DCmd_Register("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias - DCmd_Register("segment_kill", WRAP_METHOD(Console, cmdKillSegment)); - DCmd_Register("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias + registerCmd("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); + registerCmd("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias + registerCmd("segment_info", WRAP_METHOD(Console, cmdSegmentInfo)); + registerCmd("seginfo", WRAP_METHOD(Console, cmdSegmentInfo)); // alias + registerCmd("segment_kill", WRAP_METHOD(Console, cmdKillSegment)); + registerCmd("segkill", WRAP_METHOD(Console, cmdKillSegment)); // alias // Garbage collection - DCmd_Register("gc", WRAP_METHOD(Console, cmdGCInvoke)); - DCmd_Register("gc_objects", WRAP_METHOD(Console, cmdGCObjects)); - DCmd_Register("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable)); - DCmd_Register("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable)); - DCmd_Register("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize)); + registerCmd("gc", WRAP_METHOD(Console, cmdGCInvoke)); + registerCmd("gc_objects", WRAP_METHOD(Console, cmdGCObjects)); + registerCmd("gc_reachable", WRAP_METHOD(Console, cmdGCShowReachable)); + registerCmd("gc_freeable", WRAP_METHOD(Console, cmdGCShowFreeable)); + registerCmd("gc_normalize", WRAP_METHOD(Console, cmdGCNormalize)); // Music/SFX - DCmd_Register("songlib", WRAP_METHOD(Console, cmdSongLib)); - DCmd_Register("songinfo", WRAP_METHOD(Console, cmdSongInfo)); - DCmd_Register("is_sample", WRAP_METHOD(Console, cmdIsSample)); - DCmd_Register("startsound", WRAP_METHOD(Console, cmdStartSound)); - DCmd_Register("togglesound", WRAP_METHOD(Console, cmdToggleSound)); - DCmd_Register("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds)); - DCmd_Register("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header)); - DCmd_Register("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track)); - DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); - DCmd_Register("map_instrument", WRAP_METHOD(Console, cmdMapInstrument)); + registerCmd("songlib", WRAP_METHOD(Console, cmdSongLib)); + registerCmd("songinfo", WRAP_METHOD(Console, cmdSongInfo)); + registerCmd("is_sample", WRAP_METHOD(Console, cmdIsSample)); + registerCmd("startsound", WRAP_METHOD(Console, cmdStartSound)); + registerCmd("togglesound", WRAP_METHOD(Console, cmdToggleSound)); + registerCmd("stopallsounds", WRAP_METHOD(Console, cmdStopAllSounds)); + registerCmd("sfx01_header", WRAP_METHOD(Console, cmdSfx01Header)); + registerCmd("sfx01_track", WRAP_METHOD(Console, cmdSfx01Track)); + registerCmd("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); + registerCmd("map_instrument", WRAP_METHOD(Console, cmdMapInstrument)); // Script - DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses)); - DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); - DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); - DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); - DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias - DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace)); - DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias - DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias - DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver)); - DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias - DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); - DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias - DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent)); - DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias - DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal)); - DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias - DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk)); - DCmd_Register("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias - DCmd_Register("disasm", WRAP_METHOD(Console, cmdDisassemble)); - DCmd_Register("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress)); - DCmd_Register("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall)); - DCmd_Register("send", WRAP_METHOD(Console, cmdSend)); - DCmd_Register("go", WRAP_METHOD(Console, cmdGo)); - DCmd_Register("logkernel", WRAP_METHOD(Console, cmdLogKernel)); + registerCmd("addresses", WRAP_METHOD(Console, cmdAddresses)); + registerCmd("registers", WRAP_METHOD(Console, cmdRegisters)); + registerCmd("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); + registerCmd("backtrace", WRAP_METHOD(Console, cmdBacktrace)); + registerCmd("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias + registerCmd("trace", WRAP_METHOD(Console, cmdTrace)); + registerCmd("t", WRAP_METHOD(Console, cmdTrace)); // alias + registerCmd("s", WRAP_METHOD(Console, cmdTrace)); // alias + registerCmd("stepover", WRAP_METHOD(Console, cmdStepOver)); + registerCmd("p", WRAP_METHOD(Console, cmdStepOver)); // alias + registerCmd("step_ret", WRAP_METHOD(Console, cmdStepRet)); + registerCmd("pret", WRAP_METHOD(Console, cmdStepRet)); // alias + registerCmd("step_event", WRAP_METHOD(Console, cmdStepEvent)); + registerCmd("se", WRAP_METHOD(Console, cmdStepEvent)); // alias + registerCmd("step_global", WRAP_METHOD(Console, cmdStepGlobal)); + registerCmd("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias + registerCmd("step_callk", WRAP_METHOD(Console, cmdStepCallk)); + registerCmd("snk", WRAP_METHOD(Console, cmdStepCallk)); // alias + registerCmd("disasm", WRAP_METHOD(Console, cmdDisassemble)); + registerCmd("disasm_addr", WRAP_METHOD(Console, cmdDisassembleAddress)); + registerCmd("find_callk", WRAP_METHOD(Console, cmdFindKernelFunctionCall)); + registerCmd("send", WRAP_METHOD(Console, cmdSend)); + registerCmd("go", WRAP_METHOD(Console, cmdGo)); + registerCmd("logkernel", WRAP_METHOD(Console, cmdLogKernel)); // Breakpoints - DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); - DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias - DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias - DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); - DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias - DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias - DCmd_Register("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod)); - DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias - DCmd_Register("bp_read", WRAP_METHOD(Console, cmdBreakpointRead)); - DCmd_Register("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias - DCmd_Register("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite)); - DCmd_Register("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias - DCmd_Register("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel)); - DCmd_Register("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias - DCmd_Register("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction)); - DCmd_Register("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias + registerCmd("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); + registerCmd("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias + registerCmd("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias + registerCmd("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); + registerCmd("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + registerCmd("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + registerCmd("bp_method", WRAP_METHOD(Console, cmdBreakpointMethod)); + registerCmd("bpx", WRAP_METHOD(Console, cmdBreakpointMethod)); // alias + registerCmd("bp_read", WRAP_METHOD(Console, cmdBreakpointRead)); + registerCmd("bpr", WRAP_METHOD(Console, cmdBreakpointRead)); // alias + registerCmd("bp_write", WRAP_METHOD(Console, cmdBreakpointWrite)); + registerCmd("bpw", WRAP_METHOD(Console, cmdBreakpointWrite)); // alias + registerCmd("bp_kernel", WRAP_METHOD(Console, cmdBreakpointKernel)); + registerCmd("bpk", WRAP_METHOD(Console, cmdBreakpointKernel)); // alias + registerCmd("bp_function", WRAP_METHOD(Console, cmdBreakpointFunction)); + registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias // VM - DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); - DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); - DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias - DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias - DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars)); - DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias - DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias - DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); - DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); - DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); - DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); - DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias - DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); - DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias - DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); - DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); + registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); + registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); + registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias + registerCmd("vm_vars", WRAP_METHOD(Console, cmdVMVars)); + registerCmd("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + registerCmd("vv", WRAP_METHOD(Console, cmdVMVars)); // alias + registerCmd("stack", WRAP_METHOD(Console, cmdStack)); + registerCmd("value_type", WRAP_METHOD(Console, cmdValueType)); + registerCmd("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); + registerCmd("view_reference", WRAP_METHOD(Console, cmdViewReference)); + registerCmd("vr", WRAP_METHOD(Console, cmdViewReference)); // alias + registerCmd("view_object", WRAP_METHOD(Console, cmdViewObject)); + registerCmd("vo", WRAP_METHOD(Console, cmdViewObject)); // alias + registerCmd("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); + registerCmd("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); _debugState.seeking = kDebugSeekNothing; _debugState.seekLevel = 0; @@ -307,137 +310,137 @@ void Console::postEnter() { } bool Console::cmdHelp(int argc, const char **argv) { - DebugPrintf("\n"); - DebugPrintf("Variables\n"); - DebugPrintf("---------\n"); - DebugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n"); - DebugPrintf("gc_interval: Number of kernel calls in between garbage collections\n"); - DebugPrintf("simulated_key: Add a key with the specified scan code to the event list\n"); - DebugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n"); - DebugPrintf("weak_validations: Turns some validation errors into warnings\n"); - DebugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); - DebugPrintf("\n"); - DebugPrintf("Debug flags\n"); - DebugPrintf("-----------\n"); - DebugPrintf("debugflag_list - Lists the available debug flags and their status\n"); - DebugPrintf("debugflag_enable - Enables a debug flag\n"); - DebugPrintf("debugflag_disable - Disables a debug flag\n"); - DebugPrintf("\n"); - DebugPrintf("Commands\n"); - DebugPrintf("--------\n"); - DebugPrintf("Kernel:\n"); - DebugPrintf(" opcodes - Lists the opcode names\n"); - DebugPrintf(" selectors - Lists the selector names\n"); - DebugPrintf(" selector - Attempts to find the requested selector by name\n"); - DebugPrintf(" functions - Lists the kernel functions\n"); - DebugPrintf(" class_table - Shows the available classes\n"); - DebugPrintf("\n"); - DebugPrintf("Parser:\n"); - DebugPrintf(" suffixes - Lists the vocabulary suffixes\n"); - DebugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n"); - DebugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n"); - DebugPrintf(" parser_words - Shows the words from the parse node tree\n"); - DebugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n"); - DebugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n"); - DebugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); - DebugPrintf(" said - Match a string against a said spec\n"); - DebugPrintf("\n"); - DebugPrintf("Resources:\n"); - DebugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n"); - DebugPrintf(" hexdump - Dumps the specified resource to standard output\n"); - DebugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n"); - DebugPrintf(" resource_info - Shows info about a resource\n"); - DebugPrintf(" resource_types - Shows the valid resource types\n"); - DebugPrintf(" list - Lists all the resources of a given type\n"); - DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); - DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); - DebugPrintf("\n"); - DebugPrintf("Game:\n"); - DebugPrintf(" save_game - Saves the current game state to the hard disk\n"); - DebugPrintf(" restore_game - Restores a saved game from the hard disk\n"); - DebugPrintf(" list_saves - List all saved games including filenames\n"); - DebugPrintf(" restart_game - Restarts the game\n"); - DebugPrintf(" version - Shows the resource and interpreter versions\n"); - DebugPrintf(" room - Gets or sets the current room number\n"); - DebugPrintf(" quit - Quits the game\n"); - DebugPrintf("\n"); - DebugPrintf("Graphics:\n"); - DebugPrintf(" show_map - Switches to visual, priority, control or display screen\n"); - DebugPrintf(" set_palette - Sets a palette resource\n"); - DebugPrintf(" draw_pic - Draws a pic resource\n"); - DebugPrintf(" draw_cel - Draws a cel from a view resource\n"); - DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); - DebugPrintf(" undither - Enable/disable undithering\n"); - DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); - DebugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); - DebugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); - DebugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); - DebugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); - DebugPrintf(" saved_bits - List saved bits on the hunk\n"); - DebugPrintf(" show_saved_bits - Display saved bits\n"); - DebugPrintf("\n"); - DebugPrintf("Segments:\n"); - DebugPrintf(" segment_table / segtable - Lists all segments\n"); - DebugPrintf(" segment_info / seginfo - Provides information on the specified segment\n"); - DebugPrintf(" segment_kill / segkill - Deletes the specified segment\n"); - DebugPrintf("\n"); - DebugPrintf("Garbage collection:\n"); - DebugPrintf(" gc - Invokes the garbage collector\n"); - DebugPrintf(" gc_objects - Lists all reachable objects, normalized\n"); - DebugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n"); - DebugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n"); - DebugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n"); - DebugPrintf("\n"); - DebugPrintf("Music/SFX:\n"); - DebugPrintf(" songlib - Shows the song library\n"); - DebugPrintf(" songinfo - Shows information about a specified song in the song library\n"); - DebugPrintf(" togglesound - Starts/stops a sound in the song library\n"); - DebugPrintf(" stopallsounds - Stops all sounds in the playlist\n"); - DebugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n"); - DebugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n"); - DebugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n"); - DebugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n"); - DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); - DebugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n"); - DebugPrintf("\n"); - DebugPrintf("Script:\n"); - DebugPrintf(" addresses - Provides information on how to pass addresses\n"); - DebugPrintf(" registers - Shows the current register values\n"); - DebugPrintf(" dissect_script - Examines a script\n"); - DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); - DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); - DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); - DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); - DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); - DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); - DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); - DebugPrintf(" disasm - Disassembles a method by name\n"); - DebugPrintf(" disasm_addr - Disassembles one or more commands\n"); - DebugPrintf(" send - Sends a message to an object\n"); - DebugPrintf(" go - Executes the script\n"); - DebugPrintf(" logkernel - Logs kernel calls\n"); - DebugPrintf("\n"); - DebugPrintf("Breakpoints:\n"); - DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); - DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); - DebugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n"); - DebugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n"); - DebugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n"); - DebugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n"); - DebugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); - DebugPrintf("\n"); - DebugPrintf("VM:\n"); - DebugPrintf(" script_steps - Shows the number of executed SCI operations\n"); - DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); - DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); - DebugPrintf(" stack - Lists the specified number of stack elements\n"); - DebugPrintf(" value_type - Determines the type of a value\n"); - DebugPrintf(" view_listnode - Examines the list node at the given address\n"); - DebugPrintf(" view_reference / vr - Examines an arbitrary reference\n"); - DebugPrintf(" view_object / vo - Examines the object at the given address\n"); - DebugPrintf(" active_object - Shows information on the currently active object or class\n"); - DebugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); - DebugPrintf("\n"); + debugPrintf("\n"); + debugPrintf("Variables\n"); + debugPrintf("---------\n"); + debugPrintf("sleeptime_factor: Factor to multiply with wait times in kWait()\n"); + debugPrintf("gc_interval: Number of kernel calls in between garbage collections\n"); + debugPrintf("simulated_key: Add a key with the specified scan code to the event list\n"); + debugPrintf("track_mouse_clicks: Toggles mouse click tracking to the console\n"); + debugPrintf("weak_validations: Turns some validation errors into warnings\n"); + debugPrintf("script_abort_flag: Set to 1 to abort script execution. Set to 2 to force a replay afterwards\n"); + debugPrintf("\n"); + debugPrintf("Debug flags\n"); + debugPrintf("-----------\n"); + debugPrintf("debugflag_list - Lists the available debug flags and their status\n"); + debugPrintf("debugflag_enable - Enables a debug flag\n"); + debugPrintf("debugflag_disable - Disables a debug flag\n"); + debugPrintf("\n"); + debugPrintf("Commands\n"); + debugPrintf("--------\n"); + debugPrintf("Kernel:\n"); + debugPrintf(" opcodes - Lists the opcode names\n"); + debugPrintf(" selectors - Lists the selector names\n"); + debugPrintf(" selector - Attempts to find the requested selector by name\n"); + debugPrintf(" functions - Lists the kernel functions\n"); + debugPrintf(" class_table - Shows the available classes\n"); + debugPrintf("\n"); + debugPrintf("Parser:\n"); + debugPrintf(" suffixes - Lists the vocabulary suffixes\n"); + debugPrintf(" parse_grammar - Shows the parse grammar, in strict GNF\n"); + debugPrintf(" parser_nodes - Shows the specified number of nodes from the parse node tree\n"); + debugPrintf(" parser_words - Shows the words from the parse node tree\n"); + debugPrintf(" sentence_fragments - Shows the sentence fragments (used to build Parse trees)\n"); + debugPrintf(" parse - Parses a sequence of words and prints the resulting parse tree\n"); + debugPrintf(" set_parse_nodes - Sets the contents of all parse nodes\n"); + debugPrintf(" said - Match a string against a said spec\n"); + debugPrintf("\n"); + debugPrintf("Resources:\n"); + debugPrintf(" diskdump - Dumps the specified resource to disk as a patch file\n"); + debugPrintf(" hexdump - Dumps the specified resource to standard output\n"); + debugPrintf(" resource_id - Identifies a resource number by splitting it up in resource type and resource number\n"); + debugPrintf(" resource_info - Shows info about a resource\n"); + debugPrintf(" resource_types - Shows the valid resource types\n"); + debugPrintf(" list - Lists all the resources of a given type\n"); + debugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); + debugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); + debugPrintf("\n"); + debugPrintf("Game:\n"); + debugPrintf(" save_game - Saves the current game state to the hard disk\n"); + debugPrintf(" restore_game - Restores a saved game from the hard disk\n"); + debugPrintf(" list_saves - List all saved games including filenames\n"); + debugPrintf(" restart_game - Restarts the game\n"); + debugPrintf(" version - Shows the resource and interpreter versions\n"); + debugPrintf(" room - Gets or sets the current room number\n"); + debugPrintf(" quit - Quits the game\n"); + debugPrintf("\n"); + debugPrintf("Graphics:\n"); + debugPrintf(" show_map - Switches to visual, priority, control or display screen\n"); + debugPrintf(" set_palette - Sets a palette resource\n"); + debugPrintf(" draw_pic - Draws a pic resource\n"); + debugPrintf(" draw_cel - Draws a cel from a view resource\n"); + debugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); + debugPrintf(" undither - Enable/disable undithering\n"); + debugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); + debugPrintf(" animate_list / al - Shows the current list of objects in kAnimate's draw list (SCI0 - SCI1.1)\n"); + debugPrintf(" window_list / wl - Shows a list of all the windows (ports) in the draw list (SCI0 - SCI1.1)\n"); + debugPrintf(" plane_list / pl - Shows a list of all the planes in the draw list (SCI2+)\n"); + debugPrintf(" plane_items / pi - Shows a list of all items for a plane (SCI2+)\n"); + debugPrintf(" saved_bits - List saved bits on the hunk\n"); + debugPrintf(" show_saved_bits - Display saved bits\n"); + debugPrintf("\n"); + debugPrintf("Segments:\n"); + debugPrintf(" segment_table / segtable - Lists all segments\n"); + debugPrintf(" segment_info / seginfo - Provides information on the specified segment\n"); + debugPrintf(" segment_kill / segkill - Deletes the specified segment\n"); + debugPrintf("\n"); + debugPrintf("Garbage collection:\n"); + debugPrintf(" gc - Invokes the garbage collector\n"); + debugPrintf(" gc_objects - Lists all reachable objects, normalized\n"); + debugPrintf(" gc_reachable - Lists all addresses directly reachable from a given memory object\n"); + debugPrintf(" gc_freeable - Lists all addresses freeable in a given segment\n"); + debugPrintf(" gc_normalize - Prints the \"normal\" address of a given address\n"); + debugPrintf("\n"); + debugPrintf("Music/SFX:\n"); + debugPrintf(" songlib - Shows the song library\n"); + debugPrintf(" songinfo - Shows information about a specified song in the song library\n"); + debugPrintf(" togglesound - Starts/stops a sound in the song library\n"); + debugPrintf(" stopallsounds - Stops all sounds in the playlist\n"); + debugPrintf(" startsound - Starts the specified sound resource, replacing the first song in the song library\n"); + debugPrintf(" is_sample - Shows information on a given sound resource, if it's a PCM sample\n"); + debugPrintf(" sfx01_header - Dumps the header of a SCI01 song\n"); + debugPrintf(" sfx01_track - Dumps a track of a SCI01 song\n"); + debugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); + debugPrintf(" map_instrument - Dynamically maps an MT-32 instrument to a GM instrument\n"); + debugPrintf("\n"); + debugPrintf("Script:\n"); + debugPrintf(" addresses - Provides information on how to pass addresses\n"); + debugPrintf(" registers - Shows the current register values\n"); + debugPrintf(" dissect_script - Examines a script\n"); + debugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); + debugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + debugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); + debugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); + debugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); + debugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); + debugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); + debugPrintf(" disasm - Disassembles a method by name\n"); + debugPrintf(" disasm_addr - Disassembles one or more commands\n"); + debugPrintf(" send - Sends a message to an object\n"); + debugPrintf(" go - Executes the script\n"); + debugPrintf(" logkernel - Logs kernel calls\n"); + debugPrintf("\n"); + debugPrintf("Breakpoints:\n"); + debugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); + debugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); + debugPrintf(" bp_method / bpx - Sets a breakpoint on the execution of a specified method/selector\n"); + debugPrintf(" bp_read / bpr - Sets a breakpoint on reading of a specified selector\n"); + debugPrintf(" bp_write / bpw - Sets a breakpoint on writing to a specified selector\n"); + debugPrintf(" bp_kernel / bpk - Sets a breakpoint on execution of a kernel function\n"); + debugPrintf(" bp_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); + debugPrintf("\n"); + debugPrintf("VM:\n"); + debugPrintf(" script_steps - Shows the number of executed SCI operations\n"); + debugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); + debugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); + debugPrintf(" stack - Lists the specified number of stack elements\n"); + debugPrintf(" value_type - Determines the type of a value\n"); + debugPrintf(" view_listnode - Examines the list node at the given address\n"); + debugPrintf(" view_reference / vr - Examines an arbitrary reference\n"); + debugPrintf(" view_object / vo - Examines the object at the given address\n"); + debugPrintf(" active_object - Shows information on the currently active object or class\n"); + debugPrintf(" acc_object - Shows information on the object or class at the address indexed by the accumulator\n"); + debugPrintf("\n"); return true; } @@ -464,30 +467,30 @@ bool Console::cmdGetVersion(int argc, const char **argv) { versionFile.close(); } - DebugPrintf("Game ID: %s\n", _engine->getGameIdStr()); - DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); - DebugPrintf("\n"); - DebugPrintf("Detected features:\n"); - DebugPrintf("------------------\n"); - DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); - DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); - DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); - DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); - DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); + debugPrintf("Game ID: %s\n", _engine->getGameIdStr()); + debugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); + debugPrintf("\n"); + debugPrintf("Detected features:\n"); + debugPrintf("------------------\n"); + debugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); + debugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); + debugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); + debugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); + debugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) - DebugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)"); + debugPrintf("kString type: %s\n", (_engine->_features->detectSci2StringFunctionType() == kSci2StringFunctionOld) ? "SCI2 (old)" : "SCI2.1 (new)"); if (getSciVersion() == SCI_VERSION_2_1) - DebugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); + debugPrintf("SCI2.1 kernel table: %s\n", (_engine->_features->detectSci21KernelType() == SCI_VERSION_2) ? "modified SCI2 (old)" : "SCI2.1 (new)"); #endif - DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); - DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); - DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); - DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); - DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); - DebugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no"); - DebugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str()); - DebugPrintf("\n"); + debugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); + debugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); + debugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); + debugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); + debugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); + debugPrintf("Has CantBeHere selector: %s\n", g_sci->getKernel()->_selectorCache.cantBeHere != -1 ? "yes" : "no"); + debugPrintf("Game version (VERSION file): %s\n", gameVersion.c_str()); + debugPrintf("\n"); return true; } @@ -498,13 +501,13 @@ bool Console::cmdOpcodes(int argc, const char **argv) { // If the resource couldn't be loaded, leave if (!r) { - DebugPrintf("unable to load vocab.998"); + debugPrintf("unable to load vocab.998"); return true; } int count = READ_LE_UINT16(r->data); - DebugPrintf("Opcode names in numeric order [index: type name]:\n"); + debugPrintf("Opcode names in numeric order [index: type name]:\n"); for (int i = 0; i < count; i++) { int offset = READ_LE_UINT16(r->data + 2 + i * 2); @@ -512,49 +515,49 @@ bool Console::cmdOpcodes(int argc, const char **argv) { int type = READ_LE_UINT16(r->data + offset + 2); // QFG3 has empty opcodes Common::String name = len > 0 ? Common::String((const char *)r->data + offset + 4, len) : "Dummy"; - DebugPrintf("%03x: %03x %20s | ", i, type, name.c_str()); + debugPrintf("%03x: %03x %20s | ", i, type, name.c_str()); if ((i % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::cmdSelector(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Attempts to find the requested selector by name.\n"); - DebugPrintf("Usage: %s <selector name>\n", argv[0]); + debugPrintf("Attempts to find the requested selector by name.\n"); + debugPrintf("Usage: %s <selector name>\n", argv[0]); return true; } Common::String name = argv[1]; int seeker = _engine->getKernel()->findSelector(name.c_str()); if (seeker >= 0) { - DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); + debugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); return true; } - DebugPrintf("Selector %s wasn't found\n", name.c_str()); + debugPrintf("Selector %s wasn't found\n", name.c_str()); return true; } bool Console::cmdSelectors(int argc, const char **argv) { - DebugPrintf("Selector names in numeric order:\n"); + debugPrintf("Selector names in numeric order:\n"); Common::String selectorName; for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) { selectorName = _engine->getKernel()->getSelectorName(seeker); if (selectorName != "BAD SELECTOR") - DebugPrintf("%03x: %20s | ", seeker, selectorName.c_str()); + debugPrintf("%03x: %20s | ", seeker, selectorName.c_str()); else continue; if ((seeker % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); #if 0 // For debug/development @@ -584,14 +587,14 @@ bool Console::cmdSelectors(int argc, const char **argv) { } bool Console::cmdKernelFunctions(int argc, const char **argv) { - DebugPrintf("Kernel function names in numeric order:\n"); + debugPrintf("Kernel function names in numeric order:\n"); for (uint seeker = 0; seeker < _engine->getKernel()->getKernelNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str()); + debugPrintf("%03x: %20s | ", seeker, _engine->getKernel()->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -610,9 +613,9 @@ bool Console::cmdParserWords(int argc, const char **argv) { bool Console::cmdSetParseNodes(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Sets the contents of all parse nodes.\n"); - DebugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]); - DebugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n"); + debugPrintf("Sets the contents of all parse nodes.\n"); + debugPrintf("Usage: %s <parse node1> <parse node2> ... <parse noden>\n", argv[0]); + debugPrintf("Tokens should be separated by blanks and enclosed in parentheses\n"); return true; } @@ -643,23 +646,23 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { EngineState *s = _engine->_gamestate; - DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest); + debugPrintf("Current register values:\n"); + debugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->r_rest); if (!s->_executionStack.empty()) { - DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", + debugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(s->xs->addr.pc), PRINT_REG(s->xs->objp), (unsigned)(s->xs->fp - s->stack_base), (unsigned)(s->xs->sp - s->stack_base)); } else - DebugPrintf("<no execution stack: pc,obj,fp omitted>\n"); + debugPrintf("<no execution stack: pc,obj,fp omitted>\n"); return true; } bool Console::cmdDiskDump(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps the specified resource to disk as a patch file\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Dumps the specified resource to disk as a patch file\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); cmdResourceTypes(argc, argv); return true; } @@ -668,7 +671,7 @@ bool Console::cmdDiskDump(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { @@ -680,9 +683,9 @@ bool Console::cmdDiskDump(int argc, const char **argv) { outFile->finalize(); outFile->close(); delete outFile; - DebugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNum, resource->getResourceLocation().c_str()); + debugPrintf("Resource %s.%03d (located in %s) has been dumped to disk\n", argv[1], resNum, resource->getResourceLocation().c_str()); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -691,8 +694,8 @@ bool Console::cmdDiskDump(int argc, const char **argv) { bool Console::cmdHexDump(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps the specified resource to standard output\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Dumps the specified resource to standard output\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); cmdResourceTypes(argc, argv); return true; } @@ -701,14 +704,14 @@ bool Console::cmdHexDump(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { Common::hexdump(resource->data, resource->size, 16, 0); - DebugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); + debugPrintf("Resource %s.%03d has been dumped to standard output\n", argv[1], resNum); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -717,21 +720,21 @@ bool Console::cmdHexDump(int argc, const char **argv) { bool Console::cmdResourceId(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n"); - DebugPrintf("Usage: %s <resource number>\n", argv[0]); + debugPrintf("Identifies a resource number by splitting it up in resource type and resource number\n"); + debugPrintf("Usage: %s <resource number>\n", argv[0]); return true; } int id = atoi(argv[1]); - DebugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff); + debugPrintf("%s.%d (0x%x)\n", getResourceTypeName((ResourceType)(id >> 11)), id & 0x7ff, id & 0x7ff); return true; } bool Console::cmdDissectScript(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines a script\n"); - DebugPrintf("Usage: %s <script number>\n", argv[0]); + debugPrintf("Examines a script\n"); + debugPrintf("Usage: %s <script number>\n", argv[0]); return true; } @@ -745,13 +748,13 @@ bool Console::cmdRoomNumber(int argc, const char **argv) { // The same functionality is provided by "vmvars g 13" (but this one is more straighforward) if (argc != 2) { - DebugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber()); - DebugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n"); + debugPrintf("Current room number is %d\n", _engine->_gamestate->currentRoomNumber()); + debugPrintf("Calling this command with the room number (in decimal or hexadecimal) changes the room\n"); } else { Common::String roomNumberStr = argv[1]; int roomNumber = strtol(roomNumberStr.c_str(), NULL, roomNumberStr.hasSuffix("h") ? 16 : 10); _engine->_gamestate->setRoomNumber(roomNumber); - DebugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber); + debugPrintf("Room number changed to %d (%x in hex)\n", roomNumber, roomNumber); } return true; @@ -759,8 +762,8 @@ bool Console::cmdRoomNumber(int argc, const char **argv) { bool Console::cmdResourceInfo(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Shows information about a resource\n"); - DebugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); + debugPrintf("Shows information about a resource\n"); + debugPrintf("Usage: %s <resource type> <resource number>\n", argv[0]); return true; } @@ -768,14 +771,14 @@ bool Console::cmdResourceInfo(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); else { Resource *resource = _engine->getResMan()->findResource(ResourceId(res, resNum), 0); if (resource) { - DebugPrintf("Resource size: %d\n", resource->size); - DebugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str()); + debugPrintf("Resource size: %d\n", resource->size); + debugPrintf("Resource location: %s\n", resource->getResourceLocation().c_str()); } else { - DebugPrintf("Resource %s.%03d not found\n", argv[1], resNum); + debugPrintf("Resource %s.%03d not found\n", argv[1], resNum); } } @@ -783,10 +786,10 @@ bool Console::cmdResourceInfo(int argc, const char **argv) { } bool Console::cmdResourceTypes(int argc, const char **argv) { - DebugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid); + debugPrintf("The %d valid resource types are:\n", kResourceTypeInvalid); for (int i = 0; i < kResourceTypeInvalid; i++) { - DebugPrintf("%s", getResourceTypeName((ResourceType) i)); - DebugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n"); + debugPrintf("%s", getResourceTypeName((ResourceType) i)); + debugPrintf((i < kResourceTypeInvalid - 1) ? ", " : "\n"); } return true; @@ -794,10 +797,10 @@ bool Console::cmdResourceTypes(int argc, const char **argv) { bool Console::cmdHexgrep(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n"); - DebugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]); - DebugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n"); - DebugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n"); + debugPrintf("Searches some resources for a particular sequence of bytes, represented as decimal or hexadecimal numbers.\n"); + debugPrintf("Usage: %s <resource type> <resource number> <search string>\n", argv[0]); + debugPrintf("<resource number> can be a specific resource number, or \"all\" for all of the resources of the specified type\n"); + debugPrintf("EXAMPLES:\n hexgrep script all 0xe8 0x03 0xc8 0x00\n hexgrep pic 0x42 0xfe\n"); cmdResourceTypes(argc, argv); return true; } @@ -807,7 +810,7 @@ bool Console::cmdHexgrep(int argc, const char **argv) { Resource *script = NULL; if (restype == kResourceTypeInvalid) { - DebugPrintf("Resource type '%s' is not valid\n", argv[1]); + debugPrintf("Resource type '%s' is not valid\n", argv[1]); return true; } @@ -845,10 +848,10 @@ bool Console::cmdHexgrep(int argc, const char **argv) { seeker = seekerold + 1; if (!output_script_name) { - DebugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber); + debugPrintf("\nIn %s.%03d:\n", getResourceTypeName((ResourceType)restype), resNumber); output_script_name = 1; } - DebugPrintf(" 0x%04x\n", seekerold); + debugPrintf(" 0x%04x\n", seekerold); } } else comppos = 0; @@ -863,38 +866,38 @@ bool Console::cmdHexgrep(int argc, const char **argv) { bool Console::cmdVerifyScripts(int argc, const char **argv) { if (getSciVersion() < SCI_VERSION_1_1) { - DebugPrintf("This script check is only meant for SCI1.1-SCI3 games\n"); + debugPrintf("This script check is only meant for SCI1.1-SCI3 games\n"); return true; } Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeScript); Common::sort(resources.begin(), resources.end()); - DebugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size()); + debugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size()); Resource *script, *heap; Common::List<ResourceId>::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { script = _engine->getResMan()->findResource(*itr, false); if (!script) - DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); + debugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); if (getSciVersion() <= SCI_VERSION_2_1) { heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false); if (!heap) - DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); + debugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); if (script && heap && (script->size + heap->size > 65535)) - DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", + debugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", itr->getNumber(), script->size + heap->size); } else { // SCI3 if (script && script->size > 65535) - DebugPrintf("Error: script %d is larger than 64KB (%d bytes)\n", + debugPrintf("Error: script %d is larger than 64KB (%d bytes)\n", itr->getNumber(), script->size); } } - DebugPrintf("SCI1.1-SCI2.1 script check finished\n"); + debugPrintf("SCI1.1-SCI2.1 script check finished\n"); return true; } @@ -931,9 +934,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { instrumentsSongs[i][j] = false; if (songNumber == -1) { - DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size()); - DebugPrintf("Instruments:\n"); - DebugPrintf("============\n"); + debugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size()); + debugPrintf("Instruments:\n"); + debugPrintf("============\n"); } Common::List<ResourceId>::iterator itr; @@ -956,7 +959,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { bool endOfTrack = false; bool firstOneShown = false; - DebugPrintf("Song %d: ", itr->getNumber()); + debugPrintf("Song %d: ", itr->getNumber()); do { while (*channelData == 0xF8) @@ -984,9 +987,9 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { if (!firstOneShown) firstOneShown = true; else - DebugPrintf(","); + debugPrintf(","); - DebugPrintf(" %d", instrument); + debugPrintf(" %d", instrument); instruments[instrument]++; instrumentsSongs[instrument][itr->getNumber()] = true; } else { @@ -1024,44 +1027,44 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { } } while (!endOfTrack); - DebugPrintf("\n"); + debugPrintf("\n"); } delete parser; delete player; - DebugPrintf("\n"); + debugPrintf("\n"); if (songNumber == -1) { - DebugPrintf("Used instruments: "); + debugPrintf("Used instruments: "); for (int i = 0; i < 128; i++) { if (instruments[i] > 0) - DebugPrintf("%d, ", i); + debugPrintf("%d, ", i); } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); } - DebugPrintf("Instruments not mapped in the MT32->GM map: "); + debugPrintf("Instruments not mapped in the MT32->GM map: "); for (int i = 0; i < 128; i++) { if (instruments[i] > 0 && getGmInstrument(Mt32MemoryTimbreMaps[i]) == MIDI_UNMAPPED) - DebugPrintf("%d, ", i); + debugPrintf("%d, ", i); } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); if (songNumber == -1) { - DebugPrintf("Used instruments in songs:\n"); + debugPrintf("Used instruments in songs:\n"); for (int i = 0; i < 128; i++) { if (instruments[i] > 0) { - DebugPrintf("Instrument %d: ", i); + debugPrintf("Instrument %d: ", i); for (int j = 0; j < 1000; j++) { if (instrumentsSongs[i][j]) - DebugPrintf("%d, ", j); + debugPrintf("%d, ", j); } - DebugPrintf("\n"); + debugPrintf("\n"); } } - DebugPrintf("\n\n"); + debugPrintf("\n\n"); } return true; @@ -1069,13 +1072,13 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { bool Console::cmdMapInstrument(int argc, const char **argv) { if (argc != 4) { - DebugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n"); - DebugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]); - DebugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n"); - DebugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n"); - DebugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n"); - DebugPrintf("Example: %s test_0__XX 1 255\n", argv[0]); - DebugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n"); + debugPrintf("Maps an MT-32 custom instrument to a GM instrument on the fly\n\n"); + debugPrintf("Usage %s <MT-32 instrument name> <GM instrument> <GM rhythm key>\n", argv[0]); + debugPrintf("Each MT-32 instrument is always 10 characters and is mapped to either a GM instrument, or a GM rhythm key\n"); + debugPrintf("A value of 255 (0xff) signifies an unmapped instrument\n"); + debugPrintf("Please replace the spaces in the instrument name with underscores (\"_\"). They'll be converted to spaces afterwards\n\n"); + debugPrintf("Example: %s test_0__XX 1 255\n", argv[0]); + debugPrintf("The above example will map the MT-32 instrument \"test 0 XX\" to GM instrument 1\n\n"); } else { if (Mt32dynamicMappings != NULL) { Mt32ToGmMap newMapping; @@ -1093,11 +1096,11 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { } } - DebugPrintf("Current dynamic mappings:\n"); + debugPrintf("Current dynamic mappings:\n"); if (Mt32dynamicMappings != NULL) { const Mt32ToGmMapList::iterator end = Mt32dynamicMappings->end(); for (Mt32ToGmMapList::iterator it = Mt32dynamicMappings->begin(); it != end; ++it) { - DebugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey); + debugPrintf("\"%s\" -> %d / %d\n", (*it).name, (*it).gmInstr, (*it).gmRhythmKey); } } @@ -1106,7 +1109,7 @@ bool Console::cmdMapInstrument(int argc, const char **argv) { bool Console::cmdList(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Lists all the resources of a given type\n"); + debugPrintf("Lists all the resources of a given type\n"); cmdResourceTypes(argc, argv); return true; } @@ -1114,13 +1117,13 @@ bool Console::cmdList(int argc, const char **argv) { ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) - DebugPrintf("Unknown resource type: '%s'\n", argv[1]); + debugPrintf("Unknown resource type: '%s'\n", argv[1]); else { int number = -1; if ((res == kResourceTypeAudio36) || (res == kResourceTypeSync36)) { if (argc != 3) { - DebugPrintf("Please specify map number (-1: all maps)\n"); + debugPrintf("Please specify map number (-1: all maps)\n"); return true; } number = atoi(argv[2]); @@ -1133,18 +1136,18 @@ bool Console::cmdList(int argc, const char **argv) { Common::List<ResourceId>::iterator itr; for (itr = resources.begin(); itr != resources.end(); ++itr) { if (number == -1) { - DebugPrintf("%8i", itr->getNumber()); + debugPrintf("%8i", itr->getNumber()); if (++cnt % 10 == 0) - DebugPrintf("\n"); + debugPrintf("\n"); } else if (number == (int)itr->getNumber()) { const uint32 tuple = itr->getTuple(); - DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, + debugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff); if (++cnt % 4 == 0) - DebugPrintf("\n"); + debugPrintf("\n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; @@ -1152,8 +1155,8 @@ bool Console::cmdList(int argc, const char **argv) { bool Console::cmdSaveGame(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Saves the current game state to the hard disk\n"); - DebugPrintf("Usage: %s <filename>\n", argv[0]); + debugPrintf("Saves the current game state to the hard disk\n"); + debugPrintf("Usage: %s <filename>\n", argv[0]); return true; } @@ -1163,19 +1166,19 @@ bool Console::cmdSaveGame(int argc, const char **argv) { result++; if (result) - DebugPrintf("Note: Game state has %d open file handles.\n", result); + debugPrintf("Note: Game state has %d open file handles.\n", result); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out = saveFileMan->openForSaving(argv[1]); const char *version = ""; if (!out) { - DebugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]); + debugPrintf("Error opening savegame \"%s\" for writing\n", argv[1]); return true; } // TODO: enable custom descriptions? force filename into a specific format? if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) { - DebugPrintf("Saving the game state to '%s' failed\n", argv[1]); + debugPrintf("Saving the game state to '%s' failed\n", argv[1]); } else { out->finalize(); if (out->err()) { @@ -1189,8 +1192,8 @@ bool Console::cmdSaveGame(int argc, const char **argv) { bool Console::cmdRestoreGame(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Restores a saved game from the hard disk\n"); - DebugPrintf("Usage: %s <filename>\n", argv[0]); + debugPrintf("Restores a saved game from the hard disk\n"); + debugPrintf("Usage: %s <filename>\n", argv[0]); return true; } @@ -1203,17 +1206,17 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { } if (_engine->_gamestate->r_acc == make_reg(0, 1)) { - DebugPrintf("Restoring gamestate '%s' failed.\n", argv[1]); + debugPrintf("Restoring gamestate '%s' failed.\n", argv[1]); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdRestartGame(int argc, const char **argv) { _engine->_gamestate->abortScriptProcessing = kAbortRestartGame; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } // The scripts get IDs ranging from 100->199, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN @@ -1231,25 +1234,25 @@ bool Console::cmdListSaves(int argc, const char **argv) { for (uint i = 0; i < saves.size(); i++) { Common::String filename = g_sci->getSavegameName(saves[i].id); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); + debugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); } return true; } bool Console::cmdClassTable(int argc, const char **argv) { - DebugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n"); + debugPrintf("Available classes (parse a parameter to filter the table by a specific class):\n"); for (uint i = 0; i < _engine->_gamestate->_segMan->classTableSize(); i++) { Class temp = _engine->_gamestate->_segMan->_classTable[i]; if (temp.reg.getSegment()) { const char *className = _engine->_gamestate->_segMan->getObjectName(temp.reg); if (argc == 1 || (argc == 2 && !strcmp(className, argv[1]))) { - DebugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i, + debugPrintf(" Class 0x%x (%s) at %04x:%04x (script %d)\n", i, className, PRINT_REG(temp.reg), temp.script); - } else DebugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script); + } else debugPrintf(" Class 0x%x (not loaded; can't get name) (script %d)\n", i, temp.script); } } @@ -1257,52 +1260,52 @@ bool Console::cmdClassTable(int argc, const char **argv) { } bool Console::cmdSentenceFragments(int argc, const char **argv) { - DebugPrintf("Sentence fragments (used to build Parse trees)\n"); + debugPrintf("Sentence fragments (used to build Parse trees)\n"); for (uint i = 0; i < _engine->getVocabulary()->getParserBranchesSize(); i++) { int j = 0; const parse_tree_branch_t &branch = _engine->getVocabulary()->getParseTreeBranch(i); - DebugPrintf("R%02d: [%x] ->", i, branch.id); + debugPrintf("R%02d: [%x] ->", i, branch.id); while ((j < 10) && branch.data[j]) { int dat = branch.data[j++]; switch (dat) { case VOCAB_TREE_NODE_COMPARE_TYPE: dat = branch.data[j++]; - DebugPrintf(" C(%x)", dat); + debugPrintf(" C(%x)", dat); break; case VOCAB_TREE_NODE_COMPARE_GROUP: dat = branch.data[j++]; - DebugPrintf(" WG(%x)", dat); + debugPrintf(" WG(%x)", dat); break; case VOCAB_TREE_NODE_FORCE_STORAGE: dat = branch.data[j++]; - DebugPrintf(" FORCE(%x)", dat); + debugPrintf(" FORCE(%x)", dat); break; default: if (dat > VOCAB_TREE_NODE_LAST_WORD_STORAGE) { int dat2 = branch.data[j++]; - DebugPrintf(" %x[%x]", dat, dat2); + debugPrintf(" %x[%x]", dat, dat2); } else - DebugPrintf(" ?%x?", dat); + debugPrintf(" ?%x?", dat); } } - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize()); + debugPrintf("%d rules.\n", _engine->getVocabulary()->getParserBranchesSize()); return true; } bool Console::cmdParse(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n"); - DebugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]); + debugPrintf("Parses a sequence of words with a GNF rule set and prints the resulting parse tree\n"); + debugPrintf("Usage: %s <word1> <word2> ... <wordn>\n", argv[0]); return true; } @@ -1316,7 +1319,7 @@ bool Console::cmdParse(int argc, const char **argv) { strcat(string, argv[i]); } - DebugPrintf("Parsing '%s'\n", string); + debugPrintf("Parsing '%s'\n", string); ResultWordListList words; bool res = _engine->getVocabulary()->tokenizeString(words, string, &error); @@ -1325,26 +1328,26 @@ bool Console::cmdParse(int argc, const char **argv) { _engine->getVocabulary()->synonymizeTokens(words); - DebugPrintf("Parsed to the following blocks:\n"); + debugPrintf("Parsed to the following blocks:\n"); for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) { - DebugPrintf(" "); + debugPrintf(" "); for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) { - DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); + debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); } - DebugPrintf("\n"); + debugPrintf("\n"); } if (_engine->getVocabulary()->parseGNF(words, true)) syntax_fail = 1; // Building a tree failed if (syntax_fail) - DebugPrintf("Building a tree failed.\n"); + debugPrintf("Building a tree failed.\n"); else _engine->getVocabulary()->dumpParseTree(); } else { - DebugPrintf("Unknown word: '%s'\n", error); + debugPrintf("Unknown word: '%s'\n", error); free(error); } @@ -1353,10 +1356,10 @@ bool Console::cmdParse(int argc, const char **argv) { bool Console::cmdSaid(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Matches a string against a said spec\n"); - DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); - DebugPrintf("<string> is a sequence of actual words.\n"); - DebugPrintf("<said spec> is a sequence of hex tokens.\n"); + debugPrintf("Matches a string against a said spec\n"); + debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); + debugPrintf("<string> is a sequence of actual words.\n"); + debugPrintf("<said spec> is a sequence of hex tokens.\n"); return true; } @@ -1373,10 +1376,10 @@ bool Console::cmdSaid(int argc, const char **argv) { } if (p >= argc-1) { - DebugPrintf("Matches a string against a said spec\n"); - DebugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); - DebugPrintf("<string> is a sequence of actual words.\n"); - DebugPrintf("<said spec> is a sequence of hex tokens.\n"); + debugPrintf("Matches a string against a said spec\n"); + debugPrintf("Usage: %s <string> > & <said spec>\n", argv[0]); + debugPrintf("<string> is a sequence of actual words.\n"); + debugPrintf("<said spec> is a sequence of hex tokens.\n"); return true; } @@ -1440,14 +1443,14 @@ bool Console::cmdSaid(int argc, const char **argv) { _engine->getVocabulary()->synonymizeTokens(words); - DebugPrintf("Parsed to the following blocks:\n"); + debugPrintf("Parsed to the following blocks:\n"); for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) { - DebugPrintf(" "); + debugPrintf(" "); for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) { - DebugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); + debugPrintf("%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group); } - DebugPrintf("\n"); + debugPrintf("\n"); } @@ -1456,17 +1459,17 @@ bool Console::cmdSaid(int argc, const char **argv) { syntax_fail = 1; // Building a tree failed if (syntax_fail) - DebugPrintf("Building a tree failed.\n"); + debugPrintf("Building a tree failed.\n"); else { _engine->getVocabulary()->dumpParseTree(); _engine->getVocabulary()->parserIsValid = true; int ret = said((byte *)spec, true); - DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match")); + debugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match")); } } else { - DebugPrintf("Unknown word: '%s'\n", error); + debugPrintf("Unknown word: '%s'\n", error); free(error); } @@ -1476,9 +1479,9 @@ bool Console::cmdSaid(int argc, const char **argv) { bool Console::cmdParserNodes(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows the specified number of nodes from the parse node tree\n"); - DebugPrintf("Usage: %s <nr>\n", argv[0]); - DebugPrintf("where <nr> is the number of nodes to show from the parse node tree\n"); + debugPrintf("Shows the specified number of nodes from the parse node tree\n"); + debugPrintf("Usage: %s <nr>\n", argv[0]); + debugPrintf("where <nr> is the number of nodes to show from the parse node tree\n"); return true; } @@ -1491,9 +1494,9 @@ bool Console::cmdParserNodes(int argc, const char **argv) { bool Console::cmdSetPalette(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Sets a palette resource\n"); - DebugPrintf("Usage: %s <resourceId>\n", argv[0]); - DebugPrintf("where <resourceId> is the number of the palette resource to set\n"); + debugPrintf("Sets a palette resource\n"); + debugPrintf("Usage: %s <resourceId>\n", argv[0]); + debugPrintf("where <resourceId> is the number of the palette resource to set\n"); return true; } @@ -1505,9 +1508,9 @@ bool Console::cmdSetPalette(int argc, const char **argv) { bool Console::cmdDrawPic(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Draws a pic resource\n"); - DebugPrintf("Usage: %s <resourceId>\n", argv[0]); - DebugPrintf("where <resourceId> is the number of the pic resource to draw\n"); + debugPrintf("Draws a pic resource\n"); + debugPrintf("Usage: %s <resourceId>\n", argv[0]); + debugPrintf("where <resourceId> is the number of the pic resource to draw\n"); return true; } @@ -1532,9 +1535,9 @@ bool Console::cmdDrawPic(int argc, const char **argv) { bool Console::cmdDrawCel(int argc, const char **argv) { if (argc < 4) { - DebugPrintf("Draws a cel from a view resource\n"); - DebugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]); - DebugPrintf("where <resourceId> is the number of the view resource to draw\n"); + debugPrintf("Draws a cel from a view resource\n"); + debugPrintf("Usage: %s <resourceId> <loopNr> <celNr> \n", argv[0]); + debugPrintf("where <resourceId> is the number of the view resource to draw\n"); return true; } @@ -1555,24 +1558,24 @@ bool Console::cmdDrawCel(int argc, const char **argv) { bool Console::cmdUndither(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Enable/disable undithering.\n"); - DebugPrintf("Usage: %s <0/1>\n", argv[0]); + debugPrintf("Enable/disable undithering.\n"); + debugPrintf("Usage: %s <0/1>\n", argv[0]); return true; } bool flag = atoi(argv[1]) ? true : false; _engine->_gfxScreen->enableUndithering(flag); if (flag) - DebugPrintf("undithering ENABLED\n"); + debugPrintf("undithering ENABLED\n"); else - DebugPrintf("undithering DISABLED\n"); + debugPrintf("undithering DISABLED\n"); return true; } bool Console::cmdPicVisualize(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Enable/disable picture visualization (EGA only)\n"); - DebugPrintf("Usage: %s <0/1>\n", argv[0]); + debugPrintf("Enable/disable picture visualization (EGA only)\n"); + debugPrintf("Usage: %s <0/1>\n", argv[0]); return true; } @@ -1581,21 +1584,21 @@ bool Console::cmdPicVisualize(int argc, const char **argv) { if (_engine->_resMan->getViewType() == kViewEga) { _engine->_gfxPaint16->debugSetEGAdrawingVisualize(state); if (state) - DebugPrintf("picture visualization ENABLED\n"); + debugPrintf("picture visualization ENABLED\n"); else - DebugPrintf("picture visualization DISABLED\n"); + debugPrintf("picture visualization DISABLED\n"); } else { - DebugPrintf("picture visualization only available for EGA games\n"); + debugPrintf("picture visualization only available for EGA games\n"); } return true; } bool Console::cmdPlayVideo(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n"); - DebugPrintf("Usage: %s <video file name> <delay>\n", argv[0]); - DebugPrintf("The video file name should include the extension\n"); - DebugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n"); + debugPrintf("Plays a SEQ, AVI, VMD, RBT or DUK video.\n"); + debugPrintf("Usage: %s <video file name> <delay>\n", argv[0]); + debugPrintf("The video file name should include the extension\n"); + debugPrintf("Delay is only used in SEQ videos and is measured in ticks (default: 10)\n"); return true; } @@ -1606,29 +1609,29 @@ bool Console::cmdPlayVideo(int argc, const char **argv) { filename.hasSuffix(".rbt") || filename.hasSuffix(".duk")) { _videoFile = filename; _videoFrameDelay = (argc == 2) ? 10 : atoi(argv[2]); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } else { - DebugPrintf("Unknown video file type\n"); + debugPrintf("Unknown video file type\n"); return true; } } bool Console::cmdAnimateList(int argc, const char **argv) { if (_engine->_gfxAnimate) { - DebugPrintf("Animate list:\n"); + debugPrintf("Animate list:\n"); _engine->_gfxAnimate->printAnimateList(this); } else { - DebugPrintf("This SCI version does not have an animate list\n"); + debugPrintf("This SCI version does not have an animate list\n"); } return true; } bool Console::cmdWindowList(int argc, const char **argv) { if (_engine->_gfxPorts) { - DebugPrintf("Window list:\n"); + debugPrintf("Window list:\n"); _engine->_gfxPorts->printWindowList(this); } else { - DebugPrintf("This SCI version does not have a list of ports\n"); + debugPrintf("This SCI version does not have a list of ports\n"); } return true; } @@ -1636,41 +1639,41 @@ bool Console::cmdWindowList(int argc, const char **argv) { bool Console::cmdPlaneList(int argc, const char **argv) { #ifdef ENABLE_SCI32 if (_engine->_gfxFrameout) { - DebugPrintf("Plane list:\n"); + debugPrintf("Plane list:\n"); _engine->_gfxFrameout->printPlaneList(this); } else { - DebugPrintf("This SCI version does not have a list of planes\n"); + debugPrintf("This SCI version does not have a list of planes\n"); } #else - DebugPrintf("SCI32 isn't included in this compiled executable\n"); + debugPrintf("SCI32 isn't included in this compiled executable\n"); #endif return true; } bool Console::cmdPlaneItemList(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows the list of items for a plane\n"); - DebugPrintf("Usage: %s <plane address>\n", argv[0]); + debugPrintf("Shows the list of items for a plane\n"); + debugPrintf("Usage: %s <plane address>\n", argv[0]); return true; } reg_t planeObject = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], &planeObject, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } #ifdef ENABLE_SCI32 if (_engine->_gfxFrameout) { - DebugPrintf("Plane item list:\n"); + debugPrintf("Plane item list:\n"); _engine->_gfxFrameout->printPlaneItemList(this, planeObject); } else { - DebugPrintf("This SCI version does not have a list of plane items\n"); + debugPrintf("This SCI version does not have a list of plane items\n"); } #else - DebugPrintf("SCI32 isn't included in this compiled executable\n"); + debugPrintf("SCI32 isn't included in this compiled executable\n"); #endif return true; } @@ -1680,7 +1683,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id); if (!hunks) { - DebugPrintf("No hunk segment found.\n"); + debugPrintf("No hunk segment found.\n"); return true; } @@ -1693,7 +1696,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) { byte* memoryPtr = (byte *)h.mem; if (memoryPtr) { - DebugPrintf("%04x:%04x:", PRINT_REG(entries[i])); + debugPrintf("%04x:%04x:", PRINT_REG(entries[i])); Common::Rect rect; byte mask; @@ -1702,17 +1705,17 @@ bool Console::cmdSavedBits(int argc, const char **argv) { memcpy((void *)&rect, memoryPtr, sizeof(rect)); memcpy((void *)&mask, memoryPtr + sizeof(rect), sizeof(mask)); - DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + debugPrintf(" %d,%d - %d,%d", rect.top, rect.left, rect.bottom, rect.right); if (mask & GFX_SCREEN_MASK_VISUAL) - DebugPrintf(" visual"); + debugPrintf(" visual"); if (mask & GFX_SCREEN_MASK_PRIORITY) - DebugPrintf(" priority"); + debugPrintf(" priority"); if (mask & GFX_SCREEN_MASK_CONTROL) - DebugPrintf(" control"); + debugPrintf(" control"); if (mask & GFX_SCREEN_MASK_DISPLAY) - DebugPrintf(" display"); - DebugPrintf("\n"); + debugPrintf(" display"); + debugPrintf("\n"); } } } @@ -1723,22 +1726,22 @@ bool Console::cmdSavedBits(int argc, const char **argv) { bool Console::cmdShowSavedBits(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Display saved bits.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Display saved bits.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t memoryHandle = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], &memoryHandle, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } if (memoryHandle.isNull()) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } @@ -1746,26 +1749,26 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK); HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id); if (!hunks) { - DebugPrintf("No hunk segment found.\n"); + debugPrintf("No hunk segment found.\n"); return true; } if (memoryHandle.getSegment() != id || !hunks->isValidOffset(memoryHandle.getOffset())) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } const Hunk& h = hunks->_table[memoryHandle.getOffset()]; if (strcmp(h.type, "SaveBits()") != 0) { - DebugPrintf("Invalid address.\n"); + debugPrintf("Invalid address.\n"); return true; } byte *memoryPtr = segman->getHunkPointer(memoryHandle); if (!memoryPtr) { - DebugPrintf("Invalid or freed bits.\n"); + debugPrintf("Invalid or freed bits.\n"); return true; } @@ -1783,17 +1786,17 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { Common::Point bl(rect.left, rect.bottom-1); Common::Point br(rect.right-1, rect.bottom-1); - DebugPrintf(" %d,%d - %d,%d", rect.top, rect.left, + debugPrintf(" %d,%d - %d,%d", rect.top, rect.left, rect.bottom, rect.right); if (mask & GFX_SCREEN_MASK_VISUAL) - DebugPrintf(" visual"); + debugPrintf(" visual"); if (mask & GFX_SCREEN_MASK_PRIORITY) - DebugPrintf(" priority"); + debugPrintf(" priority"); if (mask & GFX_SCREEN_MASK_CONTROL) - DebugPrintf(" control"); + debugPrintf(" control"); if (mask & GFX_SCREEN_MASK_DISPLAY) - DebugPrintf(" display"); - DebugPrintf("\n"); + debugPrintf(" display"); + debugPrintf("\n"); if (!_engine->_gfxPaint16 || !_engine->_gfxScreen) return true; @@ -1843,7 +1846,7 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) { bool Console::cmdParseGrammar(int argc, const char **argv) { - DebugPrintf("Parse grammar, in strict GNF:\n"); + debugPrintf("Parse grammar, in strict GNF:\n"); _engine->getVocabulary()->buildGNF(true); @@ -1851,71 +1854,71 @@ bool Console::cmdParseGrammar(int argc, const char **argv) { } bool Console::cmdPrintSegmentTable(int argc, const char **argv) { - DebugPrintf("Segment table:\n"); + debugPrintf("Segment table:\n"); for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++) { SegmentObj *mobj = _engine->_gamestate->_segMan->_heap[i]; if (mobj && mobj->getType()) { - DebugPrintf(" [%04x] ", i); + debugPrintf(" [%04x] ", i); switch (mobj->getType()) { case SEG_TYPE_SCRIPT: - DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); + debugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); break; case SEG_TYPE_CLONES: - DebugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used); + debugPrintf("C clones (%d allocd)", (*(CloneTable *)mobj).entries_used); break; case SEG_TYPE_LOCALS: - DebugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id); + debugPrintf("V locals %03d", (*(LocalVariables *)mobj).script_id); break; case SEG_TYPE_STACK: - DebugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity); + debugPrintf("D data stack (%d)", (*(DataStack *)mobj)._capacity); break; case SEG_TYPE_LISTS: - DebugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used); + debugPrintf("L lists (%d)", (*(ListTable *)mobj).entries_used); break; case SEG_TYPE_NODES: - DebugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used); + debugPrintf("N nodes (%d)", (*(NodeTable *)mobj).entries_used); break; case SEG_TYPE_HUNK: - DebugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used); + debugPrintf("H hunk (%d)", (*(HunkTable *)mobj).entries_used); break; case SEG_TYPE_DYNMEM: - DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); + debugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); break; #ifdef ENABLE_SCI32 case SEG_TYPE_ARRAY: - DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); + debugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); break; case SEG_TYPE_STRING: - DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); + debugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); break; #endif default: - DebugPrintf("I Invalid (type = %x)", mobj->getType()); + debugPrintf("I Invalid (type = %x)", mobj->getType()); break; } - DebugPrintf(" \n"); + debugPrintf(" \n"); } } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::segmentInfo(int nr) { - DebugPrintf("[%04x] ", nr); + debugPrintf("[%04x] ", nr); if ((nr < 0) || ((uint)nr >= _engine->_gamestate->_segMan->_heap.size()) || !_engine->_gamestate->_segMan->_heap[nr]) return false; @@ -1926,30 +1929,30 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_SCRIPT: { Script *scr = (Script *)mobj; - DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); + debugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); if (scr->getExportTable()) - DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); + debugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); else - DebugPrintf(" Exports: none\n"); + debugPrintf(" Exports: none\n"); - DebugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr()); + debugPrintf(" Synonyms: %4d\n", scr->getSynonymsNr()); if (scr->getLocalsCount() > 0) - DebugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment()); + debugPrintf(" Locals : %4d in segment 0x%x\n", scr->getLocalsCount(), scr->getLocalsSegment()); else - DebugPrintf(" Locals : none\n"); + debugPrintf(" Locals : none\n"); ObjMap objects = scr->getObjectMap(); - DebugPrintf(" Objects: %4d\n", objects.size()); + debugPrintf(" Objects: %4d\n", objects.size()); ObjMap::iterator it; const ObjMap::iterator end = objects.end(); for (it = objects.begin(); it != end; ++it) { - DebugPrintf(" "); + debugPrintf(" "); // Object header const Object *obj = _engine->_gamestate->_segMan->getObject(it->_value.getPos()); if (obj) - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(it->_value.getPos()), _engine->_gamestate->_segMan->getObjectName(it->_value.getPos()), obj->getVarCount(), obj->getMethodCount()); } @@ -1958,31 +1961,31 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_LOCALS: { LocalVariables *locals = (LocalVariables *)mobj; - DebugPrintf("locals for script.%03d\n", locals->script_id); - DebugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size()); + debugPrintf("locals for script.%03d\n", locals->script_id); + debugPrintf(" %d (0x%x) locals\n", locals->_locals.size(), locals->_locals.size()); } break; case SEG_TYPE_STACK: { DataStack *stack = (DataStack *)mobj; - DebugPrintf("stack\n"); - DebugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity); + debugPrintf("stack\n"); + debugPrintf(" %d (0x%x) entries\n", stack->_capacity, stack->_capacity); } break; case SEG_TYPE_CLONES: { CloneTable *ct = (CloneTable *)mobj; - DebugPrintf("clones\n"); + debugPrintf("clones\n"); for (uint i = 0; i < ct->_table.size(); i++) if (ct->isValidEntry(i)) { reg_t objpos = make_reg(nr, i); - DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); + debugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); // Object header const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos()); if (obj) - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].getPos()), _engine->_gamestate->_segMan->getObjectName(ct->_table[i].getPos()), obj->getVarCount(), obj->getMethodCount()); } @@ -1992,34 +1995,34 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_LISTS: { ListTable *lt = (ListTable *)mobj; - DebugPrintf("lists\n"); + debugPrintf("lists\n"); for (uint i = 0; i < lt->_table.size(); i++) if (lt->isValidEntry(i)) { - DebugPrintf(" [%04x]: ", i); + debugPrintf(" [%04x]: ", i); printList(&(lt->_table[i])); } } break; case SEG_TYPE_NODES: { - DebugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used); + debugPrintf("nodes (total %d)\n", (*(NodeTable *)mobj).entries_used); break; } case SEG_TYPE_HUNK: { HunkTable *ht = (HunkTable *)mobj; - DebugPrintf("hunk (total %d)\n", ht->entries_used); + debugPrintf("hunk (total %d)\n", ht->entries_used); for (uint i = 0; i < ht->_table.size(); i++) if (ht->isValidEntry(i)) { - DebugPrintf(" [%04x] %d bytes at %p, type=%s\n", + debugPrintf(" [%04x] %d bytes at %p, type=%s\n", i, ht->_table[i].size, ht->_table[i].mem, ht->_table[i].type); } } break; case SEG_TYPE_DYNMEM: { - DebugPrintf("dynmem (%s): %d bytes\n", + debugPrintf("dynmem (%s): %d bytes\n", (*(DynMem *)mobj)._description.c_str(), (*(DynMem *)mobj)._size); Common::hexdump((*(DynMem *)mobj)._buf, (*(DynMem *)mobj)._size, 16, 0); @@ -2028,28 +2031,28 @@ bool Console::segmentInfo(int nr) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: - DebugPrintf("SCI32 strings\n"); + debugPrintf("SCI32 strings\n"); break; case SEG_TYPE_ARRAY: - DebugPrintf("SCI32 arrays\n"); + debugPrintf("SCI32 arrays\n"); break; #endif default : - DebugPrintf("Invalid type %d\n", mobj->getType()); + debugPrintf("Invalid type %d\n", mobj->getType()); break; } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool Console::cmdSegmentInfo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Provides information on the specified segment(s)\n"); - DebugPrintf("Usage: %s <segment number>\n", argv[0]); - DebugPrintf("<segment number> can be a number, which shows the information of the segment with\n"); - DebugPrintf("the specified number, or \"all\" to show information on all active segments\n"); + debugPrintf("Provides information on the specified segment(s)\n"); + debugPrintf("Usage: %s <segment number>\n", argv[0]); + debugPrintf("<segment number> can be a number, which shows the information of the segment with\n"); + debugPrintf("the specified number, or \"all\" to show information on all active segments\n"); return true; } @@ -2061,7 +2064,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { if (!parseInteger(argv[1], segmentNr)) return true; if (!segmentInfo(segmentNr)) - DebugPrintf("Segment %04xh does not exist\n", segmentNr); + debugPrintf("Segment %04xh does not exist\n", segmentNr); } return true; @@ -2070,8 +2073,8 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { bool Console::cmdKillSegment(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Deletes the specified segment\n"); - DebugPrintf("Usage: %s <segment number>\n", argv[0]); + debugPrintf("Deletes the specified segment\n"); + debugPrintf("Usage: %s <segment number>\n", argv[0]); return true; } int segmentNumber; @@ -2084,13 +2087,13 @@ bool Console::cmdKillSegment(int argc, const char **argv) { bool Console::cmdShowMap(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Switches to one of the following screen maps\n"); - DebugPrintf("Usage: %s <screen map>\n", argv[0]); - DebugPrintf("Screen maps:\n"); - DebugPrintf("- 0: visual map\n"); - DebugPrintf("- 1: priority map\n"); - DebugPrintf("- 2: control map\n"); - DebugPrintf("- 3: display screen\n"); + debugPrintf("Switches to one of the following screen maps\n"); + debugPrintf("Usage: %s <screen map>\n", argv[0]); + debugPrintf("Screen maps:\n"); + debugPrintf("- 0: visual map\n"); + debugPrintf("- 1: priority map\n"); + debugPrintf("- 2: control map\n"); + debugPrintf("- 3: display screen\n"); return true; } @@ -2105,14 +2108,14 @@ bool Console::cmdShowMap(int argc, const char **argv) { break; default: - DebugPrintf("Map %d is not available.\n", map); + debugPrintf("Map %d is not available.\n", map); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdSongLib(int argc, const char **argv) { - DebugPrintf("Song library:\n"); + debugPrintf("Song library:\n"); g_sci->_soundCmd->printPlayList(this); return true; @@ -2120,16 +2123,16 @@ bool Console::cmdSongLib(int argc, const char **argv) { bool Console::cmdSongInfo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows information about a given song in the playlist\n"); - DebugPrintf("Usage: %s <song object>\n", argv[0]); + debugPrintf("Shows information about a given song in the playlist\n"); + debugPrintf("Usage: %s <song object>\n", argv[0]); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2140,38 +2143,38 @@ bool Console::cmdSongInfo(int argc, const char **argv) { bool Console::cmdStartSound(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n"); - DebugPrintf("Usage: %s <sound resource id>\n", argv[0]); + debugPrintf("Adds the requested sound resource to the playlist, and starts playing it\n"); + debugPrintf("Usage: %s <sound resource id>\n", argv[0]); return true; } int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { - DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); + debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); return true; } g_sci->_soundCmd->startNewSound(number); - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdToggleSound(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Plays or stops the specified sound in the playlist\n"); - DebugPrintf("Usage: %s <address> <state>\n", argv[0]); - DebugPrintf("Where:\n"); - DebugPrintf("- <address> is the address of the sound to play or stop.\n"); - DebugPrintf("- <state> is the new state (play or stop).\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Plays or stops the specified sound in the playlist\n"); + debugPrintf("Usage: %s <address> <state>\n", argv[0]); + debugPrintf("Where:\n"); + debugPrintf("- <address> is the address of the sound to play or stop.\n"); + debugPrintf("- <state> is the new state (play or stop).\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t id; if (parse_reg_t(_engine->_gamestate, argv[1], &id, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2183,7 +2186,7 @@ bool Console::cmdToggleSound(int argc, const char **argv) { else if (newState == "stop") g_sci->_soundCmd->processStopSound(id, false); else - DebugPrintf("New state can either be 'play' or 'stop'"); + debugPrintf("New state can either be 'play' or 'stop'"); return true; } @@ -2191,40 +2194,40 @@ bool Console::cmdToggleSound(int argc, const char **argv) { bool Console::cmdStopAllSounds(int argc, const char **argv) { g_sci->_soundCmd->stopAllSounds(); - DebugPrintf("All sounds have been stopped\n"); + debugPrintf("All sounds have been stopped\n"); return true; } bool Console::cmdIsSample(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Tests whether a given sound resource is a PCM sample, \n"); - DebugPrintf("and displays information on it if it is.\n"); - DebugPrintf("Usage: %s <sample id>\n", argv[0]); + debugPrintf("Tests whether a given sound resource is a PCM sample, \n"); + debugPrintf("and displays information on it if it is.\n"); + debugPrintf("Usage: %s <sample id>\n", argv[0]); return true; } int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { - DebugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); + debugPrintf("Unable to load this sound resource, most probably it has an equivalent audio resource (SCI1.1)\n"); return true; } SoundResource *soundRes = new SoundResource(number, _engine->getResMan(), _engine->_features->detectDoSoundType()); if (!soundRes) { - DebugPrintf("Not a sound resource!\n"); + debugPrintf("Not a sound resource!\n"); return true; } SoundResource::Track *track = soundRes->getDigitalTrack(); if (!track || track->digitalChannelNr == -1) { - DebugPrintf("Valid song, but not a sample.\n"); + debugPrintf("Valid song, but not a sample.\n"); delete soundRes; return true; } - DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", + debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); delete soundRes; @@ -2232,7 +2235,7 @@ bool Console::cmdIsSample(int argc, const char **argv) { } bool Console::cmdGCInvoke(int argc, const char **argv) { - DebugPrintf("Performing garbage collection...\n"); + debugPrintf("Performing garbage collection...\n"); run_gc(_engine->_gamestate); return true; } @@ -2240,9 +2243,9 @@ bool Console::cmdGCInvoke(int argc, const char **argv) { bool Console::cmdGCObjects(int argc, const char **argv) { AddrSet *use_map = findAllActiveReferences(_engine->_gamestate); - DebugPrintf("Reachable object references (normalised):\n"); + debugPrintf("Reachable object references (normalised):\n"); for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) { - DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); + debugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); } delete use_map; @@ -2252,93 +2255,93 @@ bool Console::cmdGCObjects(int argc, const char **argv) { bool Console::cmdGCShowReachable(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return 1; } - DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); + debugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); const Common::Array<reg_t> tmp = mobj->listAllOutgoingReferences(addr); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) if (it->getSegment()) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); + g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } bool Console::cmdGCShowFreeable(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints all addresses freeable in the segment associated with the\n"); - DebugPrintf("given address (offset is ignored).\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints all addresses freeable in the segment associated with the\n"); + debugPrintf("given address (offset is ignored).\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } - DebugPrintf("Freeable in segment %04x:\n", addr.getSegment()); + debugPrintf("Freeable in segment %04x:\n", addr.getSegment()); const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(addr.getSegment()); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) if (it->getSegment()) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); + g_sci->getSciDebugger()->debugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } bool Console::cmdGCNormalize(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Prints the \"normal\" address of a given address,\n"); - DebugPrintf("i.e. the address we would free in order to free\n"); - DebugPrintf("the object associated with the original address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Prints the \"normal\" address of a given address,\n"); + debugPrintf("i.e. the address we would free in order to free\n"); + debugPrintf("the object associated with the original address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } SegmentObj *mobj = _engine->_gamestate->_segMan->getSegmentObj(addr.getSegment()); if (!mobj) { - DebugPrintf("Unknown segment : %x\n", addr.getSegment()); + debugPrintf("Unknown segment : %x\n", addr.getSegment()); return true; } addr = mobj->findCanonicAddress(_engine->_gamestate->_segMan, addr); - DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); + debugPrintf(" %04x:%04x\n", PRINT_REG(addr)); return true; } @@ -2347,12 +2350,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { EngineState *s = _engine->_gamestate; const char *varnames[] = {"global", "local", "temp", "param"}; - DebugPrintf("Addresses of variables in the VM:\n"); + debugPrintf("Addresses of variables in the VM:\n"); for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); - DebugPrintf(" total %d", s->variablesMax[i]); - DebugPrintf("\n"); + debugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); + debugPrintf(" total %d", s->variablesMax[i]); + debugPrintf("\n"); } return true; @@ -2360,12 +2363,12 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { bool Console::cmdVMVars(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Displays or changes variables in the VM\n"); - DebugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]); - DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); - DebugPrintf("Second parameter is the var number (not specified on acc)\n"); - DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Displays or changes variables in the VM\n"); + debugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]); + debugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); + debugPrintf("Second parameter is the var number (not specified on acc)\n"); + debugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2379,7 +2382,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { const char *setValue = NULL; if (!varType_pre) { - DebugPrintf("Invalid variable type '%c'\n", *argv[1]); + debugPrintf("Invalid variable type '%c'\n", *argv[1]); return true; } @@ -2392,11 +2395,11 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 3: { // for global, local, temp and param, we need an index if (argc < 3) { - DebugPrintf("Variable number must be specified for requested type\n"); + debugPrintf("Variable number must be specified for requested type\n"); return true; } if (argc > 4) { - DebugPrintf("Too many arguments\n"); + debugPrintf("Too many arguments\n"); return true; } @@ -2404,12 +2407,12 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; if (varIndex < 0) { - DebugPrintf("Variable number may not be negative\n"); + debugPrintf("Variable number may not be negative\n"); return true; } if (s->variablesMax[varType] <= varIndex) { - DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); + debugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); return true; } curValue = &s->variables[varType][varIndex]; @@ -2421,7 +2424,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { case 4: // acc if (argc > 3) { - DebugPrintf("Too many arguments\n"); + debugPrintf("Too many arguments\n"); return true; } curValue = &s->r_acc; @@ -2435,16 +2438,16 @@ bool Console::cmdVMVars(int argc, const char **argv) { if (!setValue) { if (varType == 4) - DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); + debugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); else - DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); + debugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); printBasicVarInfo(*curValue); - DebugPrintf("\n"); + debugPrintf("\n"); } else { if (parse_reg_t(s, setValue, curValue, true)) { - DebugPrintf("Invalid value/address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); + debugPrintf("Invalid value/address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); return true; } } @@ -2453,13 +2456,13 @@ bool Console::cmdVMVars(int argc, const char **argv) { bool Console::cmdStack(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Lists the specified number of stack elements.\n"); - DebugPrintf("Usage: %s <elements>\n", argv[0]); + debugPrintf("Lists the specified number of stack elements.\n"); + debugPrintf("Usage: %s <elements>\n", argv[0]); return true; } if (_engine->_gamestate->_executionStack.empty()) { - DebugPrintf("No exec stack!"); + debugPrintf("No exec stack!"); return true; } @@ -2468,9 +2471,9 @@ bool Console::cmdStack(int argc, const char **argv) { for (int i = nr; i > 0; i--) { if ((xs.sp - xs.fp - i) == 0) - DebugPrintf("-- temp variables --\n"); + debugPrintf("-- temp variables --\n"); if (xs.sp - i >= _engine->_gamestate->stack_base) - DebugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i])); + debugPrintf("ST:%04x = %04x:%04x\n", (unsigned)(xs.sp - i - _engine->_gamestate->stack_base), PRINT_REG(xs.sp[-i])); } return true; @@ -2478,19 +2481,19 @@ bool Console::cmdStack(int argc, const char **argv) { bool Console::cmdValueType(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Determines the type of a value.\n"); - DebugPrintf("The type can be one of the following:\n"); - DebugPrintf("Invalid, list, object, reference or arithmetic\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Determines the type of a value.\n"); + debugPrintf("The type can be one of the following:\n"); + debugPrintf("Invalid, list, object, reference or arithmetic\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t val; if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2498,22 +2501,22 @@ bool Console::cmdValueType(int argc, const char **argv) { switch (t) { case SIG_TYPE_LIST: - DebugPrintf("List"); + debugPrintf("List"); break; case SIG_TYPE_OBJECT: - DebugPrintf("Object"); + debugPrintf("Object"); break; case SIG_TYPE_REFERENCE: - DebugPrintf("Reference"); + debugPrintf("Reference"); break; case SIG_TYPE_INTEGER: - DebugPrintf("Integer"); + debugPrintf("Integer"); break; case SIG_TYPE_INTEGER | SIG_TYPE_NULL: - DebugPrintf("Null"); + debugPrintf("Null"); break; default: - DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); + debugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); } return true; @@ -2521,17 +2524,17 @@ bool Console::cmdValueType(int argc, const char **argv) { bool Console::cmdViewListNode(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines the list node at the given address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines the list node at the given address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2541,11 +2544,11 @@ bool Console::cmdViewListNode(int argc, const char **argv) { bool Console::cmdViewReference(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Examines an arbitrary reference.\n"); - DebugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]); - DebugPrintf("Where <start address> is the starting address to examine\n"); - DebugPrintf("<end address>, if provided, is the address where examining ends at\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines an arbitrary reference.\n"); + debugPrintf("Usage: %s <start address> [<end address>]\n", argv[0]); + debugPrintf("Where <start address> is the starting address to examine\n"); + debugPrintf("<end address>, if provided, is the address where examining ends at\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2553,15 +2556,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { reg_t reg_end = NULL_REG; if (parse_reg_t(_engine->_gamestate, argv[1], ®, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } if (argc > 2) { if (parse_reg_t(_engine->_gamestate, argv[2], ®_end, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } } @@ -2570,15 +2573,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { int filter; int found = 0; - DebugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); + debugPrintf("%04x:%04x is of type 0x%x: ", PRINT_REG(reg), type_mask); if (reg.getSegment() == 0 && reg.getOffset() == 0) { - DebugPrintf("Null.\n"); + debugPrintf("Null.\n"); return true; } if (reg_end.getSegment() != reg.getSegment() && reg_end != NULL_REG) { - DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); + debugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); reg_end = NULL_REG; } @@ -2586,7 +2589,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { int type = type_mask & filter; if (found && type) { - DebugPrintf("--- Alternatively, it could be a "); + debugPrintf("--- Alternatively, it could be a "); } @@ -2596,33 +2599,33 @@ bool Console::cmdViewReference(int argc, const char **argv) { case SIG_TYPE_LIST: { List *list = _engine->_gamestate->_segMan->lookupList(reg); - DebugPrintf("list\n"); + debugPrintf("list\n"); if (list) printList(list); else - DebugPrintf("Invalid list.\n"); + debugPrintf("Invalid list.\n"); } break; case SIG_TYPE_NODE: - DebugPrintf("list node\n"); + debugPrintf("list node\n"); printNode(reg); break; case SIG_TYPE_OBJECT: - DebugPrintf("object\n"); + debugPrintf("object\n"); printObject(reg); break; case SIG_TYPE_REFERENCE: { switch (_engine->_gamestate->_segMan->getSegmentType(reg.getSegment())) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { - DebugPrintf("SCI32 string\n"); + debugPrintf("SCI32 string\n"); const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); break; } case SEG_TYPE_ARRAY: { - DebugPrintf("SCI32 array:\n"); + debugPrintf("SCI32 array:\n"); const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg); hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); break; @@ -2632,10 +2635,10 @@ bool Console::cmdViewReference(int argc, const char **argv) { const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); uint16 size = block.maxSize; - DebugPrintf("raw data\n"); + debugPrintf("raw data\n"); if (reg_end.getSegment() != 0 && (size < reg_end.getOffset() - reg.getOffset())) { - DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + debugPrintf("Block end out of bounds (size %d). Resetting.\n", size); reg_end = NULL_REG; } @@ -2643,7 +2646,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { size = reg_end.getOffset() - reg.getOffset(); if (reg_end.getSegment() != 0) - DebugPrintf("Block size less than or equal to %d\n", size); + debugPrintf("Block size less than or equal to %d\n", size); if (block.isRaw) Common::hexdump(block.raw, size, 16, 0); @@ -2654,14 +2657,14 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; } case SIG_TYPE_INTEGER: - DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); + debugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.getOffset(), reg.getOffset()); break; default: - DebugPrintf("unknown type %d.\n", type); + debugPrintf("unknown type %d.\n", type); } if (type) { - DebugPrintf("\n"); + debugPrintf("\n"); found = 1; } } @@ -2671,47 +2674,47 @@ bool Console::cmdViewReference(int argc, const char **argv) { bool Console::cmdViewObject(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Examines the object at the given address.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Examines the object at the given address.\n"); + debugPrintf("Usage: %s <address>\n", argv[0]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } reg_t addr; if (parse_reg_t(_engine->_gamestate, argv[1], &addr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } - DebugPrintf("Information on the object at the given address:\n"); + debugPrintf("Information on the object at the given address:\n"); printObject(addr); return true; } bool Console::cmdViewActiveObject(int argc, const char **argv) { - DebugPrintf("Information on the currently active object or class:\n"); + debugPrintf("Information on the currently active object or class:\n"); printObject(_engine->_gamestate->xs->objp); return true; } bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { - DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); + debugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); printObject(_engine->_gamestate->r_acc); return true; } bool Console::cmdScriptSteps(int argc, const char **argv) { - DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); + debugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); return true; } bool Console::cmdBacktrace(int argc, const char **argv) { - DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); + debugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List<ExecStack>::const_iterator iter; uint i = 0; @@ -2724,22 +2727,22 @@ bool Console::cmdBacktrace(int argc, const char **argv) { switch (call.type) { case EXEC_STACK_TYPE_CALL: // Normal function if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber()); + debugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.getSegment()]).getScriptNumber()); if (call.debugSelector != -1) { - DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); + debugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); } else if (call.debugExportId != -1) { - DebugPrintf("export %d (", call.debugExportId); + debugPrintf("export %d (", call.debugExportId); } else if (call.debugLocalCallOffset != -1) { - DebugPrintf("call %x (", call.debugLocalCallOffset); + debugPrintf("call %x (", call.debugLocalCallOffset); } break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); + debugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: - DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", + debugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); break; } @@ -2750,32 +2753,32 @@ bool Console::cmdBacktrace(int argc, const char **argv) { totalparamc = 16; for (paramc = 1; paramc <= totalparamc; paramc++) { - DebugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); + debugPrintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); if (paramc < call.argc) - DebugPrintf(", "); + debugPrintf(", "); } if (call.argc > 16) - DebugPrintf("..."); + debugPrintf("..."); - DebugPrintf(")\n "); + debugPrintf(")\n "); if (call.debugOrigin != -1) - DebugPrintf("by %x ", call.debugOrigin); - DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); + debugPrintf("by %x ", call.debugOrigin); + debugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); if (call.type == EXEC_STACK_TYPE_CALL) { - DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); + debugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); if (call.sp == CALL_SP_CARRY) - DebugPrintf(" sp,fp:carry"); + debugPrintf(" sp,fp:carry"); else { - DebugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base)); - DebugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base)); + debugPrintf(" sp=ST:%04x", (unsigned)(call.sp - _engine->_gamestate->stack_base)); + debugPrintf(" fp=ST:%04x", (unsigned)(call.fp - _engine->_gamestate->stack_base)); } } else - DebugPrintf(" pc:none"); + debugPrintf(" pc:none"); - DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); - DebugPrintf("\n"); + debugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); + debugPrintf("\n"); } return true; @@ -2786,7 +2789,7 @@ bool Console::cmdTrace(int argc, const char **argv) { _debugState.runningStep = atoi(argv[1]) - 1; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepOver(int argc, const char **argv) { @@ -2794,14 +2797,14 @@ bool Console::cmdStepOver(int argc, const char **argv) { _debugState.seekLevel = _engine->_gamestate->_executionStack.size(); _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepEvent(int argc, const char **argv) { _debugState.stopOnEvent = true; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepRet(int argc, const char **argv) { @@ -2809,13 +2812,13 @@ bool Console::cmdStepRet(int argc, const char **argv) { _debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepGlobal(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Steps until the global variable with the specified index is modified.\n"); - DebugPrintf("Usage: %s <global variable index>\n", argv[0]); + debugPrintf("Steps until the global variable with the specified index is modified.\n"); + debugPrintf("Usage: %s <global variable index>\n", argv[0]); return true; } @@ -2823,7 +2826,7 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { _debugState.seekSpecial = atoi(argv[1]); _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdStepCallk(int argc, const char **argv) { @@ -2844,7 +2847,7 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } if (callk_index == -1) { - DebugPrintf("Unknown kernel function '%s'\n", argv[1]); + debugPrintf("Unknown kernel function '%s'\n", argv[1]); return true; } } @@ -2856,16 +2859,16 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } _debugState.debugging = true; - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdDisassemble(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Disassembles a method by name.\n"); - DebugPrintf("Usage: %s <object> <method> <options>\n", argv[0]); - DebugPrintf("Valid options are:\n"); - DebugPrintf(" bwt : Print byte/word tag\n"); - DebugPrintf(" bc : Print bytecode\n"); + debugPrintf("Disassembles a method by name.\n"); + debugPrintf("Usage: %s <object> <method> <options>\n", argv[0]); + debugPrintf("Valid options are:\n"); + debugPrintf(" bwt : Print byte/word tag\n"); + debugPrintf(" bc : Print bytecode\n"); return true; } @@ -2874,8 +2877,8 @@ bool Console::cmdDisassemble(int argc, const char **argv) { bool printBWTag = false; if (parse_reg_t(_engine->_gamestate, argv[1], &objAddr, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2884,17 +2887,17 @@ bool Console::cmdDisassemble(int argc, const char **argv) { reg_t addr = NULL_REG; if (!obj) { - DebugPrintf("Not an object.\n"); + debugPrintf("Not an object.\n"); return true; } if (selectorId < 0) { - DebugPrintf("Not a valid selector name.\n"); + debugPrintf("Not a valid selector name.\n"); return true; } if (lookupSelector(_engine->_gamestate->_segMan, objAddr, selectorId, NULL, &addr) != kSelectorMethod) { - DebugPrintf("Not a method.\n"); + debugPrintf("Not a method.\n"); return true; } @@ -2924,12 +2927,12 @@ bool Console::cmdDisassemble(int argc, const char **argv) { bool Console::cmdDisassembleAddress(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Disassembles one or more commands.\n"); - DebugPrintf("Usage: %s [startaddr] <options>\n", argv[0]); - DebugPrintf("Valid options are:\n"); - DebugPrintf(" bwt : Print byte/word tag\n"); - DebugPrintf(" c<x> : Disassemble <x> bytes\n"); - DebugPrintf(" bc : Print bytecode\n"); + debugPrintf("Disassembles one or more commands.\n"); + debugPrintf("Usage: %s [startaddr] <options>\n", argv[0]); + debugPrintf("Valid options are:\n"); + debugPrintf(" bwt : Print byte/word tag\n"); + debugPrintf(" c<x> : Disassemble <x> bytes\n"); + debugPrintf(" bc : Print bytecode\n"); return true; } @@ -2940,8 +2943,8 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { uint16 size; if (parse_reg_t(_engine->_gamestate, argv[1], &vpc, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address passed.\n"); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -2956,7 +2959,7 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) { else if (toupper(argv[i][0]) == 'C') opCount = atoi(argv[i] + 1); else { - DebugPrintf("Invalid option '%s'\n", argv[i]); + debugPrintf("Invalid option '%s'\n", argv[i]); return true; } } @@ -2974,7 +2977,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { Common::sort(resources.begin(), resources.end()); if (showFoundScripts) - DebugPrintf("%d scripts found, dissassembling...\n", resources.size()); + debugPrintf("%d scripts found, dissassembling...\n", resources.size()); int scriptSegment; Script *script; @@ -3023,7 +3026,7 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { uint16 argc2 = opparams[1]; if (kFuncNum == kernelFuncNum) { - DebugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n", + debugPrintf("Called from script %d, object %s, method %s(%d) with %d bytes for arguments\n", itr->getNumber(), objName, _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), i, argc2); } @@ -3055,19 +3058,19 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) { bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Finds the scripts and methods that call a specific kernel function.\n"); - DebugPrintf("Usage: %s <kernel function>\n", argv[0]); - DebugPrintf("Example: %s Display\n", argv[0]); - DebugPrintf("Special usage:\n"); - DebugPrintf("%s Dummy - find all calls to actual dummy functions " + debugPrintf("Finds the scripts and methods that call a specific kernel function.\n"); + debugPrintf("Usage: %s <kernel function>\n", argv[0]); + debugPrintf("Example: %s Display\n", argv[0]); + debugPrintf("Special usage:\n"); + debugPrintf("%s Dummy - find all calls to actual dummy functions " "(mapped to kDummy, and dummy in the kernel table). " "There shouldn't be calls to these (apart from a known " "one in Shivers)\n", argv[0]); - DebugPrintf("%s Unused - find all calls to unused functions (mapped to " + debugPrintf("%s Unused - find all calls to unused functions (mapped to " "kDummy - i.e. mapped in SSCI but dummy in ScummVM, thus " "they'll error out when called). Only debug scripts should " "be calling these\n", argv[0]); - DebugPrintf("%s Unmapped - find all calls to currently unmapped or " + debugPrintf("%s Unmapped - find all calls to currently unmapped or " "unimplemented functions (mapped to kStub/kStubNull)\n", argv[0]); return true; } @@ -3080,7 +3083,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { int kernelFuncNum = kernel->findKernelFuncPos(argv[1]); if (kernelFuncNum < 0) { - DebugPrintf("Invalid kernel function requested\n"); + debugPrintf("Invalid kernel function requested\n"); return true; } @@ -3090,7 +3093,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { // in the kernel table) for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) == "Dummy") { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3100,7 +3103,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { // called) for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kDummy && kernel->getKernelName(i) != "Dummy") { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3109,7 +3112,7 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { for (uint i = 0; i < kernel->_kernelFuncs.size(); i++) { if (kernel->_kernelFuncs[i].function == &kStub || kernel->_kernelFuncs[i].function == &kStubNull) { - DebugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); + debugPrintf("Searching for kernel function %d (%s)...\n", i, kernel->getKernelName(i).c_str()); printKernelCallsFound(i, false); } } @@ -3120,17 +3123,17 @@ bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) { bool Console::cmdSend(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Sends a message to an object.\n"); - DebugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]); - DebugPrintf("Example: %s ?fooScript cue\n", argv[0]); + debugPrintf("Sends a message to an object.\n"); + debugPrintf("Usage: %s <object> <selector name> <param1> <param2> ... <paramn>\n", argv[0]); + debugPrintf("Example: %s ?fooScript cue\n", argv[0]); return true; } reg_t object; if (parse_reg_t(_engine->_gamestate, argv[1], &object, false)) { - DebugPrintf("Invalid address \"%s\" passed.\n", argv[1]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address \"%s\" passed.\n", argv[1]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } @@ -3138,20 +3141,20 @@ bool Console::cmdSend(int argc, const char **argv) { int selectorId = _engine->getKernel()->findSelector(selectorName); if (selectorId < 0) { - DebugPrintf("Unknown selector: \"%s\"\n", selectorName); + debugPrintf("Unknown selector: \"%s\"\n", selectorName); return true; } const Object *o = _engine->_gamestate->_segMan->getObject(object); if (o == NULL) { - DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); + debugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); return true; } SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL); if (selector_type == kSelectorNone) { - DebugPrintf("Object does not support selector: \"%s\"\n", selectorName); + debugPrintf("Object does not support selector: \"%s\"\n", selectorName); return true; } @@ -3165,8 +3168,8 @@ bool Console::cmdSend(int argc, const char **argv) { stackframe[1] = make_reg(0, send_argc); for (int i = 0; i < send_argc; i++) { if (parse_reg_t(_engine->_gamestate, argv[3+i], &stackframe[2+i], false)) { - DebugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); + debugPrintf("Invalid address \"%s\" passed.\n", argv[3+i]); + debugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } } @@ -3184,7 +3187,7 @@ bool Console::cmdSend(int argc, const char **argv) { if (old_xstack != xstack) { _engine->_gamestate->_executionStackPosChanged = true; - DebugPrintf("Message scheduled for execution\n"); + debugPrintf("Message scheduled for execution\n"); // We call run_engine explictly so we can restore the value of r_acc // after execution. @@ -3194,7 +3197,7 @@ bool Console::cmdSend(int argc, const char **argv) { if (restore_acc) { // varselector read or message executed - DebugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc)); + debugPrintf("Message completed. Value returned: %04x:%04x\n", PRINT_REG(_engine->_gamestate->r_acc)); _engine->_gamestate->r_acc = old_acc; } @@ -3205,14 +3208,14 @@ bool Console::cmdGo(int argc, const char **argv) { // CHECKME: is this necessary? _debugState.seeking = kDebugSeekNothing; - return Cmd_Exit(argc, argv); + return cmdExit(argc, argv); } bool Console::cmdLogKernel(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Logs calls to specified kernel function.\n"); - DebugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]); - DebugPrintf("Example: %s StrCpy on\n", argv[0]); + debugPrintf("Logs calls to specified kernel function.\n"); + debugPrintf("Usage: %s <kernel function/*> <on/off>\n", argv[0]); + debugPrintf("Example: %s StrCpy on\n", argv[0]); return true; } @@ -3222,14 +3225,14 @@ bool Console::cmdLogKernel(int argc, const char **argv) { else if (strcmp(argv[2], "off") == 0) logging = false; else { - DebugPrintf("2nd parameter must be either on or off\n"); + debugPrintf("2nd parameter must be either on or off\n"); return true; } if (g_sci->getKernel()->debugSetFunction(argv[1], logging, -1)) - DebugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]); + debugPrintf("Logging %s for k%s\n", logging ? "enabled" : "disabled", argv[1]); else - DebugPrintf("Unknown kernel function %s\n", argv[1]); + debugPrintf("Unknown kernel function %s\n", argv[1]); return true; } @@ -3237,25 +3240,25 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { int i = 0; int bpdata; - DebugPrintf("Breakpoint list:\n"); + debugPrintf("Breakpoint list:\n"); Common::List<Breakpoint>::const_iterator bp = _debugState._breakpoints.begin(); Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end(); for (; bp != end; ++bp) { - DebugPrintf(" #%i: ", i); + debugPrintf(" #%i: ", i); switch (bp->type) { case BREAK_SELECTOREXEC: - DebugPrintf("Execute %s\n", bp->name.c_str()); + debugPrintf("Execute %s\n", bp->name.c_str()); break; case BREAK_SELECTORREAD: - DebugPrintf("Read %s\n", bp->name.c_str()); + debugPrintf("Read %s\n", bp->name.c_str()); break; case BREAK_SELECTORWRITE: - DebugPrintf("Write %s\n", bp->name.c_str()); + debugPrintf("Write %s\n", bp->name.c_str()); break; case BREAK_EXPORT: bpdata = bp->address; - DebugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); + debugPrintf("Execute script %d, export %d\n", bpdata >> 16, bpdata & 0xFFFF); break; } @@ -3263,16 +3266,16 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { } if (!i) - DebugPrintf(" No breakpoints defined.\n"); + debugPrintf(" No breakpoints defined.\n"); return true; } bool Console::cmdBreakpointDelete(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Deletes a breakpoint with the specified index.\n"); - DebugPrintf("Usage: %s <breakpoint index>\n", argv[0]); - DebugPrintf("<index> * will remove all breakpoints\n"); + debugPrintf("Deletes a breakpoint with the specified index.\n"); + debugPrintf("Usage: %s <breakpoint index>\n", argv[0]); + debugPrintf("<index> * will remove all breakpoints\n"); return true; } @@ -3292,7 +3295,7 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } if (bp == end) { - DebugPrintf("Invalid breakpoint index %i\n", idx); + debugPrintf("Invalid breakpoint index %i\n", idx); return true; } @@ -3312,11 +3315,11 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { bool Console::cmdBreakpointMethod(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on execution of a specified method/selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::doit\n", argv[0]); - DebugPrintf("May also be used to set a breakpoint that applies whenever an object\n"); - DebugPrintf("of a specific type is touched: %s foo::\n", argv[0]); + debugPrintf("Sets a breakpoint on execution of a specified method/selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::doit\n", argv[0]); + debugPrintf("May also be used to set a breakpoint that applies whenever an object\n"); + debugPrintf("of a specific type is touched: %s foo::\n", argv[0]); return true; } @@ -3334,9 +3337,9 @@ bool Console::cmdBreakpointMethod(int argc, const char **argv) { bool Console::cmdBreakpointRead(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on reading of a specified selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::view\n", argv[0]); + debugPrintf("Sets a breakpoint on reading of a specified selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::view\n", argv[0]); return true; } @@ -3351,9 +3354,9 @@ bool Console::cmdBreakpointRead(int argc, const char **argv) { bool Console::cmdBreakpointWrite(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Sets a breakpoint on writing of a specified selector.\n"); - DebugPrintf("Usage: %s <name>\n", argv[0]); - DebugPrintf("Example: %s ego::view\n", argv[0]); + debugPrintf("Sets a breakpoint on writing of a specified selector.\n"); + debugPrintf("Usage: %s <name>\n", argv[0]); + debugPrintf("Example: %s ego::view\n", argv[0]); return true; } @@ -3368,9 +3371,9 @@ bool Console::cmdBreakpointWrite(int argc, const char **argv) { bool Console::cmdBreakpointKernel(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("Sets a breakpoint on execution of a kernel function.\n"); - DebugPrintf("Usage: %s <name> <on/off>\n", argv[0]); - DebugPrintf("Example: %s DrawPic on\n", argv[0]); + debugPrintf("Sets a breakpoint on execution of a kernel function.\n"); + debugPrintf("Usage: %s <name> <on/off>\n", argv[0]); + debugPrintf("Example: %s DrawPic on\n", argv[0]); return true; } @@ -3380,22 +3383,22 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) { else if (strcmp(argv[2], "off") == 0) breakpoint = false; else { - DebugPrintf("2nd parameter must be either on or off\n"); + debugPrintf("2nd parameter must be either on or off\n"); return true; } if (g_sci->getKernel()->debugSetFunction(argv[1], -1, breakpoint)) - DebugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]); + debugPrintf("Breakpoint %s for k%s\n", (breakpoint ? "enabled" : "disabled"), argv[1]); else - DebugPrintf("Unknown kernel function %s\n", argv[1]); + debugPrintf("Unknown kernel function %s\n", argv[1]); return true; } bool Console::cmdBreakpointFunction(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n"); - DebugPrintf("Usage: %s <script number> <export number\n", argv[0]); + debugPrintf("Sets a breakpoint on the execution of the specified exported function.\n"); + debugPrintf("Usage: %s <script number> <export number\n", argv[0]); return true; } @@ -3415,21 +3418,21 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) { bool Console::cmdSfx01Header(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Dumps the header of a SCI01 song\n"); - DebugPrintf("Usage: %s <track>\n", argv[0]); + debugPrintf("Dumps the header of a SCI01 song\n"); + debugPrintf("Usage: %s <track>\n", argv[0]); return true; } Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); if (!song) { - DebugPrintf("Doesn't exist\n"); + debugPrintf("Doesn't exist\n"); return true; } uint32 offset = 0; - DebugPrintf("SCI01 song track mappings:\n"); + debugPrintf("SCI01 song track mappings:\n"); if (*song->data == 0xf0) // SCI1 priority spec offset = 8; @@ -3439,7 +3442,7 @@ bool Console::cmdSfx01Header(int argc, const char **argv) { while (song->data[offset] != 0xff) { byte device_id = song->data[offset]; - DebugPrintf("* Device %02x:\n", device_id); + debugPrintf("* Device %02x:\n", device_id); offset++; if (offset + 1 >= song->size) @@ -3461,12 +3464,12 @@ bool Console::cmdSfx01Header(int argc, const char **argv) { track_offset += 2; end = READ_LE_UINT16(song->data + offset + 2); - DebugPrintf(" - %04x -- %04x", track_offset, track_offset + end); + debugPrintf(" - %04x -- %04x", track_offset, track_offset + end); if (track_offset == 0xfe) - DebugPrintf(" (PCM data)\n"); + debugPrintf(" (PCM data)\n"); else - DebugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n", + debugPrintf(" (channel %d, special %d, %d playing notes, %d foo)\n", header1 & 0xf, header1 >> 4, header2 & 0xf, header2 >> 4); offset += 4; } @@ -3580,8 +3583,8 @@ static void midi_hexdump(byte *data, int size, int notational_offset) { bool Console::cmdSfx01Track(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Dumps a track of a SCI01 song\n"); - DebugPrintf("Usage: %s <track> <offset>\n", argv[0]); + debugPrintf("Dumps a track of a SCI01 song\n"); + debugPrintf("Usage: %s <track> <offset>\n", argv[0]); return true; } @@ -3590,7 +3593,7 @@ bool Console::cmdSfx01Track(int argc, const char **argv) { int offset = atoi(argv[2]); if (!song) { - DebugPrintf("Doesn't exist\n"); + debugPrintf("Doesn't exist\n"); return true; } @@ -3614,29 +3617,29 @@ bool Console::cmdQuit(int argc, const char **argv) { _debugState.runningStep = 0; } else { - DebugPrintf("%s [game] - exit gracefully\n", argv[0]); - DebugPrintf("%s now - exit ungracefully\n", argv[0]); + debugPrintf("%s [game] - exit gracefully\n", argv[0]); + debugPrintf("%s now - exit ungracefully\n", argv[0]); return true; } - return Cmd_Exit(0, 0); + return cmdExit(0, 0); } bool Console::cmdAddresses(int argc, const char **argv) { - DebugPrintf("Address parameters may be passed in one of three forms:\n"); - DebugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n"); - DebugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n"); - DebugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n"); - DebugPrintf(" fail if the script is not currently loaded\n"); - DebugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n"); - DebugPrintf(" indicated by the register of this name.\n"); - DebugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n"); - DebugPrintf(" is specified in hexadecimal).\n"); - DebugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n"); - DebugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n"); - DebugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n"); - DebugPrintf(" Underscores are used as substitute characters for spaces in object names.\n"); - DebugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n"); + debugPrintf("Address parameters may be passed in one of three forms:\n"); + debugPrintf(" - ssss:oooo -- where 'ssss' denotes a segment and 'oooo' an offset.\n"); + debugPrintf(" Example: \"a:c5\" would address something in segment 0xa at offset 0xc5.\n"); + debugPrintf(" - &scr:oooo -- where 'scr' is a script number and oooo an offset within that script; will\n"); + debugPrintf(" fail if the script is not currently loaded\n"); + debugPrintf(" - $REG -- where 'REG' is one of 'PC', 'ACC', 'PREV' or 'OBJ': References the address\n"); + debugPrintf(" indicated by the register of this name.\n"); + debugPrintf(" - $REG+n (or -n) -- Like $REG, but modifies the offset part by a specific amount (which\n"); + debugPrintf(" is specified in hexadecimal).\n"); + debugPrintf(" - ?obj -- Looks up an object with the specified name, uses its address. This will abort if\n"); + debugPrintf(" the object name is ambiguous; in that case, a list of addresses and indices is provided.\n"); + debugPrintf(" ?obj.idx may be used to disambiguate 'obj' by the index 'idx'.\n"); + debugPrintf(" Underscores are used as substitute characters for spaces in object names.\n"); + debugPrintf(" For example, an object named \"Glass Jar\" can be accessed as \"Glass_Jar\".\n"); return true; } @@ -3887,14 +3890,14 @@ bool Console::parseInteger(const char *argument, int &result) { // hexadecimal number result = strtol(argument, &endPtr, 16); if ((*endPtr != 0) && (*endPtr != 'h')) { - DebugPrintf("Invalid hexadecimal number '%s'\n", argument); + debugPrintf("Invalid hexadecimal number '%s'\n", argument); return false; } } else { // decimal number result = strtol(argument, &endPtr, 10); if (*endPtr != 0) { - DebugPrintf("Invalid decimal number '%s'\n", argument); + debugPrintf("Invalid decimal number '%s'\n", argument); return false; } } @@ -3912,57 +3915,57 @@ void Console::printBasicVarInfo(reg_t variable) { case SIG_TYPE_INTEGER: { uint16 content = variable.toUint16(); if (content >= 10) - DebugPrintf(" (%dd)", content); + debugPrintf(" (%dd)", content); break; } case SIG_TYPE_OBJECT: - DebugPrintf(" (object '%s')", segMan->getObjectName(variable)); + debugPrintf(" (object '%s')", segMan->getObjectName(variable)); break; case SIG_TYPE_REFERENCE: - DebugPrintf(" (reference)"); + debugPrintf(" (reference)"); break; case SIG_TYPE_NODE: - DebugPrintf(" (node)"); + debugPrintf(" (node)"); break; case SIG_TYPE_LIST: - DebugPrintf(" (list)"); + debugPrintf(" (list)"); break; case SIG_TYPE_UNINITIALIZED: - DebugPrintf(" (uninitialized)"); + debugPrintf(" (uninitialized)"); break; case SIG_TYPE_ERROR: - DebugPrintf(" (error)"); + debugPrintf(" (error)"); break; default: - DebugPrintf(" (??\?)"); + debugPrintf(" (??\?)"); } if (regType & SIG_IS_INVALID) - DebugPrintf(" IS INVALID!"); + debugPrintf(" IS INVALID!"); } void Console::printList(List *list) { reg_t pos = list->first; reg_t my_prev = NULL_REG; - DebugPrintf("\t<\n"); + debugPrintf("\t<\n"); while (!pos.isNull()) { Node *node; NodeTable *nt = (NodeTable *)_engine->_gamestate->_segMan->getSegment(pos.getSegment(), SEG_TYPE_NODES); if (!nt || !nt->isValidEntry(pos.getOffset())) { - DebugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", + debugPrintf(" WARNING: %04x:%04x: Doesn't contain list node!\n", PRINT_REG(pos)); return; } node = &(nt->_table[pos.getOffset()]); - DebugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); + debugPrintf("\t%04x:%04x : %04x:%04x -> %04x:%04x\n", PRINT_REG(pos), PRINT_REG(node->key), PRINT_REG(node->value)); if (my_prev != node->pred) - DebugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n", + debugPrintf(" WARNING: current node gives %04x:%04x as predecessor!\n", PRINT_REG(node->pred)); my_prev = pos; @@ -3970,9 +3973,9 @@ void Console::printList(List *list) { } if (my_prev != list->last) - DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", + debugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", PRINT_REG(list->last), PRINT_REG(my_prev)); - DebugPrintf("\t>\n"); + debugPrintf("\t>\n"); } int Console::printNode(reg_t addr) { @@ -3983,32 +3986,32 @@ int Console::printNode(reg_t addr) { List *list; if (!lt->isValidEntry(addr.getOffset())) { - DebugPrintf("Address does not contain a list\n"); + debugPrintf("Address does not contain a list\n"); return 1; } list = &(lt->_table[addr.getOffset()]); - DebugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); + debugPrintf("%04x:%04x : first x last = (%04x:%04x, %04x:%04x)\n", PRINT_REG(addr), PRINT_REG(list->first), PRINT_REG(list->last)); } else { NodeTable *nt; Node *node; mobj = _engine->_gamestate->_segMan->getSegment(addr.getSegment(), SEG_TYPE_NODES); if (!mobj) { - DebugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment()); + debugPrintf("Segment #%04x is not a list or node segment\n", addr.getSegment()); return 1; } nt = (NodeTable *)mobj; if (!nt->isValidEntry(addr.getOffset())) { - DebugPrintf("Address does not contain a node\n"); + debugPrintf("Address does not contain a node\n"); return 1; } node = &(nt->_table[addr.getOffset()]); - DebugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", + debugPrintf("%04x:%04x : prev x next = (%04x:%04x, %04x:%04x); maps %04x:%04x -> %04x:%04x\n", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(node->succ), PRINT_REG(node->key), PRINT_REG(node->value)); } @@ -4022,44 +4025,44 @@ int Console::printObject(reg_t pos) { uint i; if (!obj) { - DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); + debugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); return 1; } // Object header - DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos), + debugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), s->_segMan->getObjectName(pos), obj->getVarCount(), obj->getMethodCount()); if (!obj->isClass() && getSciVersion() != SCI_VERSION_3) var_container = s->_segMan->getObject(obj->getSuperClassSelector()); - DebugPrintf(" -- member variables:\n"); + debugPrintf(" -- member variables:\n"); for (i = 0; (uint)i < obj->getVarCount(); i++) { - DebugPrintf(" "); + debugPrintf(" "); if (var_container && i < var_container->getVarCount()) { uint16 varSelector = var_container->getVarSelector(i); - DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); + debugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); } else - DebugPrintf("p#%x = ", i); + debugPrintf("p#%x = ", i); reg_t val = obj->getVariable(i); - DebugPrintf("%04x:%04x", PRINT_REG(val)); + debugPrintf("%04x:%04x", PRINT_REG(val)); if (!val.getSegment()) - DebugPrintf(" (%d)", val.getOffset()); + debugPrintf(" (%d)", val.getOffset()); const Object *ref = s->_segMan->getObject(val); if (ref) - DebugPrintf(" (%s)", s->_segMan->getObjectName(val)); + debugPrintf(" (%s)", s->_segMan->getObjectName(val)); - DebugPrintf("\n"); + debugPrintf("\n"); } - DebugPrintf(" -- methods:\n"); + debugPrintf(" -- methods:\n"); for (i = 0; i < obj->getMethodCount(); i++) { reg_t fptr = obj->getFunction(i); - DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); + debugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } if (s->_segMan->_heap[pos.getSegment()]->getType() == SEG_TYPE_SCRIPT) - DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber()); + debugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.getSegment())->getScriptNumber()); return 0; } diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 8c5f9be425..368b82cb93 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -4054,7 +4054,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { FANMADE("SCI Capture the Flag", "4cd679a51d93b8b27c6b38d81be24b8b", 432, "98ae1f6ed7b4c21f88addbf643dd1d2f", 147878), FANMADE("SCI Companion Template", "ad54d4f504086cd597aa2348d0aa3b09", 354, "6798b7b601ce8154c1d1bc0f0edcdd18", 113061), FANMADE("SCI Logging Demo", "615c30c1445ea9349847e8868312a674", 558, "2df6858526177612ef9473e7af5b31c6", 171012), -#ifdef 0 +#if 0 // Disabled as this requires network access to the Google Translate API, which is not available as OSystem has no network API. FANMADE("SCI Narration Demo", "731f4f2b726a13c153380af08da16591", 360, "38c80558fb942e8568f011d4a1a4af59", 109789), #endif diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 59f741a254..cb81da2279 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -126,7 +126,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // track left buttton clicks, if requested if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.data == 1 && g_debug_track_mouse_clicks) { - g_sci->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", + g_sci->getSciDebugger()->debugPrintf("Mouse clicked at %d, %d\n", mousePos.x, mousePos.y); } @@ -163,20 +163,20 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // A SCI event occurred, and we have been asked to stop, so open the debug console Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("SCI event occurred: "); + con->debugPrintf("SCI event occurred: "); switch (curEvent.type) { case SCI_EVENT_QUIT: - con->DebugPrintf("quit event\n"); + con->debugPrintf("quit event\n"); break; case SCI_EVENT_KEYBOARD: - con->DebugPrintf("keyboard event\n"); + con->debugPrintf("keyboard event\n"); break; case SCI_EVENT_MOUSE_RELEASE: case SCI_EVENT_MOUSE_PRESS: - con->DebugPrintf("mouse click event\n"); + con->debugPrintf("mouse click event\n"); break; default: - con->DebugPrintf("unknown or no event (event type %d)\n", curEvent.type); + con->debugPrintf("unknown or no event (event type %d)\n", curEvent.type); } con->attach(); diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index b4d245197b..8bbbd713a6 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -1218,7 +1218,7 @@ static const uint16 kq6CDPatchAudioTextSupportGirlInTheTower[] = { // Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode. // View 947, loop 9, cel 0+1 -> "text" // View 947, loop 8, cel 0+1 -> "speech" -// View 947, loop 12, cel 0+1 -> "dual" (TODO: inject our own 2 views for the new "dual" mode) +// View 947, loop 12, cel 0+1 -> "dual" (this view is injected by us into the game) // Applies to at least: PC-CD // Patched method: iconTextSwitch::show, iconTextSwitch::doit static const uint16 kq6CDSignatureAudioTextMenuSupport[] = { @@ -1595,6 +1595,86 @@ static const uint16 laurabow2CDPatchFixProblematicIconBar[] = { PATCH_END }; +// Opening/Closing the east door in the pterodactyl room doesn't +// check, if it's locked and will open/close the door internally +// even when it is. +// +// It will get wired shut later in the game by Laura Bow and will be +// "locked" because of this. We patch in a check for the locked +// state. We also add code, that will set the "locked" state +// in case our eastDoor-wired-global is set. This makes the locked +// state effectively persistent. +// +// Applies to at least: English PC-CD, English PC-Floppy +// Responsible method (CD): eastDoor::doVerb +// Responsible method (Floppy): eastDoor::<noname300> +// Fixes bug: #6458 (partly, see additional patch below) +static const uint16 laurabow2CDSignatureFixWiredEastDoor[] = { + 0x30, SIG_UINT16(0x0022), // bnt [skip hand action] + 0x67, SIG_ADDTOOFFSET(+1), // pTos CD: doorState, Floppy: state + 0x35, 0x00, // ldi 00 + 0x1a, // eq? + 0x31, 0x08, // bnt [close door code] + 0x78, // push1 + SIG_MAGICDWORD, + 0x39, 0x63, // pushi 63h + 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag) + 0x33, 0x06, // jmp [super-code] + 0x78, // push1 + 0x39, 0x63, // pushi 63h + 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag) + 0x38, SIG_ADDTOOFFSET(+2), // pushi CD: 011dh, Floppy: 012ch + 0x78, // push1 + 0x8f, 0x01, // lsp param[01] + 0x59, 0x02, // rest 02 + 0x57, SIG_ADDTOOFFSET(+1), 0x06, // super CD: LbDoor, Floppy: Door, 06 + 0x33, 0x0b, // jmp [ret] + SIG_END +}; + +static const uint16 laurabow2CDPatchFixWiredEastDoor[] = { + 0x31, 0x23, // bnt [skip hand action] (saves 1 byte) + 0x81, 97, // lag 97d (get our eastDoor-wired-global) + 0x31, 0x04, // bnt [skip setting locked property] + 0x35, 0x01, // ldi 01 + 0x65, 0x6a, // aTop locked (set eastDoor::locked to 1) + 0x63, 0x6a, // pToa locked (get eastDoor::locked) + 0x2f, 0x17, // bt [skip hand action] + 0x63, PATCH_GETORIGINALBYTE(+4), // pToa CD: doorState, Floppy: state + 0x78, // push1 + 0x39, 0x63, // pushi 63h + 0x2f, 0x05, // bt [close door code] + 0x45, 0x04, 0x02, // callb export000_4, 02 (sets door-bitflag) + 0x33, 0x0b, // jmp [super-code] + 0x45, 0x03, 0x02, // callb export000_3, 02 (resets door-bitflag) + 0x33, 0x06, // jmp [super-code] + PATCH_END +}; + +// We patch in code, so that our eastDoor-wired-global will get set to 1. +// This way the wired-state won't get lost when exiting room 430. +// +// Applies to at least: English PC-CD, English PC-Floppy +// Responsible method (CD): sWireItShut::changeState +// Responsible method (Floppy): sWireItShut::<noname144> +// Fixes bug: #6458 (partly, see additional patch above) +static const uint16 laurabow2SignatureRememberWiredEastDoor[] = { + SIG_MAGICDWORD, + 0x33, 0x27, // jmp [ret] + 0x3c, // dup + 0x35, 0x06, // ldi 06 + 0x1a, // eq? + 0x31, 0x21, // bnt [skip step] + SIG_END +}; + +static const uint16 laurabow2PatchRememberWiredEastDoor[] = { + PATCH_ADDTOOFFSET(+2), // skip jmp [ret] + 0x34, PATCH_UINT16(0x0001), // ldi 0001 + 0xa1, PATCH_UINT16(97), // sag 97d (set our eastDoor-wired-global) + PATCH_END +}; + // Laura Bow 2 CD resets the audio mode to speech on init/restart // We already sync the settings from ScummVM (see SciEngine::syncIngameAudioOptions()) // and this script code would make it impossible to see the intro using "dual" mode w/o using debugger command @@ -1617,7 +1697,7 @@ static const uint16 laurabow2CDPatchAudioTextSupportModeReset[] = { // That way it's possible to use a new "dual" mode view in the game menu // View 995, loop 13, cel 0 -> "text" // View 995, loop 13, cel 1 -> "speech" -// View 995, loop 13, cel 2 -> "dual" (TODO: inject our own view for the new "dual" mode) +// View 995, loop 13, cel 2 -> "dual" (this view is injected by us into the game) // Patched method: gcWin::open static const uint16 laurabow2CDSignatureAudioTextMenuSupport1[] = { SIG_MAGICDWORD, @@ -1636,7 +1716,6 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport1[] = { }; // Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode. -// TODO: inject our own 2 views for the new "dual" mode // Patched method: iconMode::doit static const uint16 laurabow2CDSignatureAudioTextMenuSupport2[] = { SIG_MAGICDWORD, @@ -1684,6 +1763,8 @@ static const uint16 laurabow2CDPatchAudioTextMenuSupport2[] = { static const SciScriptPatcherEntry laurabow2Signatures[] = { { true, 560, "CD: painting closing immediately", 1, laurabow2CDSignaturePaintingClosing, laurabow2CDPatchPaintingClosing }, { true, 0, "CD: fix problematic icon bar", 1, laurabow2CDSignatureFixProblematicIconBar, laurabow2CDPatchFixProblematicIconBar }, + { true, 430, "CD/Floppy: make wired east door persistent", 1, laurabow2SignatureRememberWiredEastDoor, laurabow2PatchRememberWiredEastDoor }, + { true, 430, "CD/Floppy: fix wired east door", 1, laurabow2CDSignatureFixWiredEastDoor, laurabow2CDPatchFixWiredEastDoor }, // King's Quest 6 and Laura Bow 2 share basic patches for audio + text support { false, 924, "CD: audio + text support 1", 1, kq6laurabow2CDSignatureAudioTextSupport1, kq6laurabow2CDPatchAudioTextSupport1 }, { false, 924, "CD: audio + text support 2", 1, kq6laurabow2CDSignatureAudioTextSupport2, kq6laurabow2CDPatchAudioTextSupport2 }, @@ -2373,11 +2454,91 @@ static const uint16 sq1vgaPatchEgoShowsCard[] = { PATCH_END }; +// The spider droid on planet Korona has a fixed movement speed, +// which is way faster than the default movement speed of ego. +// This means that the player would have to turn up movement speed, +// otherwise it will be impossible to escape it. +// We fix this issue by making the droid move a bit slower than ego +// does (relative to movement speed setting). +// +// Applies to at least: English PC floppy +// Responsible method: spider::doit +static const uint16 sq1vgaSignatureSpiderDroidTiming[] = { + SIG_MAGICDWORD, + 0x63, 0x4e, // pToa script + 0x30, SIG_UINT16(0x0005), // bnt [further method code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_UINT16(0x0062), // jmp [super-call] + 0x38, SIG_UINT16(0x0088), // pushi 0088h (script) + 0x76, // push0 + 0x81, 0x02, // lag global[2] (current room) + 0x4a, 0x04, // send 04 (get [current room].script) + 0x30, SIG_UINT16(0x0005), // bnt [further method code] + 0x35, 0x00, // ldi 00 + 0x32, SIG_UINT16(0x0052), // jmp [super-call] + 0x89, 0xa6, // lsg global[a6] + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + 0x30, SIG_UINT16(0x0012), // bnt [2nd code], in case global A6 <> 1 + 0x81, 0xb5, // lag global[b5] + 0x30, SIG_UINT16(0x000d), // bnt [2nd code], in case global B5 == 0 + 0x38, SIG_UINT16(0x008c), // pushi 008c + 0x78, // push1 + 0x72, SIG_UINT16(0x1cb6), // lofsa 1CB6 (moveToPath) + 0x36, // push + 0x54, 0x06, // self 06 + 0x32, SIG_UINT16(0x0038), // jmp [super-call] + 0x81, 0xb5, // lag global[B5] + 0x18, // not + 0x30, SIG_UINT16(0x0032), // bnt [super-call], in case global B5 <> 0 + SIG_END +}; // 58 bytes) + +static const uint16 sq1vgaPatchSpiderDroidTiming[] = { + 0x63, 0x4e, // pToa script + 0x2f, 0x68, // bt [super-call] + 0x38, PATCH_UINT16(0x0088), // pushi 0088 (script) + 0x76, // push0 + 0x81, 0x02, // lag global[2] (current room) + 0x4a, 0x04, // send 04 + 0x2f, 0x5e, // bt [super-call] + // --> 12 bytes saved + // new code + 0x38, PATCH_UINT16(0x0176), // pushi 0176 (egoMoveSpeed) + 0x76, // push0 + 0x81, 0x01, // lag global[1] + 0x4a, 0x04, // send 04 - sq1::egoMoveSpeed + 0x36, // push + 0x36, // push + 0x35, 0x03, // ldi 03 + 0x0c, // shr + 0x02, // add --> egoMoveSpeed + (egoMoveSpeed >> 3) + 0x39, 0x01, // push 01 (waste 1 byte) + 0x02, // add --> egoMoveSpeed++ + 0x65, 0x4c, // aTop cycleSpeed + 0x65, 0x5e, // aTop moveSpeed + // new code end + 0x89, 0xb5, // lsg global[B5] + 0x31, 0x13, // bnt [2nd code chunk] + 0x89, 0xa6, // lsg global[A6] + 0x35, 0x01, // ldi 01 + 0x1a, // eq? + 0x31, 0x3e, // bnt [super-call] + 0x38, PATCH_UINT16(0x008c), // pushi 008c + 0x78, // push1 + 0x72, PATCH_UINT16(0x1cb6), // lofsa moveToPath + 0x36, // push + 0x54, 0x06, // self 06 - spider::setScript(movePath) + 0x33, 0x32, // jmp [super-call] + // --> 9 bytes saved + PATCH_END +}; // script, description, signature patch static const SciScriptPatcherEntry sq1vgaSignatures[] = { { true, 45, "Ulence Flats: timepod graphic glitch", 1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch }, { true, 58, "Sarien armory droid zapping ego first time", 1, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard }, + { true, 704, "spider droid timing issue", 1, sq1vgaSignatureSpiderDroidTiming, sq1vgaPatchSpiderDroidTiming }, SCI_SIGNATUREENTRY_TERMINATOR }; diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 44910058ef..f0157a6569 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -604,7 +604,7 @@ bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t sen Common::List<Breakpoint>::const_iterator bpIter; for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { - _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); + _console->debugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); _debugState.debugging = true; _debugState.breakpointWasHit = true; return true; @@ -620,7 +620,7 @@ bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { Common::List<Breakpoint>::const_iterator bp; for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { - _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); + _console->debugPrintf("Break on script %d, export %d\n", script, pubfunct); _debugState.debugging = true; _debugState.breakpointWasHit = true; return true; @@ -666,12 +666,12 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg reg_t selectorValue = *varp.getPointer(segMan); if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) { if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) - con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n", + con->debugPrintf("Read from selector (%s:%s): %04x:%04x\n", objectName, selectorName, PRINT_REG(selectorValue)); } else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) { if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) - con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n", + con->debugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n", objectName, selectorName, PRINT_REG(selectorValue), PRINT_REG(argp[1])); } @@ -690,13 +690,13 @@ void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr arg if (true) { if (true) { #endif - con->DebugPrintf("%s::%s(", objectName, selectorName); + con->debugPrintf("%s::%s(", objectName, selectorName); for (int i = 0; i < argc; i++) { - con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); + con->debugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); if (i + 1 < argc) - con->DebugPrintf(", "); + con->debugPrintf(", "); } - con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); + con->debugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); } } break; diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 73cd7240d3..7957ed6a55 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -726,7 +726,7 @@ void GfxAnimate::printAnimateList(Console *con) { Script *scr = _s->_segMan->getScriptIfLoaded(it->object.getSegment()); int16 scriptNo = scr ? scr->getScriptNumber() : -1; - con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " + con->debugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " "at %d, %d, scale %d, %d / %d (z: %d, prio: %d, shown: %d, signal: %d)\n", PRINT_REG(it->object), _s->_segMan->getObjectName(it->object), scriptNo, it->viewId, it->loopNo, it->celNo, it->paletteNo, diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index ffed7b596e..a322eb8e61 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -852,21 +852,21 @@ void GfxFrameout::printPlaneList(Console *con) { Common::Rect r = p.upscaledPlaneRect; Common::Rect cr = p.upscaledPlaneClipRect; - con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", + con->debugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", PRINT_REG(p.object), curPlaneName.c_str(), (int16)p.priority, (int16)p.lastPriority, p.planeOffsetX, p.planeOffsetY, p.pictureId, p.planePictureMirrored, p.planeBack); - con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", + con->debugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom, cr.left, cr.top, cr.right, cr.bottom); if (p.pictureId != 0xffff && p.pictureId != 0xfffe) { - con->DebugPrintf("Pictures:\n"); + con->debugPrintf("Pictures:\n"); for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { if (pictureIt->object == p.object) { - con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); + con->debugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); } } } @@ -883,7 +883,7 @@ void GfxFrameout::printPlaneItemList(Console *con, reg_t planeObject) { Common::Rect icr = e->celRect; GuiResourceId picId = e->picture ? e->picture->getResourceId() : 0; - con->DebugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " + con->debugPrintf("%d: %04x:%04x (%s), view %d, loop %d, cel %d, x %d, y %d, z %d, " "signal %d, scale signal %d, scaleX %d, scaleY %d, rect (%d, %d, %d, %d), " "pic %d, picX %d, picY %d, visible %d\n", e->givenOrderNr, PRINT_REG(e->object), curItemName.c_str(), diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index bd0b5f4081..56c63a7b12 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -748,7 +748,7 @@ void GfxPorts::printWindowList(Console *con) { for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) { if ((*it)->isWindow()) { Window *wnd = ((Window *)*it); - con->DebugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n", + con->debugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n", wnd->id, wnd->title.c_str(), wnd->left, wnd->top, wnd->rect.left, wnd->rect.top, wnd->rect.right, wnd->rect.bottom, wnd->bDrawn, wnd->wndStyle); diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp index ee0125b7c9..05764ba0a8 100644 --- a/engines/sci/parser/grammar.cpp +++ b/engines/sci/parser/grammar.cpp @@ -397,7 +397,7 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) { ntrules_nr = _vocab_rule_list_length(ntlist); if (verbose) - con->DebugPrintf("Starting with %d rules\n", ntrules_nr); + con->debugPrintf("Starting with %d rules\n", ntrules_nr); new_tlist = tlist; tlist = NULL; @@ -425,17 +425,17 @@ ParseRuleList *Vocabulary::buildGNF(bool verbose) { termrules = _vocab_rule_list_length(new_new_tlist); if (verbose) - con->DebugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules); + con->debugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules); } while (termrules && (iterations < 30)); freeRuleList(ntlist); if (verbose) { - con->DebugPrintf("\nGNF rules:\n"); + con->debugPrintf("\nGNF rules:\n"); tlist->print(); - con->DebugPrintf("%d allocd rules\n", _allocd_rules); - con->DebugPrintf("Freeing rule list...\n"); + con->debugPrintf("%d allocd rules\n", _allocd_rules); + con->debugPrintf("Freeing rule list...\n"); freeRuleList(tlist); return NULL; } @@ -548,7 +548,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { ParseRuleList *seeker, *subseeker; if (verbose) - con->DebugPrintf("Adding word %d...\n", word); + con->debugPrintf("Adding word %d...\n", word); seeker = work; while (seeker) { @@ -562,7 +562,7 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { if (reduced_rules == NULL) { freeRuleList(work); if (verbose) - con->DebugPrintf("No results.\n"); + con->debugPrintf("No results.\n"); return 1; } @@ -592,10 +592,10 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { work = new_work; if (verbose) - con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work)); + con->debugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work)); if (work == NULL) { if (verbose) - con->DebugPrintf("No results.\n"); + con->debugPrintf("No results.\n"); return 1; } } @@ -603,9 +603,9 @@ int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { results = work; if (verbose) { - con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id); + con->debugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id); results->print(); - con->DebugPrintf("\n"); + con->debugPrintf("\n"); } // now use the first result diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 7c560dfaef..b4a223dcff 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -577,7 +577,7 @@ void Vocabulary::printSuffixes() const { strncpy(alt_buf, suf->alt_suffix, suf->alt_suffix_length); alt_buf[suf->alt_suffix_length] = 0; - con->DebugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class); + con->debugPrintf("%4d: (%03x) -%12s => -%12s (%03x)\n", i, suf->class_mask, word_buf, alt_buf, suf->result_class); ++i; } } @@ -588,14 +588,14 @@ void Vocabulary::printParserWords() const { int n = 0; for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) { for (ResultWordList::iterator j = i->_value.begin(); j != i->_value.end(); ++j) { - con->DebugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str()); + con->debugPrintf("%4d: %03x [%03x] %20s |", n, j->_class, j->_group, i->_key.c_str()); if (n % 3 == 0) - con->DebugPrintf("\n"); + con->debugPrintf("\n"); n++; } } - con->DebugPrintf("\n"); + con->debugPrintf("\n"); } void _vocab_recursive_ptree_dump(ParseTreeNode *tree, int blanks) { @@ -665,15 +665,15 @@ void Vocabulary::printParserNodes(int num) { Console *con = g_sci->getSciDebugger(); for (int i = 0; i < num; i++) { - con->DebugPrintf(" Node %03x: ", i); + con->debugPrintf(" Node %03x: ", i); if (_parserNodes[i].type == kParseTreeLeafNode) - con->DebugPrintf("Leaf: %04x\n", _parserNodes[i].value); + con->debugPrintf("Leaf: %04x\n", _parserNodes[i].value); else { // FIXME: Do we really want to print the *addresses* // of the left & right child? // Note that one or both may be zero pointers, so we can't just // print their values. - con->DebugPrintf("Branch: ->%p, ->%p\n", + con->debugPrintf("Branch: ->%p, ->%p\n", (const void *)_parserNodes[i].left, (const void *)_parserNodes[i].right); } @@ -694,11 +694,11 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c return *pos; } if (type == kParseEndOfInput) { - con->DebugPrintf("Unbalanced parentheses\n"); + con->debugPrintf("Unbalanced parentheses\n"); return -1; } if (type == kParseClosingParenthesis) { - con->DebugPrintf("Syntax error at token %d\n", *i); + con->debugPrintf("Syntax error at token %d\n", *i); return -1; } @@ -735,7 +735,7 @@ int Vocabulary::parseNodes(int *i, int *pos, int type, int nr, int argc, const c const char *token = argv[(*i)++]; if (strcmp(token, ")")) - con->DebugPrintf("Expected ')' at token %d\n", *i); + con->debugPrintf("Expected ')' at token %d\n", *i); return oldPos; } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 97675a140e..362cca699d 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -142,6 +142,8 @@ void SciMusic::init() { _driverLastChannel = _pMidiDrv->getLastChannel(); if (getSciVersion() <= SCI_VERSION_0_LATE) _globalReverb = _pMidiDrv->getReverb(); // Init global reverb for SCI0 + + _currentlyPlayingSample = NULL; } void SciMusic::miditimerCallback(void *p) { @@ -432,6 +434,17 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if (pSnd->pStreamAud) { if (!_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) { + if ((_currentlyPlayingSample) && (_pMixer->isSoundHandleActive(_currentlyPlayingSample->hCurrentAud))) { + // Another sample is already playing, we have to stop that one + // SSCI is only able to play 1 sample at a time + // In Space Quest 5 room 250 the player is able to open the air-hatch and kill himself. + // In that situation the scripts are playing 2 samples at the same time and the first sample + // is not supposed to play. + // TODO: SSCI actually calls kDoAudio(play) internally, which stops other samples from being played + // but such a change isn't trivial, because we also handle Sound resources in here, that contain samples + _pMixer->stopHandle(_currentlyPlayingSample->hCurrentAud); + warning("kDoSound: sample already playing, old resource %d, new resource %d", _currentlyPlayingSample->resourceId, pSnd->resourceId); + } // Sierra SCI ignores volume set when playing samples via kDoSound // At least freddy pharkas/CD has a script bug that sets volume to 0 // when playing the "score" sample @@ -449,6 +462,8 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pStreamAud, -1, _pMixer->kMaxChannelVolume, 0, DisposeAfterUse::NO); } + // Remember the sample, that is now playing + _currentlyPlayingSample = pSnd; } } else { if (pSnd->pMidiParser) { @@ -495,8 +510,11 @@ void SciMusic::soundStop(MusicEntry *pSnd) { pSnd->status = kSoundStopped; if (_soundVersion <= SCI_VERSION_0_LATE) pSnd->isQueued = false; - if (pSnd->pStreamAud) + if (pSnd->pStreamAud) { + if (_currentlyPlayingSample == pSnd) + _currentlyPlayingSample = NULL; _pMixer->stopHandle(pSnd->hCurrentAud); + } if (pSnd->pMidiParser) { Common::StackLock lock(_mutex); @@ -556,6 +574,10 @@ void SciMusic::soundKill(MusicEntry *pSnd) { _mutex.unlock(); if (pSnd->pStreamAud) { + if (_currentlyPlayingSample == pSnd) { + // Forget about this sound, in case it was currently playing + _currentlyPlayingSample = NULL; + } _pMixer->stopHandle(pSnd->hCurrentAud); delete pSnd->pStreamAud; pSnd->pStreamAud = NULL; @@ -666,7 +688,7 @@ void SciMusic::printPlayList(Console *con) { for (uint32 i = 0; i < _playList.size(); i++) { MusicEntry *song = _playList[i]; - con->DebugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n", + con->debugPrintf("%d: %04x:%04x (%s), resource id: %d, status: %s, %s type\n", i, PRINT_REG(song->soundObj), g_sci->getEngineState()->_segMan->getObjectName(song->soundObj), song->resourceId, musicStatus[song->status], @@ -683,26 +705,26 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) { for (MusicList::iterator i = _playList.begin(); i != end; ++i) { MusicEntry *song = *i; if (song->soundObj == obj) { - con->DebugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]); - con->DebugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop); - con->DebugPrintf("signal: %d, priority: %d\n", song->signal, song->priority); - con->DebugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume); + con->debugPrintf("Resource id: %d, status: %s\n", song->resourceId, musicStatus[song->status]); + con->debugPrintf("dataInc: %d, hold: %d, loop: %d\n", song->dataInc, song->hold, song->loop); + con->debugPrintf("signal: %d, priority: %d\n", song->signal, song->priority); + con->debugPrintf("ticker: %d, volume: %d\n", song->ticker, song->volume); if (song->pMidiParser) { - con->DebugPrintf("Type: MIDI\n"); + con->debugPrintf("Type: MIDI\n"); if (song->soundRes) { SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId()); - con->DebugPrintf("Channels: %d\n", track->channelCount); + con->debugPrintf("Channels: %d\n", track->channelCount); } } else if (song->pStreamAud || song->pLoopStream) { - con->DebugPrintf("Type: digital audio (%s), sound active: %s\n", + con->debugPrintf("Type: digital audio (%s), sound active: %s\n", song->pStreamAud ? "non looping" : "looping", _pMixer->isSoundHandleActive(song->hCurrentAud) ? "yes" : "no"); if (song->soundRes) { - con->DebugPrintf("Sound resource information:\n"); + con->debugPrintf("Sound resource information:\n"); SoundResource::Track *track = song->soundRes->getTrackByType(_pMidiDrv->getPlayId()); if (track && track->digitalChannelNr != -1) { - con->DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", + con->debugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); } } @@ -712,7 +734,7 @@ void SciMusic::printSongInfo(reg_t obj, Console *con) { } } - con->DebugPrintf("Song object not found in playlist"); + con->debugPrintf("Song object not found in playlist"); } MusicEntry::MusicEntry() { @@ -1169,8 +1191,14 @@ ChannelRemapping *SciMusic::determineChannelMap() { int neededVoices = channel._voices; // do we have enough free voices? - // We only care for essential channels - if (map->_freeVoices < neededVoices && prio > 0) { + if (map->_freeVoices < neededVoices) { + // We only care for essential channels + if (prio > 0) { +#ifdef DEBUG_REMAP + debug(" not enough voices; need %d, have %d. Skipping this channel.", neededVoices, map->_freeVoices); +#endif + continue; + } do { int j = map->lowestPrio(); if (j == -1) { diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index bfc542d2a5..6149bb799e 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -264,6 +264,8 @@ private: int _driverFirstChannel; int _driverLastChannel; + + MusicEntry *_currentlyPlayingSample; }; } // End of namespace Sci diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp index a792d63149..2b718b2cfe 100644 --- a/engines/scumm/debugger.cpp +++ b/engines/scumm/debugger.cpp @@ -58,52 +58,63 @@ ScummDebugger::ScummDebugger(ScummEngine *s) _vm = s; // Register variables - DVar_Register("scumm_speed", &_vm->_fastMode, DVAR_BYTE, 0); - DVar_Register("scumm_room", &_vm->_currentRoom, DVAR_BYTE, 0); - DVar_Register("scumm_roomresource", &_vm->_roomResource, DVAR_INT, 0); - DVar_Register("scumm_vars", &_vm->_scummVars, DVAR_INTARRAY, _vm->_numVariables); + registerVar("scumm_speed", &_vm->_fastMode); + registerVar("scumm_room", &_vm->_currentRoom); + registerVar("scumm_roomresource", &_vm->_roomResource); + registerVar("scumm_vars", &_vm->_scummVars, _vm->_numVariables); // Register commands - DCmd_Register("continue", WRAP_METHOD(ScummDebugger, Cmd_Exit)); - DCmd_Register("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart)); - - DCmd_Register("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor)); - DCmd_Register("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor)); - DCmd_Register("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox)); - DCmd_Register("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix)); - DCmd_Register("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera)); - DCmd_Register("room", WRAP_METHOD(ScummDebugger, Cmd_Room)); - DCmd_Register("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects)); - DCmd_Register("object", WRAP_METHOD(ScummDebugger, Cmd_Object)); - DCmd_Register("script", WRAP_METHOD(ScummDebugger, Cmd_Script)); - DCmd_Register("scr", WRAP_METHOD(ScummDebugger, Cmd_Script)); - DCmd_Register("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript)); - DCmd_Register("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes)); + registerCmd("continue", WRAP_METHOD(ScummDebugger, cmdExit)); + registerCmd("restart", WRAP_METHOD(ScummDebugger, Cmd_Restart)); + + registerCmd("actor", WRAP_METHOD(ScummDebugger, Cmd_Actor)); + registerCmd("actors", WRAP_METHOD(ScummDebugger, Cmd_PrintActor)); + registerCmd("box", WRAP_METHOD(ScummDebugger, Cmd_PrintBox)); + registerCmd("matrix", WRAP_METHOD(ScummDebugger, Cmd_PrintBoxMatrix)); + registerCmd("camera", WRAP_METHOD(ScummDebugger, Cmd_Camera)); + registerCmd("room", WRAP_METHOD(ScummDebugger, Cmd_Room)); + registerCmd("objects", WRAP_METHOD(ScummDebugger, Cmd_PrintObjects)); + registerCmd("object", WRAP_METHOD(ScummDebugger, Cmd_Object)); + registerCmd("script", WRAP_METHOD(ScummDebugger, Cmd_Script)); + registerCmd("scr", WRAP_METHOD(ScummDebugger, Cmd_Script)); + registerCmd("scripts", WRAP_METHOD(ScummDebugger, Cmd_PrintScript)); + registerCmd("importres", WRAP_METHOD(ScummDebugger, Cmd_ImportRes)); if (_vm->_game.id == GID_LOOM) - DCmd_Register("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft)); + registerCmd("drafts", WRAP_METHOD(ScummDebugger, Cmd_PrintDraft)); if (_vm->_game.id == GID_MONKEY && _vm->_game.platform == Common::kPlatformSegaCD) - DCmd_Register("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode)); + registerCmd("passcode", WRAP_METHOD(ScummDebugger, Cmd_Passcode)); - DCmd_Register("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame)); - DCmd_Register("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame)); + registerCmd("loadgame", WRAP_METHOD(ScummDebugger, Cmd_LoadGame)); + registerCmd("savegame", WRAP_METHOD(ScummDebugger, Cmd_SaveGame)); - DCmd_Register("level", WRAP_METHOD(ScummDebugger, Cmd_DebugLevel)); - DCmd_Register("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug)); + registerCmd("debug", WRAP_METHOD(ScummDebugger, Cmd_Debug)); - DCmd_Register("show", WRAP_METHOD(ScummDebugger, Cmd_Show)); - DCmd_Register("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide)); + registerCmd("show", WRAP_METHOD(ScummDebugger, Cmd_Show)); + registerCmd("hide", WRAP_METHOD(ScummDebugger, Cmd_Hide)); - DCmd_Register("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse)); + registerCmd("imuse", WRAP_METHOD(ScummDebugger, Cmd_IMuse)); - DCmd_Register("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors)); + registerCmd("resetcursors", WRAP_METHOD(ScummDebugger, Cmd_ResetCursors)); } ScummDebugger::~ScummDebugger() { // we need this destructor, even if it is empty, for __SYMBIAN32__ } +void ScummDebugger::preEnter() { +} + +void ScummDebugger::postEnter() { + // Runtime debug level change is dealt with by the base class "debuglevel" command + // but need to ensure that the _debugMode parameter is updated in sync. + _vm->_debugMode = (gDebugLevel >= 0); + // Boot params often need debugging switched on to work + if (_vm->_bootParam) + _vm->_debugMode = true; +} + /////////////////////////////////////////////////// // Now the fun stuff: @@ -117,51 +128,51 @@ bool ScummDebugger::Cmd_Restart(int argc, const char **argv) { bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) { if (!_vm->_imuse && !_vm->_musicEngine) { - DebugPrintf("No iMuse engine is active.\n"); + debugPrintf("No iMuse engine is active.\n"); return true; } if (argc > 1) { if (!strcmp(argv[1], "panic")) { _vm->_musicEngine->stopAllSounds(); - DebugPrintf("AAAIIIEEEEEE!\n"); - DebugPrintf("Shutting down all music tracks\n"); + debugPrintf("AAAIIIEEEEEE!\n"); + debugPrintf("Shutting down all music tracks\n"); return true; } else if (!strcmp(argv[1], "play")) { if (argc > 2 && (!strcmp(argv[2], "random") || atoi(argv[2]) != 0)) { int sound = atoi(argv[2]); if (!strcmp(argv[2], "random")) { - DebugPrintf("Selecting from %d songs...\n", _vm->_numSounds); + debugPrintf("Selecting from %d songs...\n", _vm->_numSounds); sound = _vm->_rnd.getRandomNumber(_vm->_numSounds); } _vm->ensureResourceLoaded(rtSound, sound); _vm->_musicEngine->startSound(sound); - DebugPrintf("Attempted to start music %d.\n", sound); + debugPrintf("Attempted to start music %d.\n", sound); } else { - DebugPrintf("Specify a music resource # from 1-255.\n"); + debugPrintf("Specify a music resource # from 1-255.\n"); } return true; } else if (!strcmp(argv[1], "stop")) { if (argc > 2 && (!strcmp(argv[2], "all") || atoi(argv[2]) != 0)) { if (!strcmp(argv[2], "all")) { _vm->_musicEngine->stopAllSounds(); - DebugPrintf("Shutting down all music tracks.\n"); + debugPrintf("Shutting down all music tracks.\n"); } else { _vm->_musicEngine->stopSound(atoi(argv[2])); - DebugPrintf("Attempted to stop music %d.\n", atoi(argv[2])); + debugPrintf("Attempted to stop music %d.\n", atoi(argv[2])); } } else { - DebugPrintf("Specify a music resource # or \"all\".\n"); + debugPrintf("Specify a music resource # or \"all\".\n"); } return true; } } - DebugPrintf("Available iMuse commands:\n"); - DebugPrintf(" panic - Stop all music tracks\n"); - DebugPrintf(" play # - Play a music resource\n"); - DebugPrintf(" stop # - Stop a music resource\n"); + debugPrintf("Available iMuse commands:\n"); + debugPrintf(" panic - Stop all music tracks\n"); + debugPrintf(" play # - Play a music resource\n"); + debugPrintf(" stop # - Stop a music resource\n"); return true; } @@ -174,7 +185,7 @@ bool ScummDebugger::Cmd_Room(int argc, const char **argv) { _vm->_fullRedraw = true; return false; } else { - DebugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource); + debugPrintf("Current room: %d [%d] - use 'room <roomnum>' to switch\n", _vm->_currentRoom, _vm->_roomResource); return true; } } @@ -189,7 +200,7 @@ bool ScummDebugger::Cmd_LoadGame(int argc, const char **argv) { return false; } - DebugPrintf("Syntax: loadgame <slotnum>\n"); + debugPrintf("Syntax: loadgame <slotnum>\n"); return true; } @@ -199,7 +210,7 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) { _vm->requestSave(slot, argv[2]); } else - DebugPrintf("Syntax: savegame <slotnum> <name>\n"); + debugPrintf("Syntax: savegame <slotnum> <name>\n"); return true; } @@ -207,18 +218,18 @@ bool ScummDebugger::Cmd_SaveGame(int argc, const char **argv) { bool ScummDebugger::Cmd_Show(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: show <parameter>\n"); + debugPrintf("Syntax: show <parameter>\n"); return true; } if (!strcmp(argv[1], "hex")) { _vm->_hexdumpScripts = true; - DebugPrintf("Script hex dumping on\n"); + debugPrintf("Script hex dumping on\n"); } else if (!strncmp(argv[1], "sta", 3)) { _vm->_showStack = 1; - DebugPrintf("Stack tracing on\n"); + debugPrintf("Stack tracing on\n"); } else { - DebugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]); + debugPrintf("Unknown show parameter '%s'\nParameters are 'hex' for hex dumping and 'sta' for stack tracing\n", argv[1]); } return true; } @@ -226,18 +237,18 @@ bool ScummDebugger::Cmd_Show(int argc, const char **argv) { bool ScummDebugger::Cmd_Hide(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Syntax: hide <parameter>\n"); + debugPrintf("Syntax: hide <parameter>\n"); return true; } if (!strcmp(argv[1], "hex")) { _vm->_hexdumpScripts = false; - DebugPrintf("Script hex dumping off\n"); + debugPrintf("Script hex dumping off\n"); } else if (!strncmp(argv[1], "sta", 3)) { _vm->_showStack = 0; - DebugPrintf("Stack tracing off\n"); + debugPrintf("Stack tracing off\n"); } else { - DebugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]); + debugPrintf("Unknown hide parameter '%s'\nParameters are 'hex' to turn off hex dumping and 'sta' to turn off stack tracing\n", argv[1]); } return true; } @@ -246,7 +257,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { int scriptnum; if (argc < 2) { - DebugPrintf("Syntax: script <scriptnum> <command>\n"); + debugPrintf("Syntax: script <scriptnum> <command>\n"); return true; } @@ -254,7 +265,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { // FIXME: what is the max range on these? // if (scriptnum >= _vm->_numScripts) { - // DebugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts); + // debugPrintf("Script number %d is out of range (range: 1 - %d)\n", scriptnum, _vm->_numScripts); // return true; //} @@ -264,7 +275,7 @@ bool ScummDebugger::Cmd_Script(int argc, const char** argv) { _vm->runScript(scriptnum, 0, 0, 0); return false; } else { - DebugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]); + debugPrintf("Unknown script command '%s'\nUse <kill/stop | run/start> as command\n", argv[2]); } return true; @@ -276,7 +287,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { int resnum; if (argc != 4) { - DebugPrintf("Syntax: importres <restype> <filename> <resnum>\n"); + debugPrintf("Syntax: importres <restype> <filename> <resnum>\n"); return true; } @@ -286,7 +297,7 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { if (!strncmp(argv[1], "scr", 3)) { file.open(argv[2]); if (file.isOpen() == false) { - DebugPrintf("Could not open file %s\n", argv[2]); + debugPrintf("Could not open file %s\n", argv[2]); return true; } if (_vm->_game.features & GF_SMALL_HEADER) { @@ -307,25 +318,25 @@ bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) { file.read(_vm->_res->createResource(rtScript, resnum, size), size); } else - DebugPrintf("Unknown importres type '%s'\n", argv[1]); + debugPrintf("Unknown importres type '%s'\n", argv[1]); return true; } bool ScummDebugger::Cmd_PrintScript(int argc, const char **argv) { int i; ScriptSlot *ss = _vm->vm.slot; - DebugPrintf("+-----------------------------------+\n"); - DebugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n"); - DebugPrintf("+--+----+-----+---+---+--+---+--+---+\n"); + debugPrintf("+-----------------------------------+\n"); + debugPrintf("|# | num|offst|sta|typ|fr|rec|fc|cut|\n"); + debugPrintf("+--+----+-----+---+---+--+---+--+---+\n"); for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) { if (ss->number) { - DebugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n", + debugPrintf("|%2d|%4d|%05x|%3d|%3d|%2d|%3d|%2d|%3d|\n", i, ss->number, ss->offs, ss->status, ss->where, ss->freezeResistant, ss->recursive, ss->freezeCount, ss->cutsceneOverride); } } - DebugPrintf("+-----------------------------------+\n"); + debugPrintf("+-----------------------------------+\n"); return true; } @@ -336,13 +347,13 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { int value = 0, value2 = 0; if (argc < 3) { - DebugPrintf("Syntax: actor <actornum> <command> <parameter>\n"); + debugPrintf("Syntax: actor <actornum> <command> <parameter>\n"); return true; } actnum = atoi(argv[1]); if (actnum >= _vm->_numActors) { - DebugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors); + debugPrintf("Actor %d is out of range (range: 1 - %d)\n", actnum, _vm->_numActors); return true; } @@ -354,43 +365,43 @@ bool ScummDebugger::Cmd_Actor(int argc, const char **argv) { if (!strcmp(argv[2], "animvar")) { a->setAnimVar(value, value2); - DebugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value)); + debugPrintf("Actor[%d].animVar[%d] = %d\n", actnum, value, a->getAnimVar(value)); } else if (!strcmp(argv[2], "anim")) { a->animateActor(value); - DebugPrintf("Actor[%d].animateActor(%d)\n", actnum, value); + debugPrintf("Actor[%d].animateActor(%d)\n", actnum, value); } else if (!strcmp(argv[2], "ignoreboxes")) { a->_ignoreBoxes = (value > 0); - DebugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes); + debugPrintf("Actor[%d].ignoreBoxes = %d\n", actnum, a->_ignoreBoxes); } else if (!strcmp(argv[2], "x")) { a->putActor(value, a->getRealPos().y); - DebugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x); + debugPrintf("Actor[%d].x = %d\n", actnum, a->getRealPos().x); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "y")) { a->putActor(a->getRealPos().x, value); - DebugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y); + debugPrintf("Actor[%d].y = %d\n", actnum, a->getRealPos().y); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "_elevation")) { a->setElevation(value); - DebugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation()); + debugPrintf("Actor[%d]._elevation = %d\n", actnum, a->getElevation()); _vm->_fullRedraw = true; } else if (!strcmp(argv[2], "costume")) { if (value >= (int)_vm->_res->_types[rtCostume].size()) - DebugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size()); + debugPrintf("Costume not changed as %d exceeds max of %d\n", value, _vm->_res->_types[rtCostume].size()); else { a->setActorCostume(value); _vm->_fullRedraw = true; - DebugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume); + debugPrintf("Actor[%d].costume = %d\n", actnum, a->_costume); } } else if (!strcmp(argv[2], "name")) { - DebugPrintf("Name of actor %d: %s\n", actnum, + debugPrintf("Name of actor %d: %s\n", actnum, _vm->getObjOrActorName(_vm->actorToObj(actnum))); } else if (!strcmp(argv[2], "condmask")) { if (argc > 3) { a->_heCondMask = value; } - DebugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask); + debugPrintf("Actor[%d]._heCondMask = 0x%X\n", actnum, a->_heCondMask); } else { - DebugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]); + debugPrintf("Unknown actor command '%s'\nUse <ignoreboxes |costume> as command\n", argv[2]); } return true; @@ -400,40 +411,40 @@ bool ScummDebugger::Cmd_PrintActor(int argc, const char **argv) { int i; Actor *a; - DebugPrintf("+---------------------------------------------------------------+\n"); - DebugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n"); - DebugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n"); + debugPrintf("+---------------------------------------------------------------+\n"); + debugPrintf("|# | x | y | w | h |elev|cos|box|mov| zp|frm|scl|dir| cls |\n"); + debugPrintf("+--+----+----+---+---+----+---+---+---+---+---+---+---+---------+\n"); for (i = 1; i < _vm->_numActors; i++) { a = _vm->_actors[i]; if (a->_visible) - DebugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n", + debugPrintf("|%2d|%4d|%4d|%3d|%3d|%4d|%3d|%3d|%3d|%3d|%3d|%3d|%3d|$%08x|\n", a->_number, a->getRealPos().x, a->getRealPos().y, a->_width, a->_bottom - a->_top, a->getElevation(), a->_costume, a->_walkbox, a->_moving, a->_forceClip, a->_frame, a->_scalex, a->getFacing(), _vm->_classData[a->_number]); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } bool ScummDebugger::Cmd_PrintObjects(int argc, const char **argv) { int i; ObjectData *o; - DebugPrintf("Objects in current room\n"); - DebugPrintf("+---------------------------------+------------+\n"); - DebugPrintf("|num | x | y |width|height|state|fl| cls |\n"); - DebugPrintf("+----+----+----+-----+------+-----+--+---------+\n"); + debugPrintf("Objects in current room\n"); + debugPrintf("+---------------------------------+------------+\n"); + debugPrintf("|num | x | y |width|height|state|fl| cls |\n"); + debugPrintf("+----+----+----+-----+------+-----+--+---------+\n"); for (i = 1; i < _vm->_numLocalObjects; i++) { o = &(_vm->_objs[i]); if (o->obj_nr == 0) continue; int classData = (_vm->_game.version != 0 ? _vm->_classData[o->obj_nr] : 0); - DebugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n", + debugPrintf("|%4d|%4d|%4d|%5d|%6d|%5d|%2d|$%08x|\n", o->obj_nr, o->x_pos, o->y_pos, o->width, o->height, o->state, o->fl_object_index, classData); } - DebugPrintf("\n"); + debugPrintf("\n"); return true; } @@ -443,13 +454,13 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { int obj; if (argc < 3) { - DebugPrintf("Syntax: object <objectnum> <command> <parameter>\n"); + debugPrintf("Syntax: object <objectnum> <command> <parameter>\n"); return true; } obj = atoi(argv[1]); if (_vm->_game.version != 0 && obj >= _vm->_numGlobalObjects) { - DebugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects); + debugPrintf("Object %d is out of range (range: 1 - %d)\n", obj, _vm->_numGlobalObjects); return true; } @@ -479,12 +490,12 @@ bool ScummDebugger::Cmd_Object(int argc, const char **argv) { //is BgNeedsRedraw enough? _vm->_bgNeedsRedraw = true; } else { - DebugPrintf("State of object %d: %d\n", obj, _vm->getState(obj)); + debugPrintf("State of object %d: %d\n", obj, _vm->getState(obj)); } } else if (!strcmp(argv[2], "name")) { - DebugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj)); + debugPrintf("Name of object %d: %s\n", obj, _vm->getObjOrActorName(obj)); } else { - DebugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]); + debugPrintf("Unknown object command '%s'\nUse <pickup | state | name> as command\n", argv[2]); } return true; @@ -495,9 +506,9 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { // No parameters given: Print out a list of all channels and their status if (argc <= 1) { - DebugPrintf("Available debug channels:\n"); + debugPrintf("Available debug channels:\n"); for (Common::DebugManager::DebugChannelList::const_iterator i = lvls.begin(); i != lvls.end(); ++i) { - DebugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', + debugPrintf("%c%s - %s (%s)\n", i->enabled ? '+' : ' ', i->name.c_str(), i->description.c_str(), i->enabled ? "enabled" : "disabled"); } @@ -513,39 +524,18 @@ bool ScummDebugger::Cmd_Debug(int argc, const char **argv) { } if (result) { - DebugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1); + debugPrintf("%s %s\n", (argv[1][0] == '+') ? "Enabled" : "Disabled", argv[1] + 1); } else { - DebugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n"); - DebugPrintf("Enables or disables the given debug channel.\n"); - DebugPrintf("When used without parameters, lists all available debug channels and their status.\n"); - } - - return true; -} - -bool ScummDebugger::Cmd_DebugLevel(int argc, const char **argv) { - if (argc == 1) { - if (_vm->_debugMode == false) - DebugPrintf("Debugging is not enabled at this time\n"); - else - DebugPrintf("Debugging is currently set at level %d\n", gDebugLevel); - } else { // set level - gDebugLevel = atoi(argv[1]); - if (gDebugLevel >= 0) { - _vm->_debugMode = true; - DebugPrintf("Debug level set to level %d\n", gDebugLevel); - } else if (gDebugLevel < 0) { - _vm->_debugMode = false; - DebugPrintf("Debugging is now disabled\n"); - } else - DebugPrintf("Not a valid debug level\n"); + debugPrintf("Usage: debug [+CHANNEL|-CHANNEL]\n"); + debugPrintf("Enables or disables the given debug channel.\n"); + debugPrintf("When used without parameters, lists all available debug channels and their status.\n"); } return true; } bool ScummDebugger::Cmd_Camera(int argc, const char **argv) { - DebugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n", + debugPrintf("Camera: cur (%d,%d) - dest (%d,%d) - accel (%d,%d) -- last (%d,%d)\n", _vm->camera._cur.x, _vm->camera._cur.y, _vm->camera._dest.x, _vm->camera._dest.y, _vm->camera._accel.x, _vm->camera._accel.y, _vm->camera._last.x, _vm->camera._last.y); @@ -560,7 +550,7 @@ bool ScummDebugger::Cmd_PrintBox(int argc, const char **argv) { printBox(atoi(argv[i])); } else { num = _vm->getNumBoxes(); - DebugPrintf("\nWalk boxes:\n"); + debugPrintf("\nWalk boxes:\n"); for (i = 0; i < num; i++) printBox(i); } @@ -572,29 +562,29 @@ bool ScummDebugger::Cmd_PrintBoxMatrix(int argc, const char **argv) { int num = _vm->getNumBoxes(); int i, j; - DebugPrintf("Walk matrix:\n"); + debugPrintf("Walk matrix:\n"); if (_vm->_game.version <= 2) boxm += num; for (i = 0; i < num; i++) { - DebugPrintf("%d: ", i); + debugPrintf("%d: ", i); if (_vm->_game.version <= 2) { for (j = 0; j < num; j++) - DebugPrintf("[%d] ", *boxm++); + debugPrintf("[%d] ", *boxm++); } else { while (*boxm != 0xFF) { - DebugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]); + debugPrintf("[%d-%d=>%d] ", boxm[0], boxm[1], boxm[2]); boxm += 3; } boxm++; } - DebugPrintf("\n"); + debugPrintf("\n"); } return true; } void ScummDebugger::printBox(int box) { if (box < 0 || box >= _vm->getNumBoxes()) { - DebugPrintf("%d is not a valid box!\n", box); + debugPrintf("%d is not a valid box!\n", box); return; } BoxCoords coords; @@ -605,7 +595,7 @@ void ScummDebugger::printBox(int box) { coords = _vm->getBoxCoordinates(box); // Print out coords, flags, zbuffer mask - DebugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n", + debugPrintf("%d: [%d x %d] [%d x %d] [%d x %d] [%d x %d], flags=0x%02x, mask=%d, scale=%d\n", box, coords.ul.x, coords.ul.y, coords.ll.x, coords.ll.y, coords.ur.x, coords.ur.y, coords.lr.x, coords.lr.y, @@ -746,7 +736,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { int i, base, draft; if (_vm->_game.id != GID_LOOM) { - DebugPrintf("Command only works with Loom/LoomCD\n"); + debugPrintf("Command only works with Loom/LoomCD\n"); return true; } @@ -797,7 +787,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { // the distaff, but I don't know if that's a safe // thing to do. - DebugPrintf("Learned all drafts and notes.\n"); + debugPrintf("Learned all drafts and notes.\n"); return true; } } @@ -806,7 +796,7 @@ bool ScummDebugger::Cmd_PrintDraft(int argc, const char **argv) { for (i = 0; i < 16; i++) { draft = _vm->_scummVars[base + i * 2]; - DebugPrintf("%d %-13s %c%c%c%c %c%c\n", + debugPrintf("%d %-13s %c%c%c%c %c%c\n", base + 2 * i, names[i], notes[draft & 0x0007], @@ -830,7 +820,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) { _vm->runScript(61, 0, 0, args); if (_vm->_bootParam != _vm->_scummVars[411]){ - DebugPrintf("Invalid Passcode\n"); + debugPrintf("Invalid Passcode\n"); return true; } @@ -838,7 +828,7 @@ bool ScummDebugger::Cmd_Passcode(int argc, const char **argv) { detach(); } else { - DebugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]); + debugPrintf("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]); return true; } return false; diff --git a/engines/scumm/debugger.h b/engines/scumm/debugger.h index 43bf9d6fd4..657f6be286 100644 --- a/engines/scumm/debugger.h +++ b/engines/scumm/debugger.h @@ -37,6 +37,9 @@ public: private: ScummEngine *_vm; + virtual void preEnter(); + virtual void postEnter(); + // Commands bool Cmd_Room(int argc, const char **argv); bool Cmd_LoadGame(int argc, const char **argv); @@ -58,7 +61,6 @@ private: bool Cmd_Passcode(int argc, const char **argv); bool Cmd_Debug(int argc, const char **argv); - bool Cmd_DebugLevel(int argc, const char **argv); bool Cmd_Show(int argc, const char **argv); bool Cmd_Hide(int argc, const char **argv); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 54f22ecad3..34c231e5d4 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -205,7 +205,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _lastInputScriptTime = 0; _bootParam = 0; _dumpScripts = false; - _debugMode = 0; + _debugMode = false; _objectOwnerTable = NULL; _objectRoomTable = NULL; _objectStateTable = NULL; @@ -2281,7 +2281,7 @@ void ScummEngine::scummLoop_updateScummVars() { VAR(VAR_MOUSE_Y) = _mouse.y; if (VAR_DEBUGMODE != 0xFF) { // This is NOT for the Mac version of Indy3/Loom - VAR(VAR_DEBUGMODE) = _debugMode; + VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0); } } else if (_game.version >= 1) { // We use shifts below instead of dividing by V12_X_MULTIPLIER resp. diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index b4afa09bb2..be5a83d8c9 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -586,7 +586,7 @@ protected: bool _dumpScripts; bool _hexdumpScripts; bool _showStack; - uint16 _debugMode; + bool _debugMode; // Save/Load class - some of this may be GUI byte _saveLoadFlag, _saveLoadSlot; diff --git a/engines/scumm/vars.cpp b/engines/scumm/vars.cpp index 73028c8513..79d7ed03da 100644 --- a/engines/scumm/vars.cpp +++ b/engines/scumm/vars.cpp @@ -805,7 +805,7 @@ void ScummEngine::resetScummVars() { } if (VAR_DEBUGMODE != 0xFF) { - VAR(VAR_DEBUGMODE) = _debugMode; + VAR(VAR_DEBUGMODE) = (_debugMode ? 1 : 0); if (_game.heversion >= 80 && _debugMode) VAR(85) = 1; } diff --git a/engines/sky/debug.cpp b/engines/sky/debug.cpp index 63da42eec2..d663bd206d 100644 --- a/engines/sky/debug.cpp +++ b/engines/sky/debug.cpp @@ -1087,14 +1087,14 @@ void Debug::mcode(uint32 mcode, uint32 a, uint32 b, uint32 c) { Debugger::Debugger(Logic *logic, Mouse *mouse, Screen *screen, SkyCompact *skyCompact) : GUI::Debugger(), _logic(logic), _mouse(mouse), _screen(screen), _skyCompact(skyCompact), _showGrid(false) { - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid)); - DCmd_Register("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid)); - DCmd_Register("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact)); - DCmd_Register("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand)); - DCmd_Register("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar)); - DCmd_Register("section", WRAP_METHOD(Debugger, Cmd_Section)); - DCmd_Register("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("showgrid", WRAP_METHOD(Debugger, Cmd_ShowGrid)); + registerCmd("reloadgrid", WRAP_METHOD(Debugger, Cmd_ReloadGrid)); + registerCmd("compact", WRAP_METHOD(Debugger, Cmd_ShowCompact)); + registerCmd("logiccmd", WRAP_METHOD(Debugger, Cmd_LogicCommand)); + registerCmd("scriptvar", WRAP_METHOD(Debugger, Cmd_ScriptVar)); + registerCmd("section", WRAP_METHOD(Debugger, Cmd_Section)); + registerCmd("logiclist", WRAP_METHOD(Debugger, Cmd_LogicList)); } Debugger::~Debugger() {} // we need this here for __SYMBIAN32__ @@ -1119,14 +1119,14 @@ static bool isNumeric(const char *arg) { bool Debugger::Cmd_ShowGrid(int argc, const char **argv) { _showGrid = !_showGrid; - DebugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); + debugPrintf("Show grid: %s\n", _showGrid ? "On" : "Off"); if (!_showGrid) _screen->forceRefresh(); return true; } bool Debugger::Cmd_ReloadGrid(int argc, const char **argv) { _logic->_skyGrid->loadGrids(); - DebugPrintf("Grid reloaded\n"); + debugPrintf("Grid reloaded\n"); return true; } @@ -1143,35 +1143,35 @@ void Debugger::dumpCompact(uint16 cptId) { Compact *cpt = _skyCompact->fetchCptInfo(cptId, &size, &type, name); if (type == COMPACT) { - DebugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF); - DebugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown"); - DebugPrintf("status : %04X\n", cpt->status); - DebugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]); - DebugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]); - DebugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]); - DebugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]); - DebugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]); - DebugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]); - DebugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]); - DebugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]); - DebugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]); - DebugPrintf("sync : %04X\n", cpt->sync); - DebugPrintf("screen : %d\n", cpt->screen); + debugPrintf("Compact %s: id = %04X, section %d, id %d\n", name, cptId, cptId >> 12, cptId & 0xFFF); + debugPrintf("logic : %04X: %s\n", cpt->logic, (cpt->logic <= 16) ? logicTypes[cpt->logic] : "unknown"); + debugPrintf("status : %04X\n", cpt->status); + debugPrintf(" : background : %s\n", noYes[(cpt->status & ST_BACKGROUND) >> 0]); + debugPrintf(" : foreground : %s\n", noYes[(cpt->status & ST_FOREGROUND) >> 1]); + debugPrintf(" : sort list : %s\n", noYes[(cpt->status & ST_SORT) >> 2]); + debugPrintf(" : recreate : %s\n", noYes[(cpt->status & ST_RECREATE) >> 3]); + debugPrintf(" : mouse : %s\n", noYes[(cpt->status & ST_MOUSE) >> 4]); + debugPrintf(" : collision : %s\n", noYes[(cpt->status & ST_COLLISION) >> 5]); + debugPrintf(" : logic : %s\n", noYes[(cpt->status & ST_LOGIC) >> 6]); + debugPrintf(" : on grid : %s\n", noYes[(cpt->status & ST_GRID_PLOT) >> 7]); + debugPrintf(" : ar priority : %s\n", noYes[(cpt->status & ST_AR_PRIORITY) >> 8]); + debugPrintf("sync : %04X\n", cpt->sync); + debugPrintf("screen : %d\n", cpt->screen); _skyCompact->fetchCptInfo(cpt->place, NULL, NULL, name); - DebugPrintf("place : %04X: %s\n", cpt->place, name); + debugPrintf("place : %04X: %s\n", cpt->place, name); _skyCompact->fetchCptInfo(cpt->getToTableId, NULL, NULL, name); - DebugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name); - DebugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood); + debugPrintf("get to tab : %04X: %s\n", cpt->getToTableId, name); + debugPrintf("x/y : %d/%d\n", cpt->xcood, cpt->ycood); } else { - DebugPrintf("Can't dump binary data\n"); + debugPrintf("Can't dump binary data\n"); } } bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]); - DebugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]); - DebugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]); + debugPrintf("Example: \"%s foster\" dumps compact \"foster\"\n", argv[0]); + debugPrintf("Example: \"%s list 1\" lists all compacts from section 1\n", argv[0]); + debugPrintf("Example: \"%s list 1 all\" lists all entities from section 1\n", argv[0]); return true; } @@ -1181,7 +1181,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { if (argc >= 3) { sectionNumber = atoi(argv[2]); if (sectionNumber >= _skyCompact->giveNumDataLists()) { - DebugPrintf("Section number %d does not exist\n", sectionNumber); + debugPrintf("Section number %d does not exist\n", sectionNumber); return true; } if ((argc == 4) && (scumm_stricmp(argv[3], "all") == 0)) @@ -1189,14 +1189,14 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { } for (int sec = 0; sec < _skyCompact->giveNumDataLists(); sec++) { if ((sectionNumber == -1) || (sectionNumber == sec)) { - DebugPrintf("Compacts in section %d:\n", sec); + debugPrintf("Compacts in section %d:\n", sec); if (showAll) { char line[256]; char *linePos = line; for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) { if (cpt != 0) { if ((cpt % 3) == 0) { - DebugPrintf("%s\n", line); + debugPrintf("%s\n", line); linePos = line; } else linePos += sprintf(linePos, ", "); @@ -1208,7 +1208,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { linePos += sprintf(linePos, "%04X: %10s %22s", cptId, _skyCompact->nameForType(type), name); } if (linePos != line) - DebugPrintf("%s\n", line); + debugPrintf("%s\n", line); } else { for (int cpt = 0; cpt < _skyCompact->giveDataListLen(sec); cpt++) { uint16 cptId = (uint16)((sec << 12) | cpt); @@ -1216,7 +1216,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { char name[256]; _skyCompact->fetchCptInfo(cptId, &size, &type, name); if (type == COMPACT) - DebugPrintf("%04X: %s\n", cptId, name); + debugPrintf("%04X: %s\n", cptId, name); } } } @@ -1224,7 +1224,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { } else { uint16 cptId = _skyCompact->findCptId(argv[1]); if (cptId == 0) - DebugPrintf("Unknown compact: '%s'\n", argv[1]); + debugPrintf("Unknown compact: '%s'\n", argv[1]); else dumpCompact(cptId); } @@ -1233,7 +1233,7 @@ bool Debugger::Cmd_ShowCompact(int argc, const char **argv) { bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: %s fn_printf 42\n", argv[0]); + debugPrintf("Example: %s fn_printf 42\n", argv[0]); return true; } @@ -1241,7 +1241,7 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { if (0 == strcmp(argv[1], "list")) { for (int i = 0; i < numMCodes; ++i) { - DebugPrintf("%s\n", mcodes[i]); + debugPrintf("%s\n", mcodes[i]); } return true; } @@ -1264,21 +1264,21 @@ bool Debugger::Cmd_LogicCommand(int argc, const char **argv) { } } - DebugPrintf("Unknown function: '%s'\n", argv[1]); + debugPrintf("Unknown function: '%s'\n", argv[1]); return true; } bool Debugger::Cmd_Info(int argc, const char **argv) { - DebugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion); - DebugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off"); - DebugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off"); + debugPrintf("Beneath a Steel Sky version: 0.0%d\n", SkyEngine::_systemVars.gameVersion); + debugPrintf("Speech: %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_SPEECH) ? "on" : "off"); + debugPrintf("Text : %s\n", (SkyEngine::_systemVars.systemFlags & SF_ALLOW_TEXT) ? "on" : "off"); return true; } bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Example: %s lamb_friend <value>\n", argv[0]); + debugPrintf("Example: %s lamb_friend <value>\n", argv[0]); return true; } @@ -1286,7 +1286,7 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (0 == strcmp(argv[1], "list")) { for (int i = 0; i < numScriptVars; ++i) { - DebugPrintf("%s\n", scriptVars[i]); + debugPrintf("%s\n", scriptVars[i]); } return true; } @@ -1296,13 +1296,13 @@ bool Debugger::Cmd_ScriptVar(int argc, const char **argv) { if (argc == 3) { Logic::_scriptVariables[i] = atoi(argv[2]); } - DebugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]); + debugPrintf("%s = %d\n", argv[1], Logic::_scriptVariables[i]); return true; } } - DebugPrintf("Unknown ScriptVar: '%s'\n", argv[1]); + debugPrintf("Unknown ScriptVar: '%s'\n", argv[1]); return true; } @@ -1317,30 +1317,30 @@ bool Debugger::Cmd_Section(int argc, const char **argv) { _logic->fnAssignBase(ID_FOSTER, baseId[section], 0); _skyCompact->fetchCpt(ID_FOSTER)->megaSet = 0; } else { - DebugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6); + debugPrintf("Section %d is out of range (range: %d - %d)\n", section, 0, 6); } } else { - DebugPrintf("Example: %s 4\n", argv[0]); + debugPrintf("Example: %s 4\n", argv[0]); } return true; } bool Debugger::Cmd_LogicList(int argc, const char **argv) { if (argc != 1) - DebugPrintf("%s does not expect any parameters\n", argv[0]); + debugPrintf("%s does not expect any parameters\n", argv[0]); char cptName[256]; uint16 numElems, type; uint16 *logicList = (uint16 *)_skyCompact->fetchCptInfo(Logic::_scriptVariables[LOGIC_LIST_NO], &numElems, &type, cptName); - DebugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName); + debugPrintf("Current LogicList: %04X (%s)\n", Logic::_scriptVariables[LOGIC_LIST_NO], cptName); while (*logicList != 0) { if (*logicList == 0xFFFF) { uint16 newList = logicList[1]; logicList = (uint16 *)_skyCompact->fetchCptInfo(newList, &numElems, &type, cptName); - DebugPrintf("New List: %04X (%s)\n", newList, cptName); + debugPrintf("New List: %04X (%s)\n", newList, cptName); } else { _skyCompact->fetchCptInfo(*logicList, &numElems, &type, cptName); - DebugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type)); + debugPrintf(" Cpt %04X (%s) (%s)\n", *logicList, cptName, _skyCompact->nameForType(type)); logicList++; } } diff --git a/engines/sword2/console.cpp b/engines/sword2/console.cpp index 4838bd15f6..0aa78f552b 100644 --- a/engines/sword2/console.cpp +++ b/engines/sword2/console.cpp @@ -82,55 +82,55 @@ Debugger::Debugger(Sword2Engine *vm) // Register commands - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("q", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("mem", WRAP_METHOD(Debugger, Cmd_Mem)); - DCmd_Register("tony", WRAP_METHOD(Debugger, Cmd_Tony)); - DCmd_Register("res", WRAP_METHOD(Debugger, Cmd_Res)); - DCmd_Register("reslist", WRAP_METHOD(Debugger, Cmd_ResList)); - DCmd_Register("starts", WRAP_METHOD(Debugger, Cmd_Starts)); - DCmd_Register("start", WRAP_METHOD(Debugger, Cmd_Start)); - DCmd_Register("s", WRAP_METHOD(Debugger, Cmd_Start)); - DCmd_Register("info", WRAP_METHOD(Debugger, Cmd_Info)); - DCmd_Register("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid)); - DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); - DCmd_Register("player", WRAP_METHOD(Debugger, Cmd_Player)); - DCmd_Register("reslook", WRAP_METHOD(Debugger, Cmd_ResLook)); - DCmd_Register("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo)); - DCmd_Register("runlist", WRAP_METHOD(Debugger, Cmd_RunList)); - DCmd_Register("kill", WRAP_METHOD(Debugger, Cmd_Kill)); - DCmd_Register("nuke", WRAP_METHOD(Debugger, Cmd_Nuke)); - DCmd_Register("var", WRAP_METHOD(Debugger, Cmd_Var)); - DCmd_Register("rect", WRAP_METHOD(Debugger, Cmd_Rect)); - DCmd_Register("clear", WRAP_METHOD(Debugger, Cmd_Clear)); - DCmd_Register("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn)); - DCmd_Register("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff)); - DCmd_Register("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest)); - DCmd_Register("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn)); - DCmd_Register("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff)); - DCmd_Register("text", WRAP_METHOD(Debugger, Cmd_Text)); - DCmd_Register("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar)); - DCmd_Register("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar)); - DCmd_Register("version", WRAP_METHOD(Debugger, Cmd_Version)); - DCmd_Register("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest)); - DCmd_Register("texttest", WRAP_METHOD(Debugger, Cmd_TextTest)); - DCmd_Register("linetest", WRAP_METHOD(Debugger, Cmd_LineTest)); - DCmd_Register("events", WRAP_METHOD(Debugger, Cmd_Events)); - DCmd_Register("sfx", WRAP_METHOD(Debugger, Cmd_Sfx)); - DCmd_Register("english", WRAP_METHOD(Debugger, Cmd_English)); - DCmd_Register("finnish", WRAP_METHOD(Debugger, Cmd_Finnish)); - DCmd_Register("polish", WRAP_METHOD(Debugger, Cmd_Polish)); - DCmd_Register("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("q", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("mem", WRAP_METHOD(Debugger, Cmd_Mem)); + registerCmd("tony", WRAP_METHOD(Debugger, Cmd_Tony)); + registerCmd("res", WRAP_METHOD(Debugger, Cmd_Res)); + registerCmd("reslist", WRAP_METHOD(Debugger, Cmd_ResList)); + registerCmd("starts", WRAP_METHOD(Debugger, Cmd_Starts)); + registerCmd("start", WRAP_METHOD(Debugger, Cmd_Start)); + registerCmd("s", WRAP_METHOD(Debugger, Cmd_Start)); + registerCmd("info", WRAP_METHOD(Debugger, Cmd_Info)); + registerCmd("walkgrid", WRAP_METHOD(Debugger, Cmd_WalkGrid)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("player", WRAP_METHOD(Debugger, Cmd_Player)); + registerCmd("reslook", WRAP_METHOD(Debugger, Cmd_ResLook)); + registerCmd("cur", WRAP_METHOD(Debugger, Cmd_CurrentInfo)); + registerCmd("runlist", WRAP_METHOD(Debugger, Cmd_RunList)); + registerCmd("kill", WRAP_METHOD(Debugger, Cmd_Kill)); + registerCmd("nuke", WRAP_METHOD(Debugger, Cmd_Nuke)); + registerCmd("var", WRAP_METHOD(Debugger, Cmd_Var)); + registerCmd("rect", WRAP_METHOD(Debugger, Cmd_Rect)); + registerCmd("clear", WRAP_METHOD(Debugger, Cmd_Clear)); + registerCmd("debugon", WRAP_METHOD(Debugger, Cmd_DebugOn)); + registerCmd("debugoff", WRAP_METHOD(Debugger, Cmd_DebugOff)); + registerCmd("saverest", WRAP_METHOD(Debugger, Cmd_SaveRest)); + registerCmd("timeon", WRAP_METHOD(Debugger, Cmd_TimeOn)); + registerCmd("timeoff", WRAP_METHOD(Debugger, Cmd_TimeOff)); + registerCmd("text", WRAP_METHOD(Debugger, Cmd_Text)); + registerCmd("showvar", WRAP_METHOD(Debugger, Cmd_ShowVar)); + registerCmd("hidevar", WRAP_METHOD(Debugger, Cmd_HideVar)); + registerCmd("version", WRAP_METHOD(Debugger, Cmd_Version)); + registerCmd("animtest", WRAP_METHOD(Debugger, Cmd_AnimTest)); + registerCmd("texttest", WRAP_METHOD(Debugger, Cmd_TextTest)); + registerCmd("linetest", WRAP_METHOD(Debugger, Cmd_LineTest)); + registerCmd("events", WRAP_METHOD(Debugger, Cmd_Events)); + registerCmd("sfx", WRAP_METHOD(Debugger, Cmd_Sfx)); + registerCmd("english", WRAP_METHOD(Debugger, Cmd_English)); + registerCmd("finnish", WRAP_METHOD(Debugger, Cmd_Finnish)); + registerCmd("polish", WRAP_METHOD(Debugger, Cmd_Polish)); + registerCmd("fxq", WRAP_METHOD(Debugger, Cmd_FxQueue)); } void Debugger::varGet(int var) { - DebugPrintf("%d\n", _vm->_logic->readVar(var)); + debugPrintf("%d\n", _vm->_logic->readVar(var)); } void Debugger::varSet(int var, int val) { - DebugPrintf("was %d, ", _vm->_logic->readVar(var)); + debugPrintf("was %d, ", _vm->_logic->readVar(var)); _vm->_logic->writeVar(var, val); - DebugPrintf("now %d\n", _vm->_logic->readVar(var)); + debugPrintf("now %d\n", _vm->_logic->readVar(var)); } void Debugger::preEnter() { @@ -184,8 +184,8 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) { qsort(blocks, numBlocks, sizeof(MemBlock *), compare_blocks); - DebugPrintf(" size id res type name\n"); - DebugPrintf("---------------------------------------------------------------------------\n"); + debugPrintf(" size id res type name\n"); + debugPrintf("---------------------------------------------------------------------------\n"); for (i = 0; i < numBlocks; i++) { const char *type; @@ -235,21 +235,21 @@ bool Debugger::Cmd_Mem(int argc, const char **argv) { break; } - DebugPrintf("%9d %-3d %-4d %-20s %s\n", + debugPrintf("%9d %-3d %-4d %-20s %s\n", blocks[i]->size, blocks[i]->id, blocks[i]->uid, type, _vm->_resman->fetchName(blocks[i]->ptr)); } free(blocks); - DebugPrintf("---------------------------------------------------------------------------\n"); - DebugPrintf("%9d\n", _vm->_memory->getTotAlloc()); + debugPrintf("---------------------------------------------------------------------------\n"); + debugPrintf("%9d\n", _vm->_memory->getTotAlloc()); return true; } bool Debugger::Cmd_Tony(int argc, const char **argv) { - DebugPrintf("What about him?\n"); + debugPrintf("What about him?\n"); return true; } @@ -257,7 +257,7 @@ bool Debugger::Cmd_Res(int argc, const char **argv) { uint32 numClusters = _vm->_resman->getNumClusters(); if (!numClusters) { - DebugPrintf("Argh! No resources!\n"); + debugPrintf("Argh! No resources!\n"); return true; } @@ -266,10 +266,10 @@ bool Debugger::Cmd_Res(int argc, const char **argv) { for (uint i = 0; i < numClusters; i++) { const char *locStr[3] = { "HDD", "CD1", "CD2" }; - DebugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]); + debugPrintf("%-20s %s\n", resFiles[i].fileName, locStr[resFiles[i].cd]); } - DebugPrintf("%d resources\n", _vm->_resman->getNumResFiles()); + debugPrintf("%d resources\n", _vm->_resman->getNumResFiles()); return true; } @@ -285,7 +285,7 @@ bool Debugger::Cmd_ResList(int argc, const char **argv) { for (uint i = 0; i < numResFiles; i++) { if (resList[i].ptr && resList[i].refCount >= minCount) { - DebugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount); + debugPrintf("%-4d: %-35s refCount: %-3d\n", i, _vm->_resman->fetchName(resList[i].ptr), resList[i].refCount); } } @@ -296,21 +296,21 @@ bool Debugger::Cmd_Starts(int argc, const char **argv) { uint32 numStarts = _vm->getNumStarts(); if (!numStarts) { - DebugPrintf("Sorry - no startup positions registered?\n"); + debugPrintf("Sorry - no startup positions registered?\n"); uint32 numScreenManagers = _vm->getNumScreenManagers(); if (!numScreenManagers) - DebugPrintf("There is a problem with startup.inf\n"); + debugPrintf("There is a problem with startup.inf\n"); else - DebugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers); + debugPrintf(" (%d screen managers found in startup.inf)\n", numScreenManagers); return true; } StartUp *startList = _vm->getStartList(); for (uint i = 0; i < numStarts; i++) - DebugPrintf("%d (%s)\n", i, startList[i].description); + debugPrintf("%d (%s)\n", i, startList[i].description); return true; } @@ -319,25 +319,25 @@ bool Debugger::Cmd_Start(int argc, const char **argv) { uint8 pal[3] = { 255, 255, 255 }; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } uint32 numStarts = _vm->getNumStarts(); if (!numStarts) { - DebugPrintf("Sorry - there are no startups!\n"); + debugPrintf("Sorry - there are no startups!\n"); return true; } int start = atoi(argv[1]); if (start < 0 || start >= (int)numStarts) { - DebugPrintf("Not a legal start position\n"); + debugPrintf("Not a legal start position\n"); return true; } - DebugPrintf("Running start %d\n", start); + debugPrintf("Running start %d\n", start); _vm->runStart(start); _vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT); @@ -348,9 +348,9 @@ bool Debugger::Cmd_Info(int argc, const char **argv) { _displayDebugText = !_displayDebugText; if (_displayDebugText) - DebugPrintf("Info text on\n"); + debugPrintf("Info text on\n"); else - DebugPrintf("Info Text off\n"); + debugPrintf("Info Text off\n"); return true; } @@ -359,9 +359,9 @@ bool Debugger::Cmd_WalkGrid(int argc, const char **argv) { _displayWalkGrid = !_displayWalkGrid; if (_displayWalkGrid) - DebugPrintf("Walk-grid display on\n"); + debugPrintf("Walk-grid display on\n"); else - DebugPrintf("Walk-grid display off\n"); + debugPrintf("Walk-grid display off\n"); return true; } @@ -370,9 +370,9 @@ bool Debugger::Cmd_Mouse(int argc, const char **argv) { _displayMouseMarker = !_displayMouseMarker; if (_displayMouseMarker) - DebugPrintf("Mouse marker on\n"); + debugPrintf("Mouse marker on\n"); else - DebugPrintf("Mouse marker off\n"); + debugPrintf("Mouse marker off\n"); return true; } @@ -381,16 +381,16 @@ bool Debugger::Cmd_Player(int argc, const char **argv) { _displayPlayerMarker = !_displayPlayerMarker; if (_displayPlayerMarker) - DebugPrintf("Player feet marker on\n"); + debugPrintf("Player feet marker on\n"); else - DebugPrintf("Player feet marker off\n"); + debugPrintf("Player feet marker off\n"); return true; } bool Debugger::Cmd_ResLook(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -398,13 +398,13 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) { uint32 numResFiles = _vm->_resman->getNumResFiles(); if (res < 0 || res >= (int)numResFiles) { - DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", + debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", res, numResFiles, numResFiles - 1); return true; } if (!_vm->_resman->checkValid(res)) { - DebugPrintf("%d is a null & void resource number\n", res); + debugPrintf("%d is a null & void resource number\n", res); return true; } @@ -413,40 +413,40 @@ bool Debugger::Cmd_ResLook(int argc, const char **argv) { switch (type) { case ANIMATION_FILE: - DebugPrintf("<anim> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<anim> %s\n", _vm->_resman->fetchName(res)); break; case SCREEN_FILE: - DebugPrintf("<layer> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<layer> %s\n", _vm->_resman->fetchName(res)); break; case GAME_OBJECT: - DebugPrintf("<game object> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<game object> %s\n", _vm->_resman->fetchName(res)); break; case WALK_GRID_FILE: - DebugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<walk grid> %s\n", _vm->_resman->fetchName(res)); break; case GLOBAL_VAR_FILE: - DebugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<global variables> %s\n", _vm->_resman->fetchName(res)); break; case PARALLAX_FILE_null: - DebugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<parallax file NOT USED!> %s\n", _vm->_resman->fetchName(res)); break; case RUN_LIST: - DebugPrintf("<run list> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<run list> %s\n", _vm->_resman->fetchName(res)); break; case TEXT_FILE: - DebugPrintf("<text file> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<text file> %s\n", _vm->_resman->fetchName(res)); break; case SCREEN_MANAGER: - DebugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<screen manager> %s\n", _vm->_resman->fetchName(res)); break; case MOUSE_FILE: - DebugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<mouse pointer> %s\n", _vm->_resman->fetchName(res)); break; case ICON_FILE: - DebugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res)); + debugPrintf("<menu icon> %s\n", _vm->_resman->fetchName(res)); break; default: - DebugPrintf("unrecognized fileType %d\n", type); + debugPrintf("unrecognized fileType %d\n", type); break; } @@ -458,13 +458,13 @@ bool Debugger::Cmd_CurrentInfo(int argc, const char **argv) { ScreenInfo *screenInfo = _vm->_screen->getScreenInfo(); if (screenInfo->background_layer_id) { - DebugPrintf("background layer id %d\n", screenInfo->background_layer_id); - DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep); - DebugPrintf("%d normal layers\n", screenInfo->number_of_layers); + debugPrintf("background layer id %d\n", screenInfo->background_layer_id); + debugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep); + debugPrintf("%d normal layers\n", screenInfo->number_of_layers); Cmd_RunList(argc, argv); } else - DebugPrintf("No screen\n"); + debugPrintf("No screen\n"); return true; } @@ -476,26 +476,26 @@ bool Debugger::Cmd_RunList(int argc, const char **argv) { readS.seek(ResHeader::size()); - DebugPrintf("Runlist number %d\n", runList); + debugPrintf("Runlist number %d\n", runList); while (1) { uint32 res = readS.readUint32LE(); if (!res) break; - DebugPrintf("%d %s\n", res, _vm->_resman->fetchName(res)); + debugPrintf("%d %s\n", res, _vm->_resman->fetchName(res)); } _vm->_resman->closeResource(runList); } else - DebugPrintf("No run list set\n"); + debugPrintf("No run list set\n"); return true; } bool Debugger::Cmd_Kill(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -503,7 +503,7 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) { uint32 numResFiles = _vm->_resman->getNumResFiles(); if (res < 0 || res >= (int)numResFiles) { - DebugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", + debugPrintf("Illegal resource %d. There are %d resources, 0-%d.\n", res, numResFiles, numResFiles - 1); return true; } @@ -511,22 +511,22 @@ bool Debugger::Cmd_Kill(int argc, const char **argv) { Resource *resList = _vm->_resman->getResList(); if (!resList[res].ptr) { - DebugPrintf("Resource %d is not in memory\n", res); + debugPrintf("Resource %d is not in memory\n", res); return true; } if (resList[res].refCount) { - DebugPrintf("Resource %d is open - cannot remove\n", res); + debugPrintf("Resource %d is open - cannot remove\n", res); return true; } _vm->_resman->remove(res); - DebugPrintf("Trashed %d\n", res); + debugPrintf("Trashed %d\n", res); return true; } bool Debugger::Cmd_Nuke(int argc, const char **argv) { - DebugPrintf("Killing all resources except variable file and player object\n"); + debugPrintf("Killing all resources except variable file and player object\n"); _vm->_resman->killAll(true); return true; } @@ -540,7 +540,7 @@ bool Debugger::Cmd_Var(int argc, const char **argv) { varSet(atoi(argv[1]), atoi(argv[2])); break; default: - DebugPrintf("Usage: %s number value\n", argv[0]); + debugPrintf("Usage: %s number value\n", argv[0]); break; } @@ -554,10 +554,10 @@ bool Debugger::Cmd_Rect(int argc, const char **argv) { if (_definingRectangles) { _vm->setInputEventFilter(filter & ~(RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP)); - DebugPrintf("Mouse rectangles enabled\n"); + debugPrintf("Mouse rectangles enabled\n"); } else { _vm->setInputEventFilter(filter | RD_LEFTBUTTONUP | RD_RIGHTBUTTONUP); - DebugPrintf("Mouse rectangles disabled\n"); + debugPrintf("Mouse rectangles disabled\n"); } _draggingRectangle = 0; @@ -575,7 +575,7 @@ bool Debugger::Cmd_DebugOn(int argc, const char **argv) { _displayMouseMarker = true; _displayPlayerMarker = true; _displayTextNumbers = true; - DebugPrintf("Enabled all on-screen debug info\n"); + debugPrintf("Enabled all on-screen debug info\n"); return true; } @@ -585,7 +585,7 @@ bool Debugger::Cmd_DebugOff(int argc, const char **argv) { _displayMouseMarker = false; _displayPlayerMarker = false; _displayTextNumbers = false; - DebugPrintf("Disabled all on-screen debug info\n"); + debugPrintf("Disabled all on-screen debug info\n"); return true; } @@ -593,9 +593,9 @@ bool Debugger::Cmd_SaveRest(int argc, const char **argv) { _testingSnR = !_testingSnR; if (_testingSnR) - DebugPrintf("Enabled S&R logic_script stability checking\n"); + debugPrintf("Enabled S&R logic_script stability checking\n"); else - DebugPrintf("Disabled S&R logic_script stability checking\n"); + debugPrintf("Disabled S&R logic_script stability checking\n"); return true; } @@ -606,13 +606,13 @@ bool Debugger::Cmd_TimeOn(int argc, const char **argv) { else if (_startTime == 0) _startTime = _vm->_system->getMillis(); _displayTime = true; - DebugPrintf("Timer display on\n"); + debugPrintf("Timer display on\n"); return true; } bool Debugger::Cmd_TimeOff(int argc, const char **argv) { _displayTime = false; - DebugPrintf("Timer display off\n"); + debugPrintf("Timer display off\n"); return true; } @@ -620,9 +620,9 @@ bool Debugger::Cmd_Text(int argc, const char **argv) { _displayTextNumbers = !_displayTextNumbers; if (_displayTextNumbers) - DebugPrintf("Text numbers on\n"); + debugPrintf("Text numbers on\n"); else - DebugPrintf("Text numbers off\n"); + debugPrintf("Text numbers off\n"); return true; } @@ -632,7 +632,7 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) { int32 varNo; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -649,11 +649,11 @@ bool Debugger::Cmd_ShowVar(int argc, const char **argv) { if (_showVar[showVarNo] == 0) { // empty slot - add it to the list at this slot _showVar[showVarNo] = varNo; - DebugPrintf("var(%d) added to the watch-list\n", varNo); + debugPrintf("var(%d) added to the watch-list\n", varNo); } else - DebugPrintf("var(%d) already in the watch-list!\n", varNo); + debugPrintf("var(%d) already in the watch-list!\n", varNo); } else - DebugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n"); + debugPrintf("Sorry - no more allowed - hide one or extend the system watch-list\n"); return true; } @@ -663,7 +663,7 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) { int32 varNo; if (argc != 2) { - DebugPrintf("Usage: %s number\n", argv[0]); + debugPrintf("Usage: %s number\n", argv[0]); return true; } @@ -676,9 +676,9 @@ bool Debugger::Cmd_HideVar(int argc, const char **argv) { if (showVarNo < MAX_SHOWVARS) { // We've found 'varNo' in the list - clear this slot _showVar[showVarNo] = 0; - DebugPrintf("var(%d) removed from watch-list\n", varNo); + debugPrintf("var(%d) removed from watch-list\n", varNo); } else - DebugPrintf("Sorry - can't find var(%d) in the list\n", varNo); + debugPrintf("Sorry - can't find var(%d) in the list\n", varNo); return true; } @@ -687,13 +687,13 @@ bool Debugger::Cmd_Version(int argc, const char **argv) { // This function used to print more information, but nothing we // particularly care about. - DebugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n"); + debugPrintf("\"Broken Sword II\" (c) Revolution Software 1997.\n"); return true; } bool Debugger::Cmd_AnimTest(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s value\n", argv[0]); + debugPrintf("Usage: %s value\n", argv[0]); return true; } @@ -703,13 +703,13 @@ bool Debugger::Cmd_AnimTest(int argc, const char **argv) { // Same as typing "VAR 912 <value>" at the console varSet(912, atoi(argv[1])); - DebugPrintf("Setting flag 'system_testing_anims'\n"); + debugPrintf("Setting flag 'system_testing_anims'\n"); return true; } bool Debugger::Cmd_TextTest(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s value\n", argv[0]); + debugPrintf("Usage: %s value\n", argv[0]); return true; } @@ -721,14 +721,14 @@ bool Debugger::Cmd_TextTest(int argc, const char **argv) { _displayTextNumbers = true; - DebugPrintf("Setting flag 'system_testing_text'\n"); - DebugPrintf("Text numbers on\n"); + debugPrintf("Setting flag 'system_testing_text'\n"); + debugPrintf("Text numbers on\n"); return true; } bool Debugger::Cmd_LineTest(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: %s value1 value2\n", argv[0]); + debugPrintf("Usage: %s value1 value2\n", argv[0]); return true; } @@ -743,24 +743,24 @@ bool Debugger::Cmd_LineTest(int argc, const char **argv) { _displayTextNumbers = true; - DebugPrintf("Setting flag 'system_testing_text'\n"); - DebugPrintf("Setting flag 'system_test_line_no'\n"); - DebugPrintf("Text numbers on\n"); + debugPrintf("Setting flag 'system_testing_text'\n"); + debugPrintf("Setting flag 'system_test_line_no'\n"); + debugPrintf("Text numbers on\n"); return true; } bool Debugger::Cmd_Events(int argc, const char **argv) { EventUnit *eventList = _vm->_logic->getEventList(); - DebugPrintf("EVENT LIST:\n"); + debugPrintf("EVENT LIST:\n"); for (uint32 i = 0; i < MAX_events; i++) { if (eventList[i].id) { uint32 target = eventList[i].id; uint32 script = eventList[i].interact_id; - DebugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target); - DebugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536); + debugPrintf("slot %2d: id = %s (%d)\n", i, _vm->_resman->fetchName(target), target); + debugPrintf(" script = %s (%d) pos %d\n", _vm->_resman->fetchName(script / 65536), script / 65536, script % 65536); } } @@ -771,28 +771,28 @@ bool Debugger::Cmd_Sfx(int argc, const char **argv) { _vm->_wantSfxDebug = !_vm->_wantSfxDebug; if (_vm->_wantSfxDebug) - DebugPrintf("SFX logging activated\n"); + debugPrintf("SFX logging activated\n"); else - DebugPrintf("SFX logging deactivated\n"); + debugPrintf("SFX logging deactivated\n"); return true; } bool Debugger::Cmd_English(int argc, const char **argv) { _vm->initializeFontResourceFlags(DEFAULT_TEXT); - DebugPrintf("Default fonts selected\n"); + debugPrintf("Default fonts selected\n"); return true; } bool Debugger::Cmd_Finnish(int argc, const char **argv) { _vm->initializeFontResourceFlags(FINNISH_TEXT); - DebugPrintf("Finnish fonts selected\n"); + debugPrintf("Finnish fonts selected\n"); return true; } bool Debugger::Cmd_Polish(int argc, const char **argv) { _vm->initializeFontResourceFlags(POLISH_TEXT); - DebugPrintf("Polish fonts selected\n"); + debugPrintf("Polish fonts selected\n"); return true; } diff --git a/engines/sword2/resman.cpp b/engines/sword2/resman.cpp index a0561641d7..44027fd281 100644 --- a/engines/sword2/resman.cpp +++ b/engines/sword2/resman.cpp @@ -38,7 +38,7 @@ #include "sword2/screen.h" #include "sword2/sound.h" -#define Debug_Printf _vm->_debugger->DebugPrintf +#define Debug_Printf _vm->_debugger->debugPrintf namespace Sword2 { diff --git a/engines/sword2/sound.cpp b/engines/sword2/sound.cpp index aea33e99e3..1e1687b1e6 100644 --- a/engines/sword2/sound.cpp +++ b/engines/sword2/sound.cpp @@ -49,7 +49,7 @@ #include "audio/decoders/wave.h" #include "audio/decoders/xa.h" -#define Debug_Printf _vm->_debugger->DebugPrintf +#define Debug_Printf _vm->_debugger->debugPrintf namespace Sword2 { diff --git a/engines/teenagent/console.cpp b/engines/teenagent/console.cpp index 13d5c687ce..2304829782 100644 --- a/engines/teenagent/console.cpp +++ b/engines/teenagent/console.cpp @@ -26,24 +26,24 @@ namespace TeenAgent { Console::Console(TeenAgentEngine *engine) : _engine(engine) { - DCmd_Register("enable_object", WRAP_METHOD(Console, enableObject)); - DCmd_Register("disable_object", WRAP_METHOD(Console, enableObject)); - DCmd_Register("set_ons", WRAP_METHOD(Console, setOns)); - DCmd_Register("set_music", WRAP_METHOD(Console, setMusic)); - DCmd_Register("animation", WRAP_METHOD(Console, playAnimation)); - DCmd_Register("actor_animation", WRAP_METHOD(Console, playActorAnimation)); - DCmd_Register("call", WRAP_METHOD(Console, call)); + registerCmd("enable_object", WRAP_METHOD(Console, enableObject)); + registerCmd("disable_object", WRAP_METHOD(Console, enableObject)); + registerCmd("set_ons", WRAP_METHOD(Console, setOns)); + registerCmd("set_music", WRAP_METHOD(Console, setMusic)); + registerCmd("animation", WRAP_METHOD(Console, playAnimation)); + registerCmd("actor_animation", WRAP_METHOD(Console, playActorAnimation)); + registerCmd("call", WRAP_METHOD(Console, call)); } bool Console::enableObject(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s object_id [scene_id]\n", argv[0]); + debugPrintf("usage: %s object_id [scene_id]\n", argv[0]); return true; } int id = atoi(argv[1]); if (id < 0) { - DebugPrintf("object id %d is invalid\n", id); + debugPrintf("object id %d is invalid\n", id); return true; } @@ -51,7 +51,7 @@ bool Console::enableObject(int argc, const char **argv) { if (argc > 2) { scene_id = atoi(argv[2]); if (scene_id < 0) { - DebugPrintf("scene id %d is invalid\n", scene_id); + debugPrintf("scene id %d is invalid\n", scene_id); return true; } } @@ -66,20 +66,20 @@ bool Console::enableObject(int argc, const char **argv) { bool Console::setOns(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]); + debugPrintf("usage: %s index(0-3) value [scene_id]\n", argv[0]); return true; } int index = atoi(argv[1]); if (index < 0 || index > 3) { - DebugPrintf("index %d is invalid\n", index); + debugPrintf("index %d is invalid\n", index); return true; } int value = 0; value = atoi(argv[2]); if (value < 0) { - DebugPrintf("invalid value\n"); + debugPrintf("invalid value\n"); return true; } @@ -87,7 +87,7 @@ bool Console::setOns(int argc, const char **argv) { if (argc > 3) { scene_id = atoi(argv[3]); if (scene_id < 0) { - DebugPrintf("scene id %d is invalid\n", scene_id); + debugPrintf("scene id %d is invalid\n", scene_id); return true; } } @@ -98,13 +98,13 @@ bool Console::setOns(int argc, const char **argv) { bool Console::setMusic(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s index(1-11)\n", argv[0]); + debugPrintf("usage: %s index(1-11)\n", argv[0]); return true; } int index = atoi(argv[1]); if (index <= 0 || index > 11) { - DebugPrintf("invalid value\n"); + debugPrintf("invalid value\n"); return true; } @@ -114,14 +114,14 @@ bool Console::setMusic(int argc, const char **argv) { bool Console::playAnimation(int argc, const char **argv) { if (argc < 3) { - DebugPrintf("usage: %s id slot(0-3)\n", argv[0]); + debugPrintf("usage: %s id slot(0-3)\n", argv[0]); return true; } int id = atoi(argv[1]); int slot = atoi(argv[2]); if (id < 0 || slot < 0 || slot > 3) { - DebugPrintf("invalid slot or animation id\n"); + debugPrintf("invalid slot or animation id\n"); return true; } @@ -131,13 +131,13 @@ bool Console::playAnimation(int argc, const char **argv) { bool Console::playActorAnimation(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s id\n", argv[0]); + debugPrintf("usage: %s id\n", argv[0]); return true; } int id = atoi(argv[1]); if (id < 0) { - DebugPrintf("invalid animation id\n"); + debugPrintf("invalid animation id\n"); return true; } @@ -147,18 +147,18 @@ bool Console::playActorAnimation(int argc, const char **argv) { bool Console::call(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("usage: %s 0xHEXADDR\n", argv[0]); + debugPrintf("usage: %s 0xHEXADDR\n", argv[0]); return true; } uint addr; if (sscanf(argv[1], "0x%x", &addr) != 1) { - DebugPrintf("invalid address\n"); + debugPrintf("invalid address\n"); return true; } if (!_engine->processCallback(addr)) - DebugPrintf("calling callback %04x failed\n", addr); + debugPrintf("calling callback %04x failed\n", addr); return true; } diff --git a/engines/tinsel/debugger.cpp b/engines/tinsel/debugger.cpp index 45e3a05903..1dbb19d383 100644 --- a/engines/tinsel/debugger.cpp +++ b/engines/tinsel/debugger.cpp @@ -62,11 +62,11 @@ int strToInt(const char *s) { //----------------- CONSOLE CLASS --------------------- Console::Console() : GUI::Debugger() { - DCmd_Register("item", WRAP_METHOD(Console, cmd_item)); - DCmd_Register("scene", WRAP_METHOD(Console, cmd_scene)); - DCmd_Register("music", WRAP_METHOD(Console, cmd_music)); - DCmd_Register("sound", WRAP_METHOD(Console, cmd_sound)); - DCmd_Register("string", WRAP_METHOD(Console, cmd_string)); + registerCmd("item", WRAP_METHOD(Console, cmd_item)); + registerCmd("scene", WRAP_METHOD(Console, cmd_scene)); + registerCmd("music", WRAP_METHOD(Console, cmd_music)); + registerCmd("sound", WRAP_METHOD(Console, cmd_sound)); + registerCmd("string", WRAP_METHOD(Console, cmd_string)); } Console::~Console() { @@ -74,8 +74,8 @@ Console::~Console() { bool Console::cmd_item(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s item_number\n", argv[0]); - DebugPrintf("Sets the currently active 'held' item\n"); + debugPrintf("%s item_number\n", argv[0]); + debugPrintf("Sets the currently active 'held' item\n"); return true; } @@ -86,14 +86,14 @@ bool Console::cmd_item(int argc, const char **argv) { bool Console::cmd_scene(int argc, const char **argv) { if (argc < 1 || argc > 3) { - DebugPrintf("%s [scene_number [entry number]]\n", argv[0]); - DebugPrintf("If no parameters are given, prints the current scene.\n"); - DebugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n"); + debugPrintf("%s [scene_number [entry number]]\n", argv[0]); + debugPrintf("If no parameters are given, prints the current scene.\n"); + debugPrintf("Otherwise changes to the specified scene number. Entry number defaults to 1 if none provided\n"); return true; } if (argc == 1) { - DebugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT); + debugPrintf("Current scene is %d\n", GetSceneHandle() >> SCNHANDLE_SHIFT); return true; } @@ -106,15 +106,15 @@ bool Console::cmd_scene(int argc, const char **argv) { bool Console::cmd_music(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]); - DebugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n"); - DebugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n"); + debugPrintf("%s track_number or %s -offset\n", argv[0], argv[0]); + debugPrintf("Plays the MIDI track number provided, or the offset inside midi.dat\n"); + debugPrintf("A positive number signifies a track number, whereas a negative signifies an offset\n"); return true; } int param = strToInt(argv[1]); if (param == 0) { - DebugPrintf("Track number/offset can't be 0!\n"); + debugPrintf("Track number/offset can't be 0!\n"); } else if (param > 0) { // Track provided PlayMidiSequence(GetTrackOffset(param - 1), false); @@ -128,8 +128,8 @@ bool Console::cmd_music(int argc, const char **argv) { bool Console::cmd_sound(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s id\n", argv[0]); - DebugPrintf("Plays the sound with the given ID\n"); + debugPrintf("%s id\n", argv[0]); + debugPrintf("Plays the sound with the given ID\n"); return true; } @@ -140,7 +140,7 @@ bool Console::cmd_sound(int argc, const char **argv) { else _vm->_sound->playSample(id, 0, false, 0, 0, PRIORITY_TALK, Audio::Mixer::kSpeechSoundType); } else { - DebugPrintf("Sample %d does not exist!\n", id); + debugPrintf("Sample %d does not exist!\n", id); } return true; @@ -148,15 +148,15 @@ bool Console::cmd_sound(int argc, const char **argv) { bool Console::cmd_string(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("%s id\n", argv[0]); - DebugPrintf("Prints the string with the given ID\n"); + debugPrintf("%s id\n", argv[0]); + debugPrintf("Prints the string with the given ID\n"); return true; } char tmp[TBUFSZ]; int id = strToInt(argv[1]); LoadStringRes(id, tmp, TBUFSZ); - DebugPrintf("%s\n", tmp); + debugPrintf("%s\n", tmp); return true; } diff --git a/engines/toltecs/console.cpp b/engines/toltecs/console.cpp index f84a8e3c44..5a0c66c7b0 100644 --- a/engines/toltecs/console.cpp +++ b/engines/toltecs/console.cpp @@ -31,8 +31,8 @@ namespace Toltecs { Console::Console(ToltecsEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); - DCmd_Register("dump", WRAP_METHOD(Console, Cmd_Dump)); + registerCmd("room", WRAP_METHOD(Console, Cmd_Room)); + registerCmd("dump", WRAP_METHOD(Console, Cmd_Dump)); } Console::~Console() { @@ -40,10 +40,10 @@ Console::~Console() { bool Console::Cmd_Room(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Current room number is %d\n", _vm->_sceneResIndex); + debugPrintf("Current room number is %d\n", _vm->_sceneResIndex); #if 0 - DebugPrintf("Calling this command with the room number changes the room\n"); - DebugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n"); + debugPrintf("Calling this command with the room number changes the room\n"); + debugPrintf("WARNING: It's a bad idea to warp to rooms with this, as the room object scripts are not loaded\n"); #endif return true; #if 0 @@ -65,13 +65,13 @@ bool Console::Cmd_Room(int argc, const char **argv) { bool Console::Cmd_Dump(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: dump <resource number>\n"); + debugPrintf("Usage: dump <resource number>\n"); return true; } int resNum = atoi(argv[1]); _vm->_arc->dump(resNum); - DebugPrintf("Resource %d has been dumped to disk\n", resNum); + debugPrintf("Resource %d has been dumped to disk\n", resNum); return true; } diff --git a/engines/tony/debugger.cpp b/engines/tony/debugger.cpp index 22c218a19c..e192c53d2b 100644 --- a/engines/tony/debugger.cpp +++ b/engines/tony/debugger.cpp @@ -28,9 +28,9 @@ namespace Tony { Debugger::Debugger() : GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene)); - DCmd_Register("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene)); + registerCmd("dirty_rects", WRAP_METHOD(Debugger, Cmd_DirtyRects)); } static int strToInt(const char *s) { @@ -82,13 +82,13 @@ void DebugChangeScene(CORO_PARAM, const void *param) { */ bool Debugger::Cmd_Scene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]); + debugPrintf("Usage: %s <scene number> [<x> <y>]\n", argv[0]); return true; } int sceneNumber = strToInt(argv[1]); if (sceneNumber >= g_vm->_theBoxes.getLocBoxesCount()) { - DebugPrintf("Invalid scene\n"); + debugPrintf("Invalid scene\n"); return true; } @@ -118,7 +118,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) { */ bool Debugger::Cmd_DirtyRects(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage; %s [on | off]\n", argv[0]); + debugPrintf("Usage; %s [on | off]\n", argv[0]); return true; } else { g_vm->_window.showDirtyRects(strcmp(argv[1], "on") == 0); diff --git a/engines/tony/detection_tables.h b/engines/tony/detection_tables.h index ce4651f0ab..28dcaac752 100644 --- a/engines/tony/detection_tables.h +++ b/engines/tony/detection_tables.h @@ -217,7 +217,7 @@ static const TonyGameDescription gameDescriptions[] = { // Tony Tough German "Shoe Box", reported in bug #3582420 { "tony", - 0, + 0, { {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, {"roasted.mpc", 0, "bc3471f098e591dc509dcad401a8d8a5", 389554}, @@ -230,6 +230,23 @@ static const TonyGameDescription gameDescriptions[] = { }, }, + { + // Tony Tough Russian, reported in bug #6589 + { + "tony", + 0, + { + {"roasted.mpr", 0, "06203dbbc85fdd1e6dc8fc211c1a6207", 135911071}, + {"roasted.mpc", 0, "377d6e24adeedc6c5c09c31b92231218", 391536}, + AD_LISTEND + }, + Common::RU_RUS, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + GUIO1(GUIO_NONE) + }, + }, + { AD_TABLE_END_MARKER } }; diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp index cab31795f7..51e8dee19f 100644 --- a/engines/toon/character.cpp +++ b/engines/toon/character.cpp @@ -1059,12 +1059,14 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) { _specialAnim->loadAnimation(animName); _animSpecialId = animId; - - _animationInstance->setAnimation(_specialAnim); - _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); - _animationInstance->reset(); - _animationInstance->stopAnimation(); - _animationInstance->setLooping(false); + + if (_animationInstance) { + _animationInstance->setAnimation(_specialAnim); + _animationInstance->setAnimationRange(0, _specialAnim->_numFrames - 1); + _animationInstance->reset(); + _animationInstance->stopAnimation(); + _animationInstance->setLooping(false); + } } int32 Character::getAnimFlag() { diff --git a/engines/touche/console.cpp b/engines/touche/console.cpp index c4272038dc..472863c817 100644 --- a/engines/touche/console.cpp +++ b/engines/touche/console.cpp @@ -26,8 +26,8 @@ namespace Touche { ToucheConsole::ToucheConsole(ToucheEngine *vm) : GUI::Debugger(), _vm(vm) { - DCmd_Register("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic)); - DCmd_Register("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic)); + registerCmd("startMusic", WRAP_METHOD(ToucheConsole, Cmd_StartMusic)); + registerCmd("stopMusic", WRAP_METHOD(ToucheConsole, Cmd_StopMusic)); } ToucheConsole::~ToucheConsole() { @@ -35,7 +35,7 @@ ToucheConsole::~ToucheConsole() { bool ToucheConsole::Cmd_StartMusic(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: startMusic <num>\n"); + debugPrintf("Usage: startMusic <num>\n"); return true; } diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp index 19c10af8de..b94776eee5 100644 --- a/engines/touche/menu.cpp +++ b/engines/touche/menu.cpp @@ -31,96 +31,6 @@ namespace Touche { -enum ActionId { - kActionNone, - - // settings menu - kActionLoadMenu, - kActionSaveMenu, - kActionRestartGame, - kActionPlayGame, - kActionQuitGame, - kActionTextOnly, - kActionVoiceOnly, - kActionTextAndVoice, - kActionLowerVolume, - kActionUpperVolume, - - // saveLoad menu - kActionGameState1, - kActionGameState2, - kActionGameState3, - kActionGameState4, - kActionGameState5, - kActionGameState6, - kActionGameState7, - kActionGameState8, - kActionGameState9, - kActionGameState10, - kActionScrollUpSaves, - kActionScrollDownSaves, - kActionPerformSaveLoad, - kActionCancelSaveLoad -}; - -enum MenuMode { - kMenuSettingsMode = 0, - kMenuLoadStateMode, - kMenuSaveStateMode -}; - -enum ButtonFlags { - kButtonBorder = 1 << 0, - kButtonText = 1 << 1, - kButtonArrow = 1 << 2 -}; - -struct Button { - int x, y; - int w, h; - ActionId action; - int data; - uint8 flags; -}; - -struct MenuData { - MenuMode mode; - Button *buttonsTable; - uint buttonsCount; - bool quit; - bool exit; - char saveLoadDescriptionsTable[kMaxSaveStates][33]; - - void removeLastCharFromDescription(int slot) { - char *description = saveLoadDescriptionsTable[slot]; - int descriptionLen = strlen(description); - if (descriptionLen > 0) { - --descriptionLen; - description[descriptionLen] = 0; - } - } - - void addCharToDescription(int slot, char chr) { - char *description = saveLoadDescriptionsTable[slot]; - int descriptionLen = strlen(description); - if (descriptionLen < 32 && Common::isPrint(chr)) { - description[descriptionLen] = chr; - description[descriptionLen + 1] = 0; - } - } - - const Button *findButtonUnderCursor(int cursorX, int cursorY) const { - for (uint i = 0; i < buttonsCount; ++i) { - const Button *button = &buttonsTable[i]; - if (cursorX >= button->x && cursorX < button->x + button->w && - cursorY >= button->y && cursorY < button->y + button->h) { - return button; - } - } - return 0; - } -}; - static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 color) { static const int8 arrowCoordsTable[7][4] = { { 5, 0, 9, 0 }, @@ -140,25 +50,24 @@ static void drawArrow(uint8 *dst, int dstPitch, int x, int y, int delta, uint8 c } } -void ToucheEngine::drawButton(void *button) { - Button *b = (Button *)button; - if (b->flags & kButtonBorder) { - Graphics::drawRect(_offscreenBuffer, kScreenWidth, b->x, b->y, b->w, b->h, 0xF7, 0xF9); +void ToucheEngine::drawButton(Button *button) { + if (button->flags & kButtonBorder) { + Graphics::drawRect(_offscreenBuffer, kScreenWidth, button->x, button->y, button->w, button->h, 0xF7, 0xF9); } - if (b->flags & kButtonText) { - if (b->data != 0) { - const char *str = getString(b->data); - const int w = getStringWidth(b->data); + if (button->flags & kButtonText) { + if (button->data != 0) { + const char *str = getString(button->data); + const int w = getStringWidth(button->data); const int h = kTextHeight; - const int x = b->x + (b->w - w) / 2; - const int y = b->y + (b->h - h) / 2; + const int x = button->x + (button->w - w) / 2; + const int y = button->y + (button->h - h) / 2; Graphics::drawString16(_offscreenBuffer, kScreenWidth, 0xFF, x, y, str); } } - if (b->flags & kButtonArrow) { + if (button->flags & kButtonArrow) { int dx = 0; int dy = 0; - switch (b->data) { + switch (button->data) { case 2000: // up arrow dx = 1; dy = 2; @@ -168,8 +77,8 @@ void ToucheEngine::drawButton(void *button) { dy = -2; break; } - const int x = b->x + b->w / 2; - const int y = b->y + b->h / 2; + const int x = button->x + button->w / 2; + const int y = button->y + button->h / 2; drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy + 1, dx, 0xD2); drawArrow(_offscreenBuffer, kScreenWidth, x, y + dy, dx, 0xFF); } @@ -253,49 +162,47 @@ static void setupMenu(MenuMode mode, MenuData *menuData) { } } -void ToucheEngine::redrawMenu(void *menu) { - MenuData *menuData = (MenuData *)menu; +void ToucheEngine::redrawMenu(MenuData *menu) { Graphics::fillRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF8); Graphics::drawRect(_offscreenBuffer, kScreenWidth, 90, 102, 460, 196, 0xF7, 0xF9); Graphics::drawRect(_offscreenBuffer, kScreenWidth, 106, 118, 340, 164, 0xF9, 0xF7); - switch (menuData->mode) { + switch (menu->mode) { case kMenuSettingsMode: drawVolumeSlideBar(_offscreenBuffer, kScreenWidth, getMusicVolume()); - menuData->buttonsTable[5].data = 0; - menuData->buttonsTable[6].data = 0; - menuData->buttonsTable[7].data = 0; - menuData->buttonsTable[5 + _talkTextMode].data = -86; + menu->buttonsTable[5].data = 0; + menu->buttonsTable[6].data = 0; + menu->buttonsTable[7].data = 0; + menu->buttonsTable[5 + _talkTextMode].data = -86; break; case kMenuLoadStateMode: case kMenuSaveStateMode: - drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menuData, _saveLoadCurrentPage, _saveLoadCurrentSlot); + drawSaveGameStateDescriptions(_offscreenBuffer, kScreenWidth, menu, _saveLoadCurrentPage, _saveLoadCurrentSlot); break; } - for (uint i = 0; i < menuData->buttonsCount; ++i) { - drawButton(&menuData->buttonsTable[i]); + for (uint i = 0; i < menu->buttonsCount; ++i) { + drawButton(&menu->buttonsTable[i]); } } -void ToucheEngine::handleMenuAction(void *menu, int actionId) { - MenuData *menuData = (MenuData *)menu; +void ToucheEngine::handleMenuAction(MenuData *menu, int actionId) { switch (actionId) { case kActionLoadMenu: - menuData->mode = kMenuLoadStateMode; + menu->mode = kMenuLoadStateMode; break; case kActionSaveMenu: _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); - menuData->mode = kMenuSaveStateMode; + menu->mode = kMenuSaveStateMode; break; case kActionRestartGame: restart(); - menuData->quit = true; + menu->quit = true; break; case kActionPlayGame: - menuData->quit = true; + menu->quit = true; break; case kActionQuitGame: quitGame(); - menuData->quit = true; + menu->quit = true; break; case kActionTextOnly: _talkTextMode = kTalkModeTextOnly; @@ -327,23 +234,23 @@ void ToucheEngine::handleMenuAction(void *menu, int actionId) { _saveLoadCurrentSlot = _saveLoadCurrentPage * 10 + (_saveLoadCurrentSlot % 10); break; case kActionPerformSaveLoad: - if (menuData->mode == kMenuLoadStateMode) { + if (menu->mode == kMenuLoadStateMode) { if (loadGameState(_saveLoadCurrentSlot).getCode() == Common::kNoError) { - menuData->quit = true; + menu->quit = true; } - } else if (menuData->mode == kMenuSaveStateMode) { + } else if (menu->mode == kMenuSaveStateMode) { _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - const char *description = menuData->saveLoadDescriptionsTable[_saveLoadCurrentSlot]; + const char *description = menu->saveLoadDescriptionsTable[_saveLoadCurrentSlot]; if (strlen(description) > 0) { if (saveGameState(_saveLoadCurrentSlot, description).getCode() == Common::kNoError) { - menuData->quit = true; + menu->quit = true; } } } break; case kActionCancelSaveLoad: _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); - menuData->mode = kMenuSettingsMode; + menu->mode = kMenuSettingsMode; break; default: if (actionId >= kActionGameState1 && actionId <= kActionGameState10) { diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp index 16a95d307f..467d2bed90 100644 --- a/engines/touche/resource.cpp +++ b/engines/touche/resource.cpp @@ -150,38 +150,38 @@ void ToucheEngine::res_allocateTables() { void ToucheEngine::res_deallocateTables() { free(_textData); - _textData = 0; + _textData = nullptr; free(_backdropBuffer); - _backdropBuffer = 0; + _backdropBuffer = nullptr; free(_menuKitData); - _menuKitData = 0; + _menuKitData = nullptr; free(_convKitData); - _convKitData = 0; + _convKitData = nullptr; for (int i = 0; i < NUM_SEQUENCES; ++i) { free(_sequenceDataTable[i]); - _sequenceDataTable[i] = 0; + _sequenceDataTable[i] = nullptr; } free(_programData); - _programData = 0; + _programData = nullptr; free(_mouseData); - _mouseData = 0; + _mouseData = nullptr; free(_iconData); - _iconData = 0; + _iconData = nullptr; for (int i = 0; i < NUM_SPRITES; ++i) { free(_spritesTable[i].ptr); - _spritesTable[i].ptr = 0; + _spritesTable[i].ptr = nullptr; } free(_offscreenBuffer); - _offscreenBuffer = 0; + _offscreenBuffer = nullptr; } uint32 ToucheEngine::res_getDataOffset(ResourceType type, int num, uint32 *size) { diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 09697d0e4a..ff4f41f44d 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -46,32 +46,32 @@ namespace Touche { ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) - : Engine(system), _midiPlayer(0), _language(language), _rnd("touche") { + : Engine(system), _midiPlayer(nullptr), _language(language), _rnd("touche") { _saveLoadCurrentPage = 0; _saveLoadCurrentSlot = 0; _hideInventoryTexts = false; _numOpcodes = 0; _compressedSpeechData = 0; - _textData = 0; - _backdropBuffer = 0; - _menuKitData = 0; - _convKitData = 0; + _textData = nullptr; + _backdropBuffer = nullptr; + _menuKitData = nullptr; + _convKitData = nullptr; for (int i = 0; i < NUM_SEQUENCES; i++) - _sequenceDataTable[i] = 0; + _sequenceDataTable[i] = nullptr; - _programData = 0; + _programData = nullptr; _programDataSize = 0; - _mouseData = 0; - _iconData = 0; + _mouseData = nullptr; + _iconData = nullptr; _currentBitmapWidth = 0; _currentBitmapHeight = 0; _currentImageWidth = 0; _currentImageHeight = 0; _roomWidth = 0; - _programTextDataPtr = 0; - _offscreenBuffer = 0; + _programTextDataPtr = nullptr; + _offscreenBuffer = nullptr; _screenRect = Common::Rect(kScreenWidth, kScreenHeight); _roomAreaRect = Common::Rect(kScreenWidth, kRoomHeight); @@ -124,11 +124,11 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _script.opcodeNum = 0; _script.dataOffset = 0; _script.keyCharNum = 0; - _script.dataPtr = 0; - _script.stackDataPtr = 0; - _script.stackDataBasePtr = 0; + _script.dataPtr = nullptr; + _script.stackDataPtr = nullptr; + _script.stackDataBasePtr = nullptr; _script.quitFlag = 0; - _opcodesTable = 0; + _opcodesTable = nullptr; for (uint i = 0; i < NUM_SPRITES; i++) memset(&_spritesTable[i], 0, sizeof(SpriteData)); @@ -138,10 +138,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _talkListEnd = 0; _talkListCurrent = 0; - _talkTextRectDefined = 0; - _talkTextDisplayed = 0; - _talkTextInitialized = 0; - _skipTalkText = 0; + _talkTextRectDefined = false; + _talkTextDisplayed = false; + _talkTextInitialized = false; + _skipTalkText = false; _talkTextSpeed = 0; _keyCharTalkCounter = 0; _talkTableLastTalkingKeyChar = 0; @@ -151,14 +151,14 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) for (uint i = 0; i < NUM_TALK_ENTRIES; i++) memset(&_talkTable[i], 0, sizeof(TalkEntry)); - _conversationChoicesUpdated = 0; + _conversationChoicesUpdated = false; _conversationReplyNum = 0; - _conversationEnded = 0; + _conversationEnded = false; _conversationNum = 0; _scrollConversationChoiceOffset = 0; _currentConversation = 0; - _disableConversationScript = 0; - _conversationAreaCleared = 0; + _disableConversationScript = false; + _conversationAreaCleared = false; for (uint i = 0; i < NUM_CONVERSATION_CHOICES; i++) memset(&_conversationChoicesTable[i], 0, sizeof(ConversationChoice)); @@ -167,6 +167,26 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _sortedKeyCharsTable[i] = 0; _currentKeyCharNum = 0; + _inp_leftMouseButtonPressed = false; + _inp_rightMouseButtonPressed = false; + _disabledInputCounter = 0; + _gameState = kGameStateNone; + _displayQuitDialog = false; + _newMusicNum = 0; + _currentMusicNum = 0; + _newSoundNum = 0; + _newSoundDelay = 0; + _newSoundPriority = 0; + for (int i = 0; i < 3; ++i) { + _inventoryStateTable[i].displayOffset = 0; + _inventoryStateTable[i].lastItem = 0; + _inventoryStateTable[i].itemsPerLine = 0; + _inventoryStateTable[i].itemsList = nullptr; + } + _inventoryVar1 = nullptr; + _inventoryVar2 = nullptr; + _currentCursorObject = 0; + _talkTextMode = 0; } ToucheEngine::~ToucheEngine() { @@ -3094,12 +3114,12 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) { for (uint i = 0; i < _programWalkTable.size(); ++i) { const ProgramWalkData *pwd = &_programWalkTable[i]; if ((pwd->point1 & 0x4000) == 0) { - int distance = 32000; ProgramPointData *pts1 = &_programPointsTable[pwd->point1]; ProgramPointData *pts2 = &_programPointsTable[pwd->point2]; if (pts1->order != 0) { int dx = pts2->x - pts1->x; int dy = pts2->y - pts1->y; + int distance = 32000; if (dx == 0) { if (dstPosY > MIN(pts2->y, pts1->y) && dstPosY < MAX(pts2->y, pts1->y)) { int d = ABS(dstPosX - pts1->x); diff --git a/engines/touche/touche.h b/engines/touche/touche.h index 3da33f593b..20bf723553 100644 --- a/engines/touche/touche.h +++ b/engines/touche/touche.h @@ -346,16 +346,108 @@ enum StringType { kStringTypeConversation }; -void readGameStateDescription(Common::ReadStream *f, char *description, int len); -Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false); -int getGameStateFileSlot(const char *filename); - enum GameState { kGameStateGameLoop, kGameStateOptionsDialog, - kGameStateQuitDialog + kGameStateQuitDialog, + kGameStateNone +}; + +enum ActionId { + kActionNone, + + // settings menu + kActionLoadMenu, + kActionSaveMenu, + kActionRestartGame, + kActionPlayGame, + kActionQuitGame, + kActionTextOnly, + kActionVoiceOnly, + kActionTextAndVoice, + kActionLowerVolume, + kActionUpperVolume, + + // saveLoad menu + kActionGameState1, + kActionGameState2, + kActionGameState3, + kActionGameState4, + kActionGameState5, + kActionGameState6, + kActionGameState7, + kActionGameState8, + kActionGameState9, + kActionGameState10, + kActionScrollUpSaves, + kActionScrollDownSaves, + kActionPerformSaveLoad, + kActionCancelSaveLoad +}; + +enum MenuMode { + kMenuSettingsMode = 0, + kMenuLoadStateMode, + kMenuSaveStateMode +}; + +enum ButtonFlags { + kButtonBorder = 1 << 0, + kButtonText = 1 << 1, + kButtonArrow = 1 << 2 }; +struct Button { + int x, y; + int w, h; + ActionId action; + int data; + uint8 flags; +}; + +struct MenuData { + MenuMode mode; + Button *buttonsTable; + uint buttonsCount; + bool quit; + bool exit; + char saveLoadDescriptionsTable[kMaxSaveStates][33]; + + void removeLastCharFromDescription(int slot) { + char *description = saveLoadDescriptionsTable[slot]; + int descriptionLen = strlen(description); + if (descriptionLen > 0) { + --descriptionLen; + description[descriptionLen] = 0; + } + } + + void addCharToDescription(int slot, char chr) { + char *description = saveLoadDescriptionsTable[slot]; + int descriptionLen = strlen(description); + if (descriptionLen < 32 && Common::isPrint(chr)) { + description[descriptionLen] = chr; + description[descriptionLen + 1] = 0; + } + } + + const Button *findButtonUnderCursor(int cursorX, int cursorY) const { + for (uint i = 0; i < buttonsCount; ++i) { + const Button *button = &buttonsTable[i]; + if (cursorX >= button->x && cursorX < button->x + button->w && + cursorY >= button->y && cursorY < button->y + button->h) { + return button; + } + } + return 0; + } +}; + + +void readGameStateDescription(Common::ReadStream *f, char *description, int len); +Common::String generateGameStateFileName(const char *target, int slot, bool prefixOnly = false); +int getGameStateFileSlot(const char *filename); + class MidiPlayer; class ToucheEngine: public Engine { @@ -631,9 +723,9 @@ protected: void res_loadSpeechSegment(int num); void res_stopSpeech(); - void drawButton(void *button); - void redrawMenu(void *menu); - void handleMenuAction(void *menu, int actionId); + void drawButton(Button *button); + void redrawMenu(MenuData *menu); + void handleMenuAction(MenuData *menu, int actionId); void handleOptions(int forceDisplay); void drawActionsPanel(int dstX, int dstY, int deltaX, int deltaY); void drawConversationPanelBorder(int dstY, int srcX, int srcY); diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp index 5a520b0e89..b647807f8a 100644 --- a/engines/tsage/debugger.cpp +++ b/engines/tsage/debugger.cpp @@ -30,19 +30,19 @@ namespace TsAGE { Debugger::Debugger() : GUI::Debugger() { - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("scene", WRAP_METHOD(Debugger, Cmd_Scene)); - DCmd_Register("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions)); - DCmd_Register("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions)); - DCmd_Register("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions)); - DCmd_Register("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag)); - DCmd_Register("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag)); - DCmd_Register("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag)); - DCmd_Register("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects)); - DCmd_Register("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); - DCmd_Register("sound", WRAP_METHOD(Debugger, Cmd_Sound)); - DCmd_Register("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("scene", WRAP_METHOD(Debugger, Cmd_Scene)); + registerCmd("walk_regions", WRAP_METHOD(Debugger, Cmd_WalkRegions)); + registerCmd("priority_regions", WRAP_METHOD(Debugger, Cmd_PriorityRegions)); + registerCmd("scene_regions", WRAP_METHOD(Debugger, Cmd_SceneRegions)); + registerCmd("setflag", WRAP_METHOD(Debugger, Cmd_SetFlag)); + registerCmd("getflag", WRAP_METHOD(Debugger, Cmd_GetFlag)); + registerCmd("clearflag", WRAP_METHOD(Debugger, Cmd_ClearFlag)); + registerCmd("listobjects", WRAP_METHOD(Debugger, Cmd_ListObjects)); + registerCmd("moveobject", WRAP_METHOD(Debugger, Cmd_MoveObject)); + registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); + registerCmd("sound", WRAP_METHOD(Debugger, Cmd_Sound)); + registerCmd("setdebug", WRAP_METHOD(Debugger, Cmd_SetDebug)); } static int strToInt(const char *s) { @@ -66,7 +66,7 @@ static int strToInt(const char *s) { */ bool Debugger::Cmd_Scene(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]); + debugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]); return true; } @@ -82,7 +82,7 @@ bool Debugger::Cmd_Scene(int argc, const char **argv) { */ bool Debugger::Cmd_WalkRegions(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } @@ -120,8 +120,8 @@ bool Debugger::Cmd_WalkRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size()); - DebugPrintf("%s\n", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", g_globals->_walkRegions._regionList.size()); + debugPrintf("%s\n", regionsDesc.c_str()); return false; } @@ -172,8 +172,8 @@ bool Debugger::Cmd_PriorityRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", count); - DebugPrintf("%s", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", count); + debugPrintf("%s", regionsDesc.c_str()); return true; } @@ -225,8 +225,8 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) { // Mark the scene as requiring a full redraw g_globals->_paneRefreshFlag[0] = 2; - DebugPrintf("Total regions = %d\n", count); - DebugPrintf("%s", regionsDesc.c_str()); + debugPrintf("Total regions = %d\n", count); + debugPrintf("%s", regionsDesc.c_str()); return true; } @@ -237,7 +237,7 @@ bool Debugger::Cmd_SceneRegions(int argc, const char **argv) { bool Debugger::Cmd_SetFlag(int argc, const char **argv) { // Check for a flag to set if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } @@ -252,12 +252,12 @@ bool Debugger::Cmd_SetFlag(int argc, const char **argv) { bool Debugger::Cmd_GetFlag(int argc, const char **argv) { // Check for an flag to display if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } int flagNum = strToInt(argv[1]); - DebugPrintf("Value: %d\n", g_globals->getFlag(flagNum)); + debugPrintf("Value: %d\n", g_globals->getFlag(flagNum)); return true; } @@ -267,7 +267,7 @@ bool Debugger::Cmd_GetFlag(int argc, const char **argv) { bool Debugger::Cmd_ClearFlag(int argc, const char **argv) { // Check for a flag to clear if (argc != 2) { - DebugPrintf("Usage: %s <flag number>\n", argv[0]); + debugPrintf("Usage: %s <flag number>\n", argv[0]); return true; } @@ -332,7 +332,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { */ bool Debugger::Cmd_Sound(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Usage: %s <sound number>\n", argv[0]); + debugPrintf("Usage: %s <sound number>\n", argv[0]); return true; } @@ -345,7 +345,7 @@ bool Debugger::Cmd_Sound(int argc, const char **argv) { * Activate internal debugger, when available */ bool Debugger::Cmd_SetDebug(int argc, const char **argv) { - DebugPrintf("Not available in this game\n"); + debugPrintf("Not available in this game\n"); return true; } @@ -353,12 +353,12 @@ bool Debugger::Cmd_SetDebug(int argc, const char **argv) { * This command lists the objects available, and their ID */ bool DemoDebugger::Cmd_ListObjects(int argc, const char **argv) { - DebugPrintf("Not available in Demo\n"); + debugPrintf("Not available in Demo\n"); return true; } bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) { - DebugPrintf("Not available in Demo\n"); + debugPrintf("Not available in Demo\n"); return true; } @@ -367,44 +367,44 @@ bool DemoDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("0 - Stunner\n"); - DebugPrintf("1 - Scanner\n"); - DebugPrintf("2 - Stasis Box\n"); - DebugPrintf("3 - Info Disk\n"); - DebugPrintf("4 - Stasis Negator\n"); - DebugPrintf("5 - Key Device\n"); - DebugPrintf("6 - Medkit\n"); - DebugPrintf("7 - Ladder\n"); - DebugPrintf("8 - Rope\n"); - DebugPrintf("9 - Key\n"); - DebugPrintf("10 - Translator\n"); - DebugPrintf("11 - Ale\n"); - DebugPrintf("12 - Paper\n"); - DebugPrintf("13 - Waldos\n"); - DebugPrintf("14 - Stasis Box 2\n"); - DebugPrintf("15 - Ring\n"); - DebugPrintf("16 - Cloak\n"); - DebugPrintf("17 - Tunic\n"); - DebugPrintf("18 - Candle\n"); - DebugPrintf("19 - Straw\n"); - DebugPrintf("20 - Scimitar\n"); - DebugPrintf("21 - Sword\n"); - DebugPrintf("22 - Helmet\n"); - DebugPrintf("23 - Items\n"); - DebugPrintf("24 - Concentrator\n"); - DebugPrintf("25 - Nullifier\n"); - DebugPrintf("26 - Peg\n"); - DebugPrintf("27 - Vial\n"); - DebugPrintf("28 - Jacket\n"); - DebugPrintf("29 - Tunic 2\n"); - DebugPrintf("30 - Bone\n"); - DebugPrintf("31 - Empty Jar\n"); - DebugPrintf("32 - Jar\n"); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("0 - Stunner\n"); + debugPrintf("1 - Scanner\n"); + debugPrintf("2 - Stasis Box\n"); + debugPrintf("3 - Info Disk\n"); + debugPrintf("4 - Stasis Negator\n"); + debugPrintf("5 - Key Device\n"); + debugPrintf("6 - Medkit\n"); + debugPrintf("7 - Ladder\n"); + debugPrintf("8 - Rope\n"); + debugPrintf("9 - Key\n"); + debugPrintf("10 - Translator\n"); + debugPrintf("11 - Ale\n"); + debugPrintf("12 - Paper\n"); + debugPrintf("13 - Waldos\n"); + debugPrintf("14 - Stasis Box 2\n"); + debugPrintf("15 - Ring\n"); + debugPrintf("16 - Cloak\n"); + debugPrintf("17 - Tunic\n"); + debugPrintf("18 - Candle\n"); + debugPrintf("19 - Straw\n"); + debugPrintf("20 - Scimitar\n"); + debugPrintf("21 - Sword\n"); + debugPrintf("22 - Helmet\n"); + debugPrintf("23 - Items\n"); + debugPrintf("24 - Concentrator\n"); + debugPrintf("25 - Nullifier\n"); + debugPrintf("26 - Peg\n"); + debugPrintf("27 - Vial\n"); + debugPrintf("28 - Jacket\n"); + debugPrintf("29 - Tunic 2\n"); + debugPrintf("30 - Bone\n"); + debugPrintf("31 - Empty Jar\n"); + debugPrintf("32 - Jar\n"); return true; } @@ -414,8 +414,8 @@ bool RingworldDebugger::Cmd_ListObjects(int argc, const char **argv) { bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -525,7 +525,7 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { RING_INVENTORY._jar._sceneNumber = sceneNum; break; default: - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); break; } @@ -537,83 +537,83 @@ bool RingworldDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool BlueForceDebugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("1 - INV_COLT45\n"); - DebugPrintf("2 - INV_AMMO_CLIP\n"); - DebugPrintf("3 - INV_SPARE_CLIP\n"); - DebugPrintf("4 - INV_HANDCUFFS\n"); - DebugPrintf("5 - INV_GREENS_GUN\n"); - DebugPrintf("6 - INV_TICKET_BOOK\n"); - DebugPrintf("7 - INV_MIRANDA_CARD\n"); - DebugPrintf("8 - INV_FOREST_RAP\n"); - DebugPrintf("9 - INV_GREEN_ID\n"); - DebugPrintf("10 - INV_BASEBALL_CARD\n"); - DebugPrintf("11 - INV_BOOKING_GREEN\n"); - DebugPrintf("12 - INV_FLARE\n"); - DebugPrintf("13 - INV_COBB_RAP\n"); - DebugPrintf("14 - INV_22_BULLET\n"); - DebugPrintf("15 - INV_AUTO_RIFLE\n"); - DebugPrintf("16 - INV_WIG\n"); - DebugPrintf("17 - INV_FRANKIE_ID\n"); - DebugPrintf("18 - INV_TYRONE_ID\n"); - DebugPrintf("19 - INV_22_SNUB\n"); - DebugPrintf("20 - INV_BOOKING_FRANKIE\n"); - DebugPrintf("21 - INV_BOOKING_GANG\n"); - DebugPrintf("22 - INV_FBI_TELETYPE\n"); - DebugPrintf("23 - INV_DA_NOTE\n"); - DebugPrintf("24 - INV_PRINT_OUT\n"); - DebugPrintf("25 - INV_WAREHOUSE_KEYS\n"); - DebugPrintf("26 - INV_CENTER_PUNCH\n"); - DebugPrintf("27 - INV_TRANQ_GUN\n"); - DebugPrintf("28 - INV_HOOK\n"); - DebugPrintf("29 - INV_RAGS\n"); - DebugPrintf("30 - INV_JAR\n"); - DebugPrintf("31 - INV_SCREWDRIVER\n"); - DebugPrintf("32 - INV_D_FLOPPY\n"); - DebugPrintf("33 - INV_BLANK_DISK\n"); - DebugPrintf("34 - INV_STICK\n"); - DebugPrintf("35 - INV_CRATE1\n"); - DebugPrintf("36 - INV_CRATE2\n"); - DebugPrintf("37 - INV_SHOEBOX\n"); - DebugPrintf("38 - INV_BADGE\n"); - DebugPrintf("39 - INV_RENTAL_COUPON\n"); - DebugPrintf("40 - INV_NICKEL\n"); - DebugPrintf("41 - INV_LYLE_CARD\n"); - DebugPrintf("42 - INV_CARTER_NOTE\n"); - DebugPrintf("43 - INV_MUG_SHOT\n"); - DebugPrintf("44 - INV_CLIPPING\n"); - DebugPrintf("45 - INV_MICROFILM \n"); - DebugPrintf("46 - INV_WAVE_KEYS\n"); - DebugPrintf("47 - INV_RENTAL_KEYS\n"); - DebugPrintf("48 - INV_NAPKIN\n"); - DebugPrintf("49 - INV_DMV_PRINTOUT\n"); - DebugPrintf("50 - INV_FISHING_NET\n"); - DebugPrintf("51 - INV_ID\n"); - DebugPrintf("52 - INV_9MM_BULLETS\n"); - DebugPrintf("53 - INV_SCHEDULE\n"); - DebugPrintf("54 - INV_GRENADES\n"); - DebugPrintf("55 - INV_YELLOW_CORD\n"); - DebugPrintf("56 - INV_HALF_YELLOW_CORD\n"); - DebugPrintf("57 - INV_BLACK_CORD\n"); - DebugPrintf("58 - INV_HALF_BLACK_CORD\n"); - DebugPrintf("59 - INV_WARRANT\n"); - DebugPrintf("60 - INV_JACKET\n"); - DebugPrintf("61 - INV_GREENS_KNIFE\n"); - DebugPrintf("62 - INV_DOG_WHISTLE\n"); - DebugPrintf("63 - INV_AMMO_BELT\n"); - DebugPrintf("64 - INV_CARAVAN_KEY\n"); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("1 - INV_COLT45\n"); + debugPrintf("2 - INV_AMMO_CLIP\n"); + debugPrintf("3 - INV_SPARE_CLIP\n"); + debugPrintf("4 - INV_HANDCUFFS\n"); + debugPrintf("5 - INV_GREENS_GUN\n"); + debugPrintf("6 - INV_TICKET_BOOK\n"); + debugPrintf("7 - INV_MIRANDA_CARD\n"); + debugPrintf("8 - INV_FOREST_RAP\n"); + debugPrintf("9 - INV_GREEN_ID\n"); + debugPrintf("10 - INV_BASEBALL_CARD\n"); + debugPrintf("11 - INV_BOOKING_GREEN\n"); + debugPrintf("12 - INV_FLARE\n"); + debugPrintf("13 - INV_COBB_RAP\n"); + debugPrintf("14 - INV_22_BULLET\n"); + debugPrintf("15 - INV_AUTO_RIFLE\n"); + debugPrintf("16 - INV_WIG\n"); + debugPrintf("17 - INV_FRANKIE_ID\n"); + debugPrintf("18 - INV_TYRONE_ID\n"); + debugPrintf("19 - INV_22_SNUB\n"); + debugPrintf("20 - INV_BOOKING_FRANKIE\n"); + debugPrintf("21 - INV_BOOKING_GANG\n"); + debugPrintf("22 - INV_FBI_TELETYPE\n"); + debugPrintf("23 - INV_DA_NOTE\n"); + debugPrintf("24 - INV_PRINT_OUT\n"); + debugPrintf("25 - INV_WAREHOUSE_KEYS\n"); + debugPrintf("26 - INV_CENTER_PUNCH\n"); + debugPrintf("27 - INV_TRANQ_GUN\n"); + debugPrintf("28 - INV_HOOK\n"); + debugPrintf("29 - INV_RAGS\n"); + debugPrintf("30 - INV_JAR\n"); + debugPrintf("31 - INV_SCREWDRIVER\n"); + debugPrintf("32 - INV_D_FLOPPY\n"); + debugPrintf("33 - INV_BLANK_DISK\n"); + debugPrintf("34 - INV_STICK\n"); + debugPrintf("35 - INV_CRATE1\n"); + debugPrintf("36 - INV_CRATE2\n"); + debugPrintf("37 - INV_SHOEBOX\n"); + debugPrintf("38 - INV_BADGE\n"); + debugPrintf("39 - INV_RENTAL_COUPON\n"); + debugPrintf("40 - INV_NICKEL\n"); + debugPrintf("41 - INV_LYLE_CARD\n"); + debugPrintf("42 - INV_CARTER_NOTE\n"); + debugPrintf("43 - INV_MUG_SHOT\n"); + debugPrintf("44 - INV_CLIPPING\n"); + debugPrintf("45 - INV_MICROFILM \n"); + debugPrintf("46 - INV_WAVE_KEYS\n"); + debugPrintf("47 - INV_RENTAL_KEYS\n"); + debugPrintf("48 - INV_NAPKIN\n"); + debugPrintf("49 - INV_DMV_PRINTOUT\n"); + debugPrintf("50 - INV_FISHING_NET\n"); + debugPrintf("51 - INV_ID\n"); + debugPrintf("52 - INV_9MM_BULLETS\n"); + debugPrintf("53 - INV_SCHEDULE\n"); + debugPrintf("54 - INV_GRENADES\n"); + debugPrintf("55 - INV_YELLOW_CORD\n"); + debugPrintf("56 - INV_HALF_YELLOW_CORD\n"); + debugPrintf("57 - INV_BLACK_CORD\n"); + debugPrintf("58 - INV_HALF_BLACK_CORD\n"); + debugPrintf("59 - INV_WARRANT\n"); + debugPrintf("60 - INV_JACKET\n"); + debugPrintf("61 - INV_GREENS_KNIFE\n"); + debugPrintf("62 - INV_DOG_WHISTLE\n"); + debugPrintf("63 - INV_AMMO_BELT\n"); + debugPrintf("64 - INV_CARAVAN_KEY\n"); return true; } bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -625,7 +625,7 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { if ((objNum > 0) && (objNum < 65)) BF_INVENTORY.setObjectScene(objNum, sceneNum); else - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); return true; } @@ -635,63 +635,63 @@ bool BlueForceDebugger::Cmd_MoveObject(int argc, const char **argv) { */ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } - DebugPrintf("Available objects for this game are:\n"); - DebugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1)); - DebugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2)); - DebugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3)); - DebugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4)); - DebugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5)); - DebugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6)); - DebugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7)); - DebugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8)); - DebugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9)); - DebugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10)); - DebugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11)); - DebugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12)); - DebugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13)); - DebugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14)); - DebugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15)); - DebugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16)); - DebugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17)); - DebugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18)); - DebugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19)); - DebugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20)); - DebugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21)); - DebugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22)); - DebugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23)); - DebugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24)); - DebugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25)); - DebugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26)); - DebugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27)); - DebugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28)); - DebugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29)); - DebugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30)); - DebugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31)); - DebugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32)); - DebugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33)); - DebugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34)); - DebugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35)); - DebugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36)); - DebugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37)); - DebugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38)); - DebugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39)); - DebugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40)); - DebugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41)); - DebugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42)); - DebugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43)); - DebugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44)); - DebugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45)); - DebugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46)); - DebugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47)); - DebugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48)); - DebugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49)); - DebugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50)); - DebugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51)); - DebugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52)); + debugPrintf("Available objects for this game are:\n"); + debugPrintf("1 - Scene %d - R2_OPTO_DISK\n", BF_INVENTORY.getObjectScene(1)); + debugPrintf("2 - Scene %d - R2_READER\n", BF_INVENTORY.getObjectScene(2)); + debugPrintf("3 - Scene %d - R2_NEGATOR_GUN\n", BF_INVENTORY.getObjectScene(3)); + debugPrintf("4 - Scene %d - R2_STEPPING_DISKS\n", BF_INVENTORY.getObjectScene(4)); + debugPrintf("5 - Scene %d - R2_ATTRACTOR_UNIT\n", BF_INVENTORY.getObjectScene(5)); + debugPrintf("6 - Scene %d - R2_SENSOR_PROBE\n", BF_INVENTORY.getObjectScene(6)); + debugPrintf("7 - Scene %d - R2_SONIC_STUNNER\n", BF_INVENTORY.getObjectScene(7)); + debugPrintf("8 - Scene %d - R2_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(8)); + debugPrintf("9 - Scene %d - R2_COM_SCANNER\n", BF_INVENTORY.getObjectScene(9)); + debugPrintf("10 - Scene %d - R2_SPENT_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(10)); + debugPrintf("11 - Scene %d - R2_CHARGED_POWER_CAPSULE\n", BF_INVENTORY.getObjectScene(11)); + debugPrintf("12 - Scene %d - R2_AEROSOL\n", BF_INVENTORY.getObjectScene(12)); + debugPrintf("13 - Scene %d - R2_REMOTE_CONTROL\n", BF_INVENTORY.getObjectScene(13)); + debugPrintf("14 - Scene %d - R2_OPTICAL_FIBER\n", BF_INVENTORY.getObjectScene(14)); + debugPrintf("15 - Scene %d - R2_CLAMP\n", BF_INVENTORY.getObjectScene(15)); + debugPrintf("16 - Scene %d - R2_ATTRACTOR_CABLE_HARNESS\n", BF_INVENTORY.getObjectScene(16)); + debugPrintf("17 - Scene %d - R2_FUEL_CELL\n", BF_INVENTORY.getObjectScene(17)); + debugPrintf("18 - Scene %d - R2_GYROSCOPE\n", BF_INVENTORY.getObjectScene(18)); + debugPrintf("19 - Scene %d - R2_AIRBAG\n", BF_INVENTORY.getObjectScene(19)); + debugPrintf("20 - Scene %d - R2_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(20)); + debugPrintf("21 - Scene %d - R2_RESERVE_REBREATHER_TANK\n", BF_INVENTORY.getObjectScene(21)); + debugPrintf("22 - Scene %d - R2_GUIDANCE_MODULE\n", BF_INVENTORY.getObjectScene(22)); + debugPrintf("23 - Scene %d - R2_THRUSTER_VALVE\n", BF_INVENTORY.getObjectScene(23)); + debugPrintf("24 - Scene %d - R2_BALLOON_BACKPACK\n", BF_INVENTORY.getObjectScene(24)); + debugPrintf("25 - Scene %d - R2_RADAR_MECHANISM\n", BF_INVENTORY.getObjectScene(25)); + debugPrintf("26 - Scene %d - R2_JOYSTICK\n", BF_INVENTORY.getObjectScene(26)); + debugPrintf("27 - Scene %d - R2_IGNITOR\n", BF_INVENTORY.getObjectScene(27)); + debugPrintf("28 - Scene %d - R2_DIAGNOSTICS_DISPLAY\n", BF_INVENTORY.getObjectScene(28)); + debugPrintf("29 - Scene %d - R2_GLASS_DOME\n", BF_INVENTORY.getObjectScene(29)); + debugPrintf("30 - Scene %d - R2_WICK_LAMP\n", BF_INVENTORY.getObjectScene(30)); + debugPrintf("31 - Scene %d - R2_SCRITH_KEY\n", BF_INVENTORY.getObjectScene(31)); + debugPrintf("32 - Scene %d - R2_TANNER_MASK\n", BF_INVENTORY.getObjectScene(32)); + debugPrintf("33 - Scene %d - R2_PURE_GRAIN_ALCOHOL\n", BF_INVENTORY.getObjectScene(33)); + debugPrintf("34 - Scene %d - R2_SAPPHIRE_BLUE\n", BF_INVENTORY.getObjectScene(34)); + debugPrintf("35 - Scene %d - R2_ANCIENT_SCROLLS\n", BF_INVENTORY.getObjectScene(35)); + debugPrintf("36 - Scene %d - R2_FLUTE\n", BF_INVENTORY.getObjectScene(36)); + debugPrintf("37 - Scene %d - R2_GUNPOWDER\n", BF_INVENTORY.getObjectScene(37)); + debugPrintf("38 - Scene %d - R2_NONAME\n", BF_INVENTORY.getObjectScene(38)); + debugPrintf("39 - Scene %d - R2_COM_SCANNER_2\n", BF_INVENTORY.getObjectScene(39)); + debugPrintf("40 - Scene %d - R2_SUPERCONDUCTOR_WIRE\n", BF_INVENTORY.getObjectScene(40)); + debugPrintf("41 - Scene %d - R2_PILLOW\n", BF_INVENTORY.getObjectScene(41)); + debugPrintf("42 - Scene %d - R2_FOOD_TRAY\n", BF_INVENTORY.getObjectScene(42)); + debugPrintf("43 - Scene %d - R2_LASER_HACKSAW\n", BF_INVENTORY.getObjectScene(43)); + debugPrintf("44 - Scene %d - R2_PHOTON_STUNNER\n", BF_INVENTORY.getObjectScene(44)); + debugPrintf("45 - Scene %d - R2_BATTERY\n", BF_INVENTORY.getObjectScene(45)); + debugPrintf("46 - Scene %d - R2_SOAKED_FACEMASK\n", BF_INVENTORY.getObjectScene(46)); + debugPrintf("47 - Scene %d - R2_LIGHT_BULB\n", BF_INVENTORY.getObjectScene(47)); + debugPrintf("48 - Scene %d - R2_ALCOHOL_LAMP\n", BF_INVENTORY.getObjectScene(48)); + debugPrintf("49 - Scene %d - R2_ALCOHOL_LAMP_2\n", BF_INVENTORY.getObjectScene(49)); + debugPrintf("50 - Scene %d - R2_ALCOHOL_LAMP_3\n", BF_INVENTORY.getObjectScene(50)); + debugPrintf("51 - Scene %d - R2_BROKEN_DISPLAY\n", BF_INVENTORY.getObjectScene(51)); + debugPrintf("52 - Scene %d - R2_TOOLBOX\n", BF_INVENTORY.getObjectScene(52)); return true; } @@ -699,8 +699,8 @@ bool Ringworld2Debugger::Cmd_ListObjects(int argc, const char **argv) { bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { // Check for a flag to clear if ((argc < 2) || (argc > 3)){ - DebugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); - DebugPrintf("If no scene is specified, the object will be added to inventory\n"); + debugPrintf("Usage: %s <object number> [<scene number>]\n", argv[0]); + debugPrintf("If no scene is specified, the object will be added to inventory\n"); return true; } @@ -712,7 +712,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { if ((objNum > 0) && (objNum < 53)) R2_INVENTORY.setObjectScene(objNum, sceneNum); else - DebugPrintf("Invalid object Id %s\n", argv[1]); + debugPrintf("Invalid object Id %s\n", argv[1]); return true; } @@ -722,7 +722,7 @@ bool Ringworld2Debugger::Cmd_MoveObject(int argc, const char **argv) { */ bool Ringworld2Debugger::Cmd_SetDebug(int argc, const char **argv) { if (argc != 1) { - DebugPrintf("Usage: %s\n", argv[0]); + debugPrintf("Usage: %s\n", argv[0]); return true; } diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp index 5f06334720..9cba7b523d 100644 --- a/engines/tucker/resource.cpp +++ b/engines/tucker/resource.cpp @@ -535,7 +535,10 @@ void TuckerEngine::loadObj() { return; } debug(2, "loadObj() partNum %d locationNum %d", _partNum, _locationNum); - if ((_gameFlags & kGameFlagDemo) == 0) { + // If a savegame is loaded from the launcher, skip the display chapter + if (_startSlot != -1) + _startSlot = -1; + else if ((_gameFlags & kGameFlagDemo) == 0) { handleNewPartSequence(); } _currentPartNum = _partNum; @@ -662,15 +665,13 @@ void TuckerEngine::loadData4() { t.findNextToken(kDataTokenDw); _gameDebug = t.getNextInteger() != 0; _displayGameHints = t.getNextInteger() != 0; - // forces game hints feature -// _displayGameHints = true; _locationObjectsCount = 0; if (t.findIndex(_locationNum)) { while (t.findNextToken(kDataTokenDw)) { int i = t.getNextInteger(); - if (i < 0) { + if (i < 0) break; - } + assert(_locationObjectsCount < kLocationObjectsTableSize); LocationObject *d = &_locationObjectsTable[_locationObjectsCount++]; d->_xPos = i; @@ -851,60 +852,63 @@ void TuckerEngine::unloadSprC02_01() { void TuckerEngine::loadFx() { loadFile("fx.c", _loadTempBuf); DataTokenizer t(_loadTempBuf, _fileLoadSize); - t.findIndex(_locationNum); - t.findNextToken(kDataTokenDw); - _locationSoundsCount = t.getNextInteger(); - _currentFxSet = 0; - for (int i = 0; i < _locationSoundsCount; ++i) { - LocationSound *s = &_locationSoundsTable[i]; - s->_offset = 0; - s->_num = t.getNextInteger(); - s->_volume = t.getNextInteger(); - s->_type = t.getNextInteger(); - switch (s->_type) { - case 5: - _currentFxSet = 1; - _currentFxIndex = i; - _currentFxVolume = s->_volume; - _currentFxDist = t.getNextInteger(); - _currentFxScale = t.getNextInteger(); - break; - case 6: - case 7: - case 8: - s->_startFxSpriteState = t.getNextInteger(); - s->_startFxSpriteNum = t.getNextInteger(); - s->_updateType = t.getNextInteger(); - if (s->_type == 7) { - s->_flagNum = t.getNextInteger(); - s->_flagValueStartFx = t.getNextInteger(); - s->_stopFxSpriteState = t.getNextInteger(); - s->_stopFxSpriteNum = t.getNextInteger(); - s->_flagValueStopFx = t.getNextInteger(); + if (t.findIndex(_locationNum)) { + t.findNextToken(kDataTokenDw); + _locationSoundsCount = t.getNextInteger(); + _currentFxSet = 0; + for (int i = 0; i < _locationSoundsCount; ++i) { + LocationSound *s = &_locationSoundsTable[i]; + s->_offset = 0; + s->_num = t.getNextInteger(); + s->_volume = t.getNextInteger(); + s->_type = t.getNextInteger(); + switch (s->_type) { + case 5: + _currentFxSet = 1; + _currentFxIndex = i; + _currentFxVolume = s->_volume; + _currentFxDist = t.getNextInteger(); + _currentFxScale = t.getNextInteger(); + break; + case 6: + case 7: + case 8: + s->_startFxSpriteState = t.getNextInteger(); + s->_startFxSpriteNum = t.getNextInteger(); + s->_updateType = t.getNextInteger(); + if (s->_type == 7) { + s->_flagNum = t.getNextInteger(); + s->_flagValueStartFx = t.getNextInteger(); + s->_stopFxSpriteState = t.getNextInteger(); + s->_stopFxSpriteNum = t.getNextInteger(); + s->_flagValueStopFx = t.getNextInteger(); + } + break; + } + if (s->_type == 8) { + s->_type = 6; } - break; - } - if (s->_type == 8) { - s->_type = 6; } - } - t.findNextToken(kDataTokenDw); - int count = t.getNextInteger(); - _locationMusicsCount = 0; - for (int i = 0; i < count; ++i) { - int flagNum = t.getNextInteger(); - int flagValue = t.getNextInteger(); - if (flagValue == _flagsTable[flagNum]) { - LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++]; - m->_offset = 0; - m->_num = t.getNextInteger(); - m->_volume = t.getNextInteger(); - m->_flag = t.getNextInteger(); - } else { - for (int j = 0; j < 3; ++j) { - t.getNextInteger(); + t.findNextToken(kDataTokenDw); + int count = t.getNextInteger(); + _locationMusicsCount = 0; + for (int i = 0; i < count; ++i) { + int flagNum = t.getNextInteger(); + int flagValue = t.getNextInteger(); + if (flagValue == _flagsTable[flagNum]) { + LocationMusic *m = &_locationMusicsTable[_locationMusicsCount++]; + m->_offset = 0; + m->_num = t.getNextInteger(); + m->_volume = t.getNextInteger(); + m->_flag = t.getNextInteger(); + } else { + for (int j = 0; j < 3; ++j) { + t.getNextInteger(); + } } } + } else { + error("loadFx() - Index not found for location %d", _locationNum); } } diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index 2fb881f77e..d9f284e443 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -40,7 +40,7 @@ void TuckerEngine::handleIntroSequence() { _player = new AnimationSequencePlayer(_system, _mixer, _eventMan, &_compressedSound, firstSequence); _player->mainLoop(); delete _player; - _player = 0; + _player = nullptr; } void TuckerEngine::handleCreditsSequence() { @@ -115,7 +115,8 @@ void TuckerEngine::handleCreditsSequence() { if (counter4 == _creditsSequenceTimecounts[num]) { _fadePaletteCounter = 0; clearSprites(); - ++num; + if (num < 6) + ++num; Common::String filename; if (num == 6) { for (int i = 0; i < 16; ++i) { @@ -123,6 +124,7 @@ void TuckerEngine::handleCreditsSequence() { loadImage(filename.c_str(), imgBuf + i * 64000, 2); } } else { + filename = ""; switch (num) { case 1: filename = "loc75.pcx"; @@ -140,7 +142,8 @@ void TuckerEngine::handleCreditsSequence() { filename = "loc78.pcx"; break; } - loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2); + if (filename != "") + loadImage(filename.c_str(), _quadBackgroundGfxBuf, 2); } _spritesCount = _creditsSequenceSpriteCounts[num]; ++_flagsTable[236]; diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index adf4be6b65..de555cd7b6 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -50,6 +50,7 @@ TuckerEngine::TuckerEngine(OSystem *system, Common::Language language, uint32 fl _currentSaveLoadGameState = 1; _fileLoadSize = 0; _csDataSize = 0; + _startSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1; _player = nullptr; _loadTempBuf = nullptr; @@ -91,7 +92,8 @@ Common::Error TuckerEngine::run() { initGraphics(kScreenWidth, kScreenHeight, false); syncSoundSettings(); _compressedSound.openFile(); - handleIntroSequence(); + if (_startSlot == -1) + handleIntroSequence(); if ((_gameFlags & kGameFlagIntroOnly) == 0 && !shouldQuit()) { mainLoop(); } @@ -604,6 +606,7 @@ void TuckerEngine::mainLoop() { _flagsTable[236] = 74; } } + if (_flagsTable[236] > 70) { handleCreditsSequence(); _quitGame = true; @@ -890,9 +893,8 @@ void TuckerEngine::updateCharPosition() { if (action->_testFlag1Num < 500) { if (action->_testFlag1Num >= 300) error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num); - if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value) { + if (_flagsTable[action->_testFlag1Num] != action->_testFlag1Value) skip = false; - } } else if (_inventoryItemsState[action->_testFlag1Num - 500] != action->_testFlag1Value) { skip = false; } @@ -900,9 +902,10 @@ void TuckerEngine::updateCharPosition() { } if (action->_testFlag2Num != 0) { if (action->_testFlag2Num < 500) { - if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value) { + if (action->_testFlag2Num >= 300) + error("updateCharPosition() - Unexpected value for _testFlag1Num : %d", action->_testFlag1Num); + if (_flagsTable[action->_testFlag2Num] != action->_testFlag2Value) skip = false; - } } else if (_inventoryItemsState[action->_testFlag2Num - 500] != action->_testFlag2Value) { skip = false; } diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index adcd02b2fe..a423915a5f 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -613,6 +613,7 @@ protected: CompressedSound _compressedSound; Common::Language _gameLang; uint32 _gameFlags; + int _startSlot; bool _quitGame; bool _fastMode; diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp index c1ded75f02..62b37346da 100644 --- a/engines/voyeur/animation.cpp +++ b/engines/voyeur/animation.cpp @@ -48,7 +48,7 @@ RL2Decoder::~RL2Decoder() { } bool RL2Decoder::loadVideo(int videoId) { - Common::String filename = Common::String::format("%s.rl2", + Common::String filename = Common::String::format("%s.rl2", ::Voyeur::SZ_FILENAMES[videoId * 2]); return loadRL2File(filename, false); } @@ -121,7 +121,7 @@ void RL2Decoder::readNextPacket() { if (_soundFrameNumber == -1) _soundFrameNumber = (frameNumber == -1) ? 0 : frameNumber; - while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD && + while (audioTrack->numQueuedStreams() < SOUND_FRAMES_READAHEAD && (_soundFrameNumber < (int)_soundFrames.size())) { _fileStream->seek(_soundFrames[_soundFrameNumber]._offset); audioTrack->queueSound(_fileStream, _soundFrames[_soundFrameNumber]._size); @@ -217,13 +217,13 @@ bool RL2Decoder::RL2FileHeader::isValid() const { } Common::Rational RL2Decoder::RL2FileHeader::getFrameRate() const { - return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) : + return (_soundRate > 0) ? Common::Rational(_rate, _defSoundSize) : Common::Rational(11025, 1103); } /*------------------------------------------------------------------------*/ -RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, +RL2Decoder::RL2VideoTrack::RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, Common::SeekableReadStream *stream): _header(header), _fileStream(stream) { _frameOffsets = nullptr; @@ -261,7 +261,7 @@ void RL2Decoder::RL2VideoTrack::initBackSurface() { bool RL2Decoder::RL2VideoTrack::seek(const Audio::Timestamp &time) { int frame = getFrameAtTime(time); - + if (frame < 0 || frame >= _header._numFrames) return false; @@ -287,7 +287,7 @@ const Graphics::Surface *RL2Decoder::RL2VideoTrack::decodeNextFrame() { _fileStream->seek(0x324); rl2DecodeFrameWithoutTransparency(0); - Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200), + Common::copy((byte *)_surface->getPixels(), (byte *)_surface->getPixels() + (320 * 200), (byte *)_backSurface->getPixels()); _dirtyRects.push_back(Common::Rect(0, 0, _surface->w, _surface->h)); _initialFrame = false; @@ -433,7 +433,7 @@ Graphics::Surface *RL2Decoder::RL2VideoTrack::getBackSurface() { /*------------------------------------------------------------------------*/ -RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType): +RL2Decoder::RL2AudioTrack::RL2AudioTrack(const RL2FileHeader &header, Common::SeekableReadStream *stream, Audio::Mixer::SoundType soundType): _header(header), _soundType(soundType) { // Create audio straem for the audio track _audStream = Audio::makeQueuingAudioStream(_header._rate, _header._channels == 2); @@ -450,7 +450,7 @@ void RL2Decoder::RL2AudioTrack::queueSound(Common::SeekableReadStream *stream, i Common::MemoryReadStream *memoryStream = new Common::MemoryReadStream(data, size, DisposeAfterUse::YES); - _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate, + _audStream->queueAudioStream(Audio::makeRawStream(memoryStream, _header._rate, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES), DisposeAfterUse::YES); } @@ -458,7 +458,7 @@ Audio::AudioStream *RL2Decoder::RL2AudioTrack::getAudioStream() const { return _audStream; } -void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, +void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, byte *frames, byte *imgPos) { vm->flipPageAndWait(); int paletteStart = getPaletteStart(); @@ -472,14 +472,14 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, vm->_graphicsManager->setPalette128(palette, paletteStart, paletteCount); } - + if (needsUpdate()) { if (frames) { // If reached a point where a new background is needed, load it // and copy over to the video decoder if (getCurFrame() >= READ_LE_UINT16(frames + picCtr * 4)) { PictureResource *newPic = vm->_bVoy->boltEntry(0x302 + picCtr)._picResource; - Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32, + Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32, READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20); vm->_graphicsManager->sDrawPic(newPic, &videoFrame, pt); @@ -492,7 +492,7 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset, Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200, (byte *)vm->_graphicsManager->_screenSurface.getPixels()); } - + vm->_eventsManager->getMouseInfo(); g_system->delayMillis(10); } diff --git a/engines/voyeur/animation.h b/engines/voyeur/animation.h index b17e998214..bc6d8a361a 100644 --- a/engines/voyeur/animation.h +++ b/engines/voyeur/animation.h @@ -105,7 +105,7 @@ private: class RL2VideoTrack : public FixedRateVideoTrack { public: - RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, + RL2VideoTrack(const RL2FileHeader &header, RL2AudioTrack *audioTrack, Common::SeekableReadStream *stream); ~RL2VideoTrack(); diff --git a/engines/voyeur/data.cpp b/engines/voyeur/data.cpp index cc0b81a313..b8c987f18b 100644 --- a/engines/voyeur/data.cpp +++ b/engines/voyeur/data.cpp @@ -94,7 +94,7 @@ SVoy::SVoy(VoyeurEngine *vm):_vm(vm) { _evCmPtrs[i] = nullptr; } -void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, +void SVoy::addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, int on, int off, int dead) { VoyeurEvent &e = _events[_eventCount++]; @@ -309,7 +309,7 @@ bool SVoy::checkForKey() { if (e._audioVideoId == 40 && e._computerOn < 2 && e._computerOff > 6) state->_victimEvidenceIndex = 4; break; - + default: break; } @@ -321,7 +321,7 @@ bool SVoy::checkForKey() { if (e._audioVideoId == 8 && e._computerOn < 2 && e._computerOff > 26) state->_victimEvidenceIndex = 1; break; - + case 3: if (e._audioVideoId == 20 && e._computerOn < 2 && e._computerOff > 28) state->_victimEvidenceIndex = 3; diff --git a/engines/voyeur/data.h b/engines/voyeur/data.h index 98c884d0c1..a18ad84f51 100644 --- a/engines/voyeur/data.h +++ b/engines/voyeur/data.h @@ -101,7 +101,7 @@ public: */ bool isInRange(int slotIndex, int hotspotIndex, int v) const { return _min[slotIndex][hotspotIndex] <= v && - v < _max[slotIndex][hotspotIndex]; + v < _max[slotIndex][hotspotIndex]; } }; @@ -164,7 +164,7 @@ public: /** * Add an event to the list of game events that have occurred */ - void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, + void addEvent(int hour, int minute, VoyeurEventType type, int audioVideoId, int on, int off, int dead); /** @@ -181,7 +181,7 @@ public: * Adds the start of an audio event happening */ void addAudioEventStart(); - + /** * Adsd the finish of an audio event happening */ @@ -191,17 +191,17 @@ public: * Adds the start of an evidence event happening */ void addEvidEventStart(int v); - + /** * Adds the finish of an evidence event happening */ void addEvidEventEnd(int totalPages); - + /** * Adds the start of a computer event happening */ void addComputerEventStart(); - + /** * Adds the finish of a computer event happening */ diff --git a/engines/voyeur/debugger.cpp b/engines/voyeur/debugger.cpp index 234300bce5..e9a12180da 100644 --- a/engines/voyeur/debugger.cpp +++ b/engines/voyeur/debugger.cpp @@ -29,11 +29,10 @@ namespace Voyeur { Debugger::Debugger(VoyeurEngine *vm) : GUI::Debugger(), _vm(vm) { // Register methods - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("exit", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("time", WRAP_METHOD(Debugger, Cmd_Time)); - DCmd_Register("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); - DCmd_Register("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); + registerCmd("continue", WRAP_METHOD(Debugger, cmdExit)); + registerCmd("time", WRAP_METHOD(Debugger, Cmd_Time)); + registerCmd("hotspots", WRAP_METHOD(Debugger, Cmd_Hotspots)); + registerCmd("mouse", WRAP_METHOD(Debugger, Cmd_Mouse)); // Set fields _isTimeActive = true; @@ -46,44 +45,44 @@ static const int TIME_STATES[] = { bool Debugger::Cmd_Time(int argc, const char **argv) { if (argc < 2) { - // Get the current day and time of day + // Get the current day and time of day Common::String dtString = _vm->getDayName(); Common::String timeString = _vm->getTimeOfDay(); if (!timeString.empty()) dtString += " " + timeString; - DebugPrintf("Time period = %d, date/time is: %s, time is %s\n", + debugPrintf("Time period = %d, date/time is: %s, time is %s\n", _vm->_voy->_transitionId, dtString.c_str(), _isTimeActive ? "on" : "off"); - DebugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]); + debugPrintf("Format: %s [on | off | 1..17 | val <amount>]\n\n", argv[0]); } else { if (!strcmp(argv[1], "on")) { _isTimeActive = true; - DebugPrintf("Time is now on\n\n"); + debugPrintf("Time is now on\n\n"); } else if (!strcmp(argv[1], "off")) { _isTimeActive = false; - DebugPrintf("Time is now off\n\n"); + debugPrintf("Time is now off\n\n"); } else if (!strcmp(argv[1], "val")) { if (argc < 3) { - DebugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum); + debugPrintf("Time expired is currently %d.\n", _vm->_voy->_RTVNum); } else { _vm->_voy->_RTVNum = atoi(argv[2]); - DebugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum); + debugPrintf("Time expired is now %d.\n", _vm->_voy->_RTVNum); } } else { int timeId = atoi(argv[1]); if (timeId >= 1 && timeId < 17) { int stateId = TIME_STATES[timeId - 1]; if (!stateId) { - DebugPrintf("Given time period is not used in-game\n"); + debugPrintf("Given time period is not used in-game\n"); } else { - DebugPrintf("Changing to time period: %d\n", timeId); + debugPrintf("Changing to time period: %d\n", timeId); if (_vm->_mainThread->goToState(-1, stateId)) _vm->_mainThread->parsePlayCommands(); return false; } } else { - DebugPrintf("Unknown parameter\n\n"); + debugPrintf("Unknown parameter\n\n"); } } } @@ -93,7 +92,7 @@ bool Debugger::Cmd_Time(int argc, const char **argv) { bool Debugger::Cmd_Hotspots(int argc, const char **argv) { if (_vm->_voy->_computerTextId >= 0) { - DebugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n", + debugPrintf("Hotspot Computer Screen %d - %d,%d->%d,%d\n", _vm->_voy->_computerTextId, _vm->_voy->_computerScreenRect.left, _vm->_voy->_computerScreenRect.top, @@ -112,9 +111,9 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { hotspots[hotspotIdx].right, hotspots[hotspotIdx].bottom); int arrIndex = hotspots[hotspotIdx]._arrIndex; if (_vm->_voy->_roomHotspotsEnabled[arrIndex - 1]) { - DebugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos); + debugPrintf("Hotspot Room %d - %s - Enabled\n", arrIndex, pos); } else { - DebugPrintf("Hotspot Room - %s - Disabled\n", pos); + debugPrintf("Hotspot Room - %s - Disabled\n", pos); } } } @@ -132,14 +131,14 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { for (int arrIndex = 0; arrIndex < 3; ++arrIndex) { if (_vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Audio slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_audioHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_audioHotspotTimes._max[arrIndex][hotspotIdx]); } if (_vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Evidence slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_evidenceHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_evidenceHotspotTimes._max[arrIndex][hotspotIdx]); @@ -148,7 +147,7 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { for (int arrIndex = 0; arrIndex < 8; ++arrIndex) { if (_vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx] != 9999) { - DebugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n", + debugPrintf("Hotspot %d %s Video slot %d, time: %d to %d\n", hotspotIdx, pos.c_str(), arrIndex, _vm->_voy->_videoHotspotTimes._min[arrIndex][hotspotIdx], _vm->_voy->_videoHotspotTimes._max[arrIndex][hotspotIdx]); @@ -157,16 +156,16 @@ bool Debugger::Cmd_Hotspots(int argc, const char **argv) { } } - DebugPrintf("\nEnd of list\n"); + debugPrintf("\nEnd of list\n"); return true; } bool Debugger::Cmd_Mouse(int argc, const char **argv) { if (argc < 2) { - DebugPrintf("mouse [ on | off ]\n"); + debugPrintf("mouse [ on | off ]\n"); } else { _showMousePosition = !strcmp(argv[1], "on"); - DebugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off"); + debugPrintf("Mouse position is now %s\n", _showMousePosition ? "on" : "off"); } return true; diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp index 9a3c6d00ff..7ce7351e65 100644 --- a/engines/voyeur/events.cpp +++ b/engines/voyeur/events.cpp @@ -73,7 +73,7 @@ EventsManager::EventsManager(VoyeurEngine *vm) : _intPtr(_gameData), Common::fill(&_cycleTime[0], &_cycleTime[4], 0); Common::fill(&_cycleNext[0], &_cycleNext[4], (byte *)nullptr); _cyclePtr = NULL; - + _leftClick = _rightClick = false; _mouseClicked = _newMouseClicked = false; _newLeftClick = _newRightClick = false;; @@ -158,7 +158,7 @@ void EventsManager::checkForNextFrameCounter() { showMousePosition(); // Display the frame - g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(), + g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(), SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); g_system->updateScreen(); @@ -218,7 +218,7 @@ void EventsManager::videoTimer() { _gameData._hasPalette = false; g_system->getPaletteManager()->setPalette(_gameData._palette + - _gameData._palStartIndex * 3, _gameData._palStartIndex, + _gameData._palStartIndex * 3, _gameData._palStartIndex, _gameData._palEndIndex - _gameData._palStartIndex + 1); } } @@ -241,7 +241,7 @@ void EventsManager::delayClick(int cycles) { do { g_system->delayMillis(10); getMouseInfo(); - } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd + } while (!_vm->shouldQuit() && g_system->getMillis() < delayEnd && !_vm->_eventsManager->_mouseClicked); } @@ -315,7 +315,7 @@ void EventsManager::startFade(CMapResource *cMap) { palEntry._bEntry = vgaP[2] << 8; int bDiff = (cMap->_entries[mapIndex * 3 + 2] << 8) - palEntry._bEntry; palEntry._bChange = bDiff / cMap->_steps; - + palEntry._palIndex = idx; if (!(cMap->_fadeStatus & 1)) ++mapIndex; @@ -431,12 +431,12 @@ void EventsManager::vDoCycleInt() { byte b = pPal[start * 3 + 2]; Common::copy(&pPal[start * 3 + 3], &pPal[end * 3 + 3], &pPal[start * 3]); - + // Place the original saved entry at the end of the range pPal[end * 3] = r; pPal[end * 3 + 1] = g; pPal[end * 3 + 2] = b; - + if (_fadeStatus & 1) { //dx = start, di = end warning("TODO: Adjustment of ViewPortListResource"); @@ -454,12 +454,12 @@ void EventsManager::vDoCycleInt() { // Move the remainder of the range forwards one entry Common::copy_backward(&pPal[start * 3], &pPal[end * 3], &pPal[end * 3 + 3]); - + // Place the original saved entry at the end of the range pPal[start * 3] = r; pPal[start * 3 + 1] = g; pPal[start * 3 + 2] = b; - + if (_fadeStatus & 1) { //dx = start, di = end warning("TODO: Adjustment of ViewPortListResource"); diff --git a/engines/voyeur/events.h b/engines/voyeur/events.h index 5e0bfe6404..0c1cef0955 100644 --- a/engines/voyeur/events.h +++ b/engines/voyeur/events.h @@ -38,7 +38,7 @@ class CMapResource; #define GAME_FRAME_TIME (1000 / GAME_FRAME_RATE) typedef void (EventsManager::*EventMethodPtr)(); - + class IntNode { public: EventMethodPtr _intFunc; diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp index 7369d9280e..346fd2419e 100644 --- a/engines/voyeur/files.cpp +++ b/engines/voyeur/files.cpp @@ -421,8 +421,8 @@ byte *BoltFile::getBoltMember(uint32 id) { } void BoltFile::initDefault() { - _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, - _state._curMemberPtr->_mode); + _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, + _state._curMemberPtr->_mode); } /*------------------------------------------------------------------------*/ @@ -505,7 +505,7 @@ void BVoyBoltFile::initSoundMap() { } void BVoyBoltFile::sInitRect() { - _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, + _state._curMemberPtr->_data = _state.decompress(NULL, _state._curMemberPtr->_size, _state._curMemberPtr->_mode); // Check whether the resource Id is in the list of extended rects @@ -522,7 +522,7 @@ void BVoyBoltFile::sInitRect() { void BVoyBoltFile::sInitPic() { // Read in the header data _state._curMemberPtr->_data = _state.decompress(NULL, 24, _state._curMemberPtr->_mode); - _state._curMemberPtr->_picResource = new PictureResource(_state, + _state._curMemberPtr->_picResource = new PictureResource(_state, _state._curMemberPtr->_data); } @@ -567,14 +567,14 @@ void StampBoltFile::initResource(int resType) { void StampBoltFile::initThread() { initDefault(); - _state._curMemberPtr->_threadResource = new ThreadResource(_state, + _state._curMemberPtr->_threadResource = new ThreadResource(_state, _state._curMemberPtr->_data); } void StampBoltFile::initPtr() { initDefault(); - _state._curMemberPtr->_ptrResource = new PtrResource(_state, + _state._curMemberPtr->_ptrResource = new PtrResource(_state, _state._curMemberPtr->_data); } @@ -585,7 +585,7 @@ void StampBoltFile::initControl() { initDefault(); ControlResource *res; - _state._curMemberPtr->_controlResource = res = new ControlResource(_state, + _state._curMemberPtr->_controlResource = res = new ControlResource(_state, _state._curMemberPtr->_data); _state._vm->_controlGroupPtr = _state._curGroupPtr; @@ -596,7 +596,7 @@ void StampBoltFile::initState() { initDefault(); assert(_state._curMemberPtr->_size == 16); - _state._curMemberPtr->_stateResource = new StateResource(_state, + _state._curMemberPtr->_stateResource = new StateResource(_state, _state._curMemberPtr->_data); } @@ -658,7 +658,7 @@ BoltEntry::BoltEntry(Common::SeekableReadStream *f, uint16 id): _file(f), _id(id _mode = buffer[0]; _initMethod = buffer[3]; _size = READ_LE_UINT32(&buffer[4]) & 0xffffff; - _fileOffset = READ_LE_UINT32(&buffer[8]); + _fileOffset = READ_LE_UINT32(&buffer[8]); } BoltEntry::~BoltEntry() { @@ -687,7 +687,7 @@ void BoltEntry::load() { */ bool BoltEntry::hasResource() const { return _rectResource || _picResource || _viewPortResource || _viewPortListResource - || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource + || _fontResource || _fontInfoResource || _cMapResource || _vInitCycleResource || _ptrResource || _controlResource || _stateResource || _threadResource; } @@ -719,7 +719,7 @@ RectResource::RectResource(const byte *src, int size, bool isExtendedRects) { int x1 = READ_LE_UINT16(src); int y1 = READ_LE_UINT16(src + 2); - int x2 = READ_LE_UINT16(src + 4); + int x2 = READ_LE_UINT16(src + 4); int y2 = READ_LE_UINT16(src + 6); _entries.push_back(RectEntry(x1, y1, x2, y2, arrIndex, rectCount)); @@ -896,7 +896,7 @@ int DisplayResource::drawText(const Common::String &msg) { viewPort->_fontRect.top -= fontInfo._shadow.y; } } - } + } if (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) { viewPort->addSaveRect(viewPort->_pageIndex, viewPort->_fontRect); @@ -971,7 +971,7 @@ int DisplayResource::drawText(const Common::String &msg) { fontChar._imgData = fontData._charImages + offset * 2; gfxManager.sDrawPic(&fontChar, this, Common::Point(xp, yp)); - + fontChar._imgData = NULL; xp += charWidth + padding; msgWidth += charWidth + padding; @@ -1056,7 +1056,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): byte *imgData = state._curLibPtr->boltEntry(id)._picResource->_imgData; _freeImgData = DisposeAfterUse::NO; - // TODO: Double check code below. Despite different coding in the + // TODO: Double check code below. Despite different coding in the // original, both looked like they do the same formula if (_flags & PICFLAG_PIC_OFFSET) { _imgData = imgData + (READ_LE_UINT32(&src[18]) & 0xffff); @@ -1082,7 +1082,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): if (mode != state._vm->_graphicsManager->_SVGAMode) { state._vm->_graphicsManager->_SVGAMode = mode; - state._vm->_graphicsManager->clearPalette(); + state._vm->_graphicsManager->clearPalette(); } int screenOffset = READ_LE_UINT32(&src[18]) & 0xffff; @@ -1118,7 +1118,7 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src): _imgData = new byte[nbytes]; Common::fill(_imgData, _imgData + nbytes, 0); } else { - _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode); + _imgData = state.decompress(NULL, nbytes, state._curMemberPtr->_mode); } } } @@ -1131,7 +1131,7 @@ PictureResource::PictureResource(Graphics::Surface *surface) { _maskData = 0; _planeSize = 0; _keyColor = 0; - + _bounds = Common::Rect(0, 0, surface->w, surface->h); _imgData = (byte *)surface->getPixels(); _freeImgData = DisposeAfterUse::NO; @@ -1150,7 +1150,7 @@ PictureResource::PictureResource() { _freeImgData = DisposeAfterUse::NO; } -PictureResource::PictureResource(int flags, int select, int pick, int onOff, +PictureResource::PictureResource(int flags, int select, int pick, int onOff, const Common::Rect &bounds, int maskData, byte *imgData, int planeSize) { _flags = flags; _select = select; @@ -1189,7 +1189,7 @@ void PictureResource::flipVertical(const byte *data) { for (int y = 0; y < _bounds.height(); ++y) { Common::copy(srcP, srcP + _bounds.width(), destP); srcP += _bounds.width(); - destP -= _bounds.width(); + destP -= _bounds.width(); } } @@ -1205,7 +1205,7 @@ ViewPortResource::ViewPortResource(BoltFilesState &state, const byte *src): int xs = READ_LE_UINT16(src + 12); int ys = READ_LE_UINT16(src + 14); - _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16), + _bounds = Common::Rect(xs, ys, xs + READ_LE_UINT16(src + 16), ys + READ_LE_UINT16(src + 18)); _currentPic = state._curLibPtr->getPictureResource(READ_LE_UINT32(src + 0x20)); @@ -1285,7 +1285,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi yDiff = r.bottom - page->_bounds.bottom; if (xDiff > 0) - r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0); + r.setWidth(xDiff <= r.width() ? r.width() - xDiff : 0); if (yDiff > 0) r.setHeight(yDiff <= r.height() ? r.height() - yDiff : 0); } @@ -1305,7 +1305,7 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi r.top = clippingRect->top; r.setHeight(yDiff <= height ? height - yDiff : 0); } - + xDiff = r.right - clippingRect->right; yDiff = r.bottom - clippingRect->bottom; @@ -1339,7 +1339,7 @@ void ViewPortResource::setupViewPort(PictureResource *pic, Common::Rect *clippin void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) { Common::Rect rect = r; - + if (clipRect(rect)) { if (_addFn) { (_state._vm->_graphicsManager->*_addFn)(this, pageIndex, rect); @@ -1355,21 +1355,21 @@ void ViewPortResource::fillPic(byte onOff) { void ViewPortResource::drawIfaceTime() { // Hour display - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, (_state._vm->_gameHour / 10) == 0 ? 10 : _state._vm->_gameHour / 10, Common::Point(161, 25)); - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameHour % 10, Common::Point(172, 25)); // Minute display - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameMinute / 10, Common::Point(190, 25)); - _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort, _state._vm->_gameMinute % 10, Common::Point(201, 25)); // AM/PM indicator PictureResource *pic = _state._vm->_bVoy->boltEntry(_state._vm->_voy->_isAM ? 272 : 273)._picResource; - _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort, + _state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort, Common::Point(215, 27)); } @@ -1488,9 +1488,9 @@ FontInfoResource::FontInfoResource() { _shadowColor = 0; } -FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, - byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos, - int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor, +FontInfoResource::FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, + byte fontFlags, FontJustify justify, int fontSaveBack, const Common::Point &pos, + int justifyWidth, int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, int shadowColor) { _curFont = NULL; _picFlags = picFlags; @@ -1516,7 +1516,7 @@ CMapResource::CMapResource(BoltFilesState &state, const byte *src): _vm(state._v _fadeStatus = src[1]; _start = READ_LE_UINT16(src + 2); _end = READ_LE_UINT16(src + 4); - + int count = _end - _start + 1; _entries = new byte[count * 3]; Common::copy(src + 6, src + 6 + 3 * count, _entries); @@ -1607,7 +1607,7 @@ ControlResource::ControlResource(BoltFilesState &state, const byte *src) { /*------------------------------------------------------------------------*/ StateResource::StateResource(BoltFilesState &state, const byte *src): - _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]), + _victimIndex(_vals[1]), _victimEvidenceIndex(_vals[2]), _victimMurderIndex(_vals[3]) { for (int i = 0; i < 4; ++i) _vals[i] = READ_LE_UINT32(src + i * 4); diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h index 49c0b2c8a4..eef5df497c 100644 --- a/engines/voyeur/files.h +++ b/engines/voyeur/files.h @@ -114,7 +114,7 @@ public: void resolveIt(uint32 id, byte **p); void resolveFunction(uint32 id, GraphicMethodPtr *fn); - BoltEntry &boltEntry(uint16 id); + BoltEntry &boltEntry(uint16 id); BoltEntry &getBoltEntryFromLong(uint32 id); PictureResource *getPictureResource(uint32 id); CMapResource *getCMapResource(uint32 id); @@ -160,7 +160,7 @@ public: int _fileOffset; Common::Array<BoltEntry> _entries; public: - BoltGroup(Common::SeekableReadStream *f); + BoltGroup(Common::SeekableReadStream *f); virtual ~BoltGroup(); void load(uint16 groupId); @@ -234,15 +234,15 @@ public: /* bvoy.blt resource types */ enum PictureFlag { - PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10, + PICFLAG_2 = 2, PICFLAG_PIC_OFFSET = 8, PICFLAG_CLEAR_SCREEN = 0x10, PICFLAG_20 = 0x20, PICFLAG_HFLIP = 0x40, PICFLAG_VFLIP = 0x80, PICFLAG_100 = 0x100, - PICFLAG_CLEAR_SCREEN00 = 0x1000 + PICFLAG_CLEAR_SCREEN00 = 0x1000 }; enum DisplayFlag { - DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8, + DISPFLAG_1 = 1, DISPFLAG_2 = 2, DISPFLAG_4 = 4, DISPFLAG_8 = 8, DISPFLAG_10 = 0x10, DISPFLAG_20 = 0x20, DISPFLAG_40 = 0x40, DISPFLAG_80 = 0x80, - DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400, + DISPFLAG_100 = 0x100, DISPFLAG_200 = 0x200, DISPFLAG_400 = 0x400, DISPFLAG_800 = 0x800, DISPFLAG_1000 = 0x1000, DISPFLAG_2000 = 0x2000, DISPFLAG_4000 = 0x4000, DISPFLAG_VIEWPORT = 0x8000, DISPFLAG_CURSOR = 0x10000, DISPFLAG_NONE = 0}; @@ -256,7 +256,7 @@ public: DisplayResource(); DisplayResource(VoyeurEngine *vm); - /** + /** * Fill a box of the given size at the current _drawPtr location */ void sFillBox(int width, int height); @@ -308,7 +308,7 @@ public: DisposeAfterUse::Flag _freeImgData; public: PictureResource(BoltFilesState &state, const byte *src); - PictureResource(int flags, int select, int pick, int onOff, + PictureResource(int flags, int select, int pick, int onOff, const Common::Rect &bounds, int maskData, byte *imgData, int planeSize); PictureResource(Graphics::Surface *surface); PictureResource(); @@ -334,7 +334,7 @@ public: PictureResource *_pages[2]; // Rect lists and counts. Note that _rectListCount values of '-1' seem to have - // special significance, which is why I'm not making them redundant in favor + // special significance, which is why I'm not making them redundant in favor // of the arrays' .size() method Common::Array<Common::Rect> *_rectListPtr[3]; int _rectListCount[3]; @@ -413,9 +413,9 @@ public: public: FontInfoResource(BoltFilesState &state, const byte *src); FontInfoResource(); - FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags, - FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth, - int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, + FontInfoResource(byte picFlags, byte picSelect, byte picPick, byte picOnOff, byte fontFlags, + FontJustify justify, int fontSaveBack, const Common::Point &pos, int justifyWidth, + int justifyHeight, const Common::Point &shadow, int foreColor, int backColor, int shadowColor); }; diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp index 700944f7ef..b1960a23ac 100644 --- a/engines/voyeur/files_threads.cpp +++ b/engines/voyeur/files_threads.cpp @@ -97,7 +97,7 @@ void ThreadResource::unloadAStack(int stackId) { } bool ThreadResource::doState() { - if (!getStateInfo()) + if (!getStateInfo()) return false; getButtonsFlags(); @@ -122,7 +122,7 @@ bool ThreadResource::getStateInfo() { uint32 fld = READ_LE_UINT32(_ctlPtr + 2); fld += _stateId << 3; _nextStateId = READ_LE_UINT32(_ctlPtr + fld + 4); - + fld = READ_LE_UINT32(_ctlPtr + fld); byte *baseP = _ctlPtr + fld; _stateCount = READ_LE_UINT16(baseP); @@ -133,7 +133,7 @@ bool ThreadResource::getStateInfo() { _playCommandsPtr += (READ_LE_UINT32(baseP + 6) / 2) << 1; _threadInfoPtr = baseP + 10; - + getButtonsText(); return true; } @@ -146,7 +146,7 @@ byte *ThreadResource::getDataOffset() { void ThreadResource::getButtonsText() { int idx = 0; - + for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) { if (*p == 0xC0) { ++p; @@ -162,7 +162,7 @@ void ThreadResource::getButtonsText() { void ThreadResource::getButtonsFlags() { int idx = 0; - + for (const byte *p = _threadInfoPtr; *p != 0x49; p = getNextRecord(p)) { if (*p == 0xC0) { if (*++p & 0x20) @@ -379,9 +379,9 @@ void ThreadResource::parsePlayCommands() { _vm->_eventsManager->incrementTime(1); _vm->_audioVideoId = -1; parseIndex = 999; - } - } - + } + } + dataP += 8; break; @@ -408,7 +408,7 @@ void ThreadResource::parsePlayCommands() { _vm->_voy->_eventFlags |= EVTFLAG_TIME_DISABLED; _vm->_voy->addVideoEventEnd(); _vm->_eventsManager->incrementTime(1); - + _vm->_audioVideoId = -1; _vm->_playStampGroupId = -1; @@ -494,7 +494,7 @@ void ThreadResource::parsePlayCommands() { _vm->_audioVideoId = -1; parseIndex = 999; } - break; + break; case 5: // Check whether transition to a given time period is allowed, and @@ -587,8 +587,8 @@ void ThreadResource::parsePlayCommands() { case 10: // Pick the person who is to die, during startup if (_vm->_iForceDeath == -1) { - // No specific person has been preset to be killed, so pick one randomly. - // The loop below was used because the victim was persisted from the previous + // No specific person has been preset to be killed, so pick one randomly. + // The loop below was used because the victim was persisted from the previous // play-through, so it ensured that a different victim is picked. int randomVal; do { @@ -663,7 +663,7 @@ void ThreadResource::parsePlayCommands() { if (v2 == 0 || _vm->_controlPtr->_state->_victimIndex == v2) _vm->_voy->_murderThreshold = v3; - + dataP += 4; break; @@ -819,7 +819,7 @@ const byte *ThreadResource::cardPerform(const byte *card) { case 24: case 27: case 28: - subId -= 3; + subId -= 3; // Deliberate fall-through case 21: @@ -858,13 +858,13 @@ const byte *ThreadResource::cardPerform(const byte *card) { ++count; } } - + ++card; } else { if (cardPerform2(card, id)) { card += subId; card = cardPerform(card); - while (*card++ != 61) ; + while (*card++ != 61) ; } else { card += subId; while (*card != 61 && *card != 29) @@ -878,7 +878,7 @@ const byte *ThreadResource::cardPerform(const byte *card) { assert(bVal < 8); card += 6; break; - + case 45: _newStateId = _nextStateId; _newStackId = _stackId; @@ -929,12 +929,12 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) { return vLong != vLong2; case 25: - vLong = _vm->_controlPtr->_state->_vals[*pSrc]; + vLong = _vm->_controlPtr->_state->_vals[*pSrc]; vLong2 = (int32)READ_LE_UINT32(pSrc + 1); return vLong < vLong2; case 26: - vLong = _vm->_controlPtr->_state->_vals[*pSrc]; + vLong = _vm->_controlPtr->_state->_vals[*pSrc]; vLong2 = (int32)READ_LE_UINT32(pSrc + 1); return vLong > vLong2; @@ -951,13 +951,13 @@ bool ThreadResource::cardPerform2(const byte *pSrc, int cardCmdId) { default: return false; } -} +} int ThreadResource::doApt() { loadTheApt(); _vm->_currentVocId = 151; - _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource; + _vm->_voy->_viewBounds = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._rectResource; Common::Array<RectEntry> &hotspots = _vm->_bVoy->boltEntry( _vm->_playStampGroupId + 1)._rectResource->_entries; _vm->_eventsManager->getMouseInfo(); @@ -1039,7 +1039,7 @@ int ThreadResource::doApt() { hotspotId = 5; // Draw the text description for the highlighted hotspot - pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + + pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + hotspotId + 6)._picResource; _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, Common::Point(106, 200)); @@ -1101,10 +1101,10 @@ int ThreadResource::doApt() { void ThreadResource::doRoom() { VoyeurEngine &vm = *_vm; SVoy voy = *vm._voy; - + vm.makeViewFinderP(); voy._fadingType = 0; - + if (!vm._bVoy->getBoltGroup(vm._playStampGroupId)) return; @@ -1116,7 +1116,7 @@ void ThreadResource::doRoom() { voy._fadingStep1 = 2; voy._fadingStep2 = 0; voy._fadingType = 1; - + Common::Array<RectEntry> &hotspots = vm._bVoy->boltEntry(vm._playStampGroupId + 4)._rectResource->_entries; int hotspotId = -1; @@ -1214,7 +1214,7 @@ void ThreadResource::doRoom() { vm._eventsManager->_mouseClicked = false; vm._eventsManager->startCursorBlink(); - int totalChars = vm.doComputerText(9999); + int totalChars = vm.doComputerText(9999); if (totalChars) vm._voy->addComputerEventEnd(totalChars); @@ -1345,12 +1345,12 @@ int ThreadResource::doInterface() { Common::String fname = _vm->_soundManager->getVOCFileName(_vm->_currentVocId); _vm->_soundManager->startVOCPlay(fname); _vm->_eventsManager->getMouseInfo(); - + _vm->_graphicsManager->setColor(240, 220, 220, 220); _vm->_eventsManager->_intPtr._hasPalette = true; _vm->_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED; - // Set the cusor + // Set the cusor PictureResource *crosshairsCursor = _vm->_bVoy->boltEntry(0x112)._picResource; PictureResource *eyeCursor = _vm->_bVoy->boltEntry(0x113)._picResource; PictureResource *listenCursor = _vm->_bVoy->boltEntry(0x114)._picResource; @@ -1382,7 +1382,7 @@ int ThreadResource::doInterface() { if (!mansionViewBounds.contains(pt)) pt = Common::Point(-1, -1); else - pt = _vm->_mansionViewPos + + pt = _vm->_mansionViewPos + Common::Point(pt.x - MANSION_VIEW_X, pt.y - MANSION_VIEW_Y); regionIndex = -1; @@ -1420,20 +1420,20 @@ int ThreadResource::doInterface() { // Regularly update the time display if (_vm->_voy->_RTANum & 2) { - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameMinute / 10, Common::Point(190, 25)); - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameMinute % 10, Common::Point(201, 25)); if (_vm->_voy->_RTANum & 4) { int v = _vm->_gameHour / 10; - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, v == 0 ? 10 : v, Common::Point(161, 25)); - _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, + _vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort, _vm->_gameHour % 10, Common::Point(172, 25)); pic = _vm->_bVoy->boltEntry(_vm->_voy->_isAM ? 272 : 273)._picResource; - _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, + _vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort, Common::Point(215, 27)); } } @@ -1462,7 +1462,7 @@ int ThreadResource::doInterface() { _vm->makeViewFinder(); _vm->initIFace(); - + hotspots = &_vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._rectResource->_entries; _vm->_eventsManager->getMouseInfo(); @@ -1471,7 +1471,7 @@ int ThreadResource::doInterface() { _vm->_eventsManager->_intPtr._flashTimer = 0; } } - } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() && + } while (!_vm->_eventsManager->_rightClick && !_vm->shouldQuit() && (!_vm->_eventsManager->_leftClick || regionIndex == -1)); _vm->_eventsManager->hideCursor(); @@ -1612,7 +1612,7 @@ void ThreadResource::loadTheApt() { } CMapResource *pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4)._cMapResource; - pal->_steps = 1; + pal->_steps = 1; pal->startFade(); _vm->flipPageAndWaitForFade(); } @@ -1715,7 +1715,7 @@ void ThreadResource::doAptAnim(int mode) { void ThreadResource::synchronize(Common::Serializer &s) { s.syncAsSint16LE(_aptPos.x); s.syncAsSint16LE(_aptPos.y); - + int stateId = _stateId; int stackId = _stackId; s.syncAsSint16LE(stateId); diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp index f756b9cc85..68a30e41f4 100644 --- a/engines/voyeur/graphics.cpp +++ b/engines/voyeur/graphics.cpp @@ -97,9 +97,9 @@ void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) { restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0], viewPort->_pages[1]); - + int count = viewPort->_rectListCount[0]; - restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0], + restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0], viewPort->_activePage, viewPort->_currentPic); SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]); @@ -150,7 +150,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des destPic = (PictureResource *)destDisplay; } - Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left, + Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left, initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top); width1 = width2 = srcPic->_bounds.width(); height1 = srcPic->_bounds.height(); @@ -178,7 +178,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des srcOffset -= tmpHeight * width2; height1 += tmpHeight; offset.y = newBounds.top; - + if (height1 <= 0) return; @@ -258,7 +258,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des for (uint idx = 0; idx < srcPic->_maskData; ++idx) { if (imageDataShift < 4) ++imageDataShift; - } + } } else { srcImgData = srcPic->_imgData; destImgData = destPic->_imgData; @@ -367,7 +367,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des width2 = srcPic->_bounds.width(); height1 = tmpHeight + height1; - + for (int yp = 0; yp < height1; ++yp) { runLength = 0; @@ -509,7 +509,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des if (srcFlags & DISPFLAG_2) { if (!(srcFlags & DISPFLAG_8)) { srcP = srcImgData + srcOffset; - + if (destFlags & DISPFLAG_8) { // loc_272C3 error("TODO: sDrawPic variation"); @@ -786,7 +786,7 @@ void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *des } else { // loc_271F0 srcP = srcImgData; - + if (isClipped) { // loc_2700A tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0; @@ -886,7 +886,7 @@ void GraphicsManager::flipPage() { for (uint idx = 0; idx < viewPorts.size(); ++idx) { if (viewPorts[idx]->_flags & DISPFLAG_20) { - if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1)) + if ((viewPorts[idx]->_flags & (DISPFLAG_8 || DISPFLAG_1)) == (DISPFLAG_8 || DISPFLAG_1)) { if (_planeSelect == idx) sDisplayPic(viewPorts[idx]->_currentPic); @@ -992,7 +992,7 @@ void GraphicsManager::screenReset() { _backgroundPage = NULL; _vPort->setupViewPort(NULL); - fillPic(_vPort, 0); + fillPic(_vPort, 0); _vm->flipPageAndWait(); } diff --git a/engines/voyeur/graphics.h b/engines/voyeur/graphics.h index 221d31061d..e4d0b38650 100644 --- a/engines/voyeur/graphics.h +++ b/engines/voyeur/graphics.h @@ -54,14 +54,13 @@ public: DrawInfo(int penColor, const Common::Point &pos); }; -typedef void (GraphicsManager::*GraphicMethodPtr)(); +typedef void (GraphicsManager::*GraphicMethodPtr)(); typedef void (GraphicsManager::*ViewPortSetupPtr)(ViewPortResource *); typedef void (GraphicsManager::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds); typedef void (GraphicsManager::*ViewPortRestorePtr)(ViewPortResource *); class GraphicsManager { public: - VoyeurEngine *_vm; byte _VGAColors[PALETTE_SIZE]; PictureResource *_backgroundPage; int _SVGAMode; @@ -77,6 +76,8 @@ public: DrawInfo *_drawPtr; DrawInfo _defaultDrawInfo; private: + VoyeurEngine *_vm; + void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount, PictureResource *srcPic, PictureResource *destPic); public: @@ -86,7 +87,7 @@ public: void sInitGraphics(); void setupMCGASaveRect(ViewPortResource *viewPort); - void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); + void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); void restoreMCGASaveRect(ViewPortResource *viewPort); void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds); @@ -101,7 +102,7 @@ public: void resetPalette(); void setColor(int idx, byte r, byte g, byte b); void setOneColor(int idx, byte r, byte g, byte b); - void setColors(int start, int count, const byte *pal); + void setColors(int start, int count, const byte *pal); void screenReset(); void fadeDownICF1(int steps); void fadeUpICF1(int steps = 0); diff --git a/engines/voyeur/sound.cpp b/engines/voyeur/sound.cpp index 26145bd743..c0e5a043cd 100644 --- a/engines/voyeur/sound.cpp +++ b/engines/voyeur/sound.cpp @@ -62,7 +62,7 @@ void SoundManager::startVOCPlay(const Common::String &filename) { if (!f.open(filename)) error("Could not find voc file - %s", filename.c_str()); - Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()), + Audio::SeekableAudioStream *audioStream = Audio::makeVOCStream(f.readStream(f.size()), Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream); diff --git a/engines/voyeur/staticres.cpp b/engines/voyeur/staticres.cpp index 7016793ddc..372da508f1 100644 --- a/engines/voyeur/staticres.cpp +++ b/engines/voyeur/staticres.cpp @@ -43,7 +43,7 @@ const int RESOLVE_TABLE[] = { 0x7500 }; -const int LEVEL_H[] = { +const int LEVEL_H[] = { 4, 7, 7, 8, 9, 10, 2, 2, 4, 8, 8, 9, 9, 10, 10, 11, 11 }; @@ -58,40 +58,40 @@ const int BLIND_TABLE[] = { }; const int COMPUTER_SCREEN_TABLE[] = { - 269, 128, 307, 163, - 269, 128, 307, 163, - 68, 79, 98, 102, - 68, 79, 98, 102, - 68, 79, 98, 102, + 269, 128, 307, 163, + 269, 128, 307, 163, + 68, 79, 98, 102, + 68, 79, 98, 102, + 68, 79, 98, 102, + 68, 79, 98, 102, + 248, 138, 291, 163, + 83, 132, 143, 156, + 248, 138, 291, 163, + 83, 132, 143, 156, + 83, 132, 143, 156, + 248, 138, 291, 163, 68, 79, 98, 102, - 248, 138, 291, 163, - 83, 132, 143, 156, - 248, 138, 291, 163, - 83, 132, 143, 156, - 83, 132, 143, 156, - 248, 138, 291, 163, - 68, 79, 98, 102, 68, 79, 98, 102 }; const char *const SZ_FILENAMES[] = { - "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr, - "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr, + "A2110100", nullptr, "A2300100", nullptr, "B1220100", nullptr, "C1220100", nullptr, + "C1290100", nullptr, "D1220100", nullptr, "D1270100", nullptr, "E1210100", nullptr, "E1260100", nullptr, "E1280100", nullptr, "E1325100", nullptr, "F1200100", nullptr, - "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr, - "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr, + "G1250100", nullptr, "G1260100", nullptr, "H1200100", nullptr, "H1230100", nullptr, + "H1310100", nullptr, "I1300100", nullptr, "J1220100", nullptr, "J1230100", nullptr, "J1320100", nullptr, "K1260100", nullptr, "K1280100", nullptr, "K1325100", nullptr, - "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr, - "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr, + "L1210100", nullptr, "L1280100", nullptr, "L1290100", nullptr, "L1300100", nullptr, + "L1310100", nullptr, "M1260100", nullptr, "M1310100", nullptr, "N1210100", nullptr, "N1225100", nullptr, "N1275510", nullptr, "N1280510", nullptr, "N1325100", nullptr, - "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr, - "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr, + "O1230100", nullptr, "O1260100", nullptr, "O1260520", nullptr, "O1280100", nullptr, + "O1325540", nullptr, "P1276710", nullptr, "P1280540", nullptr, "P1280740", nullptr, "P1290510", nullptr, "P1325100", nullptr, "P1325300", nullptr, "P1325520", nullptr, - "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr, - "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr, + "Q1230100", nullptr, "Q1240530", nullptr, "Q1240730", nullptr, "Q1260100", nullptr, + "Q1260520", nullptr, "Q1260720", nullptr, "Q1325100", nullptr, "R1280540", nullptr, "Z1110510", nullptr, "Z1110520", nullptr, "Z1110530", nullptr, "Z1110540", nullptr, - "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr, - "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr, + "Z1110545", nullptr, "Z2320100", nullptr, "Z2905300", nullptr, "Z3110100", nullptr, + "Z3115510", nullptr, "Z3115520", nullptr, "Z3115530", nullptr, "Z3115540", nullptr, "Z4915100", nullptr, "Z4915200", nullptr, "Z4915300", nullptr, nullptr, nullptr, nullptr, nullptr, "MMARG", "MZACK", "MREED", "MJESSI", "MCHLOE", "MCAMERA", "MENDCRED", diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp index 9843930bd3..8edacc5883 100644 --- a/engines/voyeur/voyeur.cpp +++ b/engines/voyeur/voyeur.cpp @@ -37,7 +37,7 @@ VoyeurEngine *g_vm; VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _randomSource("Voyeur"), - _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1, + _defaultFontInfo(3, 0xff, 0xff, 0, 0, ALIGN_LEFT, 0, Common::Point(), 1, 1, Common::Point(1, 1), 1, 0, 0) { _debugger = nullptr; _eventsManager = nullptr; @@ -158,7 +158,7 @@ void VoyeurEngine::initInput() { bool VoyeurEngine::doHeadTitle() { // char dest[144]; - + _eventsManager->startMainClockInt(); if (_loadGameSlot == -1) { @@ -205,7 +205,7 @@ bool VoyeurEngine::doHeadTitle() { _voy->addEvent(18, 7, EVTYPE_VIDEO, 40, 0, 998, -1); _voy->addEvent(18, 8, EVTYPE_VIDEO, 43, 0, 998, -1); _voy->addEvent(19, 1, EVTYPE_AUDIO, 20, 0, 998, -1); - } + } } _voy->_aptLoadMode = 140; @@ -271,7 +271,7 @@ bool VoyeurEngine::doLock() { _graphicsManager->setColor(2, 96, 96, 96); _graphicsManager->setColor(3, 160, 160, 160); _graphicsManager->setColor(4, 224, 224, 224); - + // Set up the cursor _eventsManager->setCursor(cursorPic); _eventsManager->showCursor(); @@ -464,11 +464,11 @@ void VoyeurEngine::doOpening() { _eventsManager->_intPtr._hasPalette = true; _graphicsManager->_vPort->setupViewPort(); flipPageAndWait(); - + RL2Decoder decoder; decoder.loadRL2File("a2300100.rl2", false); decoder.start(); - + while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) { if (decoder.hasDirtyPalette()) { const byte *palette = decoder.getPalette(); @@ -487,7 +487,7 @@ void VoyeurEngine::doOpening() { textPic = _bVoy->boltEntry(frameIndex / 2 + 0x202)._picResource; textPos = Common::Point(READ_LE_UINT16(xyTable + frameIndex * 2), READ_LE_UINT16(xyTable + (frameIndex + 1) * 2)); - + creditShow = false; } else { textPic = nullptr; @@ -500,8 +500,9 @@ void VoyeurEngine::doOpening() { if (textPic) { _graphicsManager->sDrawPic(textPic, _graphicsManager->_vPort, textPos); - flipPageAndWait(); } + + flipPageAndWait(); } _eventsManager->getMouseInfo(); @@ -560,9 +561,9 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) { RL2Decoder decoder; decoder.loadVideo(videoId); - decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000)); + decoder.seek(Audio::Timestamp(_voy->_vocSecondsOffset * 1000)); decoder.start(); - int endFrame = decoder.getCurFrame() + totalFrames; + int endFrame = decoder.getCurFrame() + totalFrames; _eventsManager->getMouseInfo(); _eventsManager->startCursorBlink(); @@ -603,9 +604,9 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) { void VoyeurEngine::playAudio(int audioId) { _bVoy->getBoltGroup(0x7F00); - _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 + + _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 + BLIND_TABLE[audioId] * 2)._picResource; - _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 + + _graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 + BLIND_TABLE[audioId] * 2)._cMapResource; _graphicsManager->_vPort->setupViewPort(); @@ -620,7 +621,7 @@ void VoyeurEngine::playAudio(int audioId) { _voy->_eventFlags |= EVTFLAG_RECORDING; _eventsManager->startCursorBlink(); - while (!shouldQuit() && !_eventsManager->_mouseClicked && + while (!shouldQuit() && !_eventsManager->_mouseClicked && _soundManager->getVOCStatus()) _eventsManager->delayClick(1); @@ -657,7 +658,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St fi._justifyHeight = 120; _graphicsManager->_vPort->drawText(time); - + if (!location.empty()) { fi._pos = Common::Point(0, 138); fi._justify = ALIGN_CENTER; @@ -723,7 +724,7 @@ void VoyeurEngine::showEndingNews() { _soundManager->startVOCPlay(fname); _eventsManager->getMouseInfo(); - while (!shouldQuit() && !_eventsManager->_mouseClicked && + while (!shouldQuit() && !_eventsManager->_mouseClicked && _soundManager->getVOCStatus()) { _eventsManager->delay(1); _eventsManager->getMouseInfo(); @@ -901,7 +902,7 @@ void VoyeurSavegameHeader::write(Common::OutSaveFile *f, VoyeurEngine *vm, const // Create a thumbnail and save it Graphics::Surface *thumb = new Graphics::Surface(); - ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(), + ::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, vm->_graphicsManager->_VGAColors); Graphics::saveThumbnail(*f, *thumb); thumb->free(); diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp index a6564c32ba..34ad62a88d 100644 --- a/engines/voyeur/voyeur_game.cpp +++ b/engines/voyeur/voyeur_game.cpp @@ -33,7 +33,7 @@ void VoyeurEngine::playStamp() { _stampLibPtr->getBoltGroup(0); _controlPtr->_state = _stampLibPtr->boltEntry(_controlPtr->_stateId >> 16)._stateResource; assert(_controlPtr->_state); - + _resolvePtr = &RESOLVE_TABLE[0]; initStamp(); @@ -57,11 +57,11 @@ void VoyeurEngine::playStamp() { _mainThread->parsePlayCommands(); bool flag = breakFlag = (_voy->_eventFlags & EVTFLAG_2) != 0; - + switch (_voy->_playStampMode) { case 5: buttonId = _mainThread->doInterface(); - + if (buttonId == -2) { switch (_mainThread->doApt()) { case 0: @@ -110,7 +110,7 @@ void VoyeurEngine::playStamp() { case 16: _voy->_transitionId = 17; buttonId = _mainThread->doApt(); - + switch (buttonId) { case 1: _mainThread->chooseSTAMPButton(22); @@ -234,19 +234,19 @@ void VoyeurEngine::closeStamp() { void VoyeurEngine::doTailTitle() { _graphicsManager->_vPort->setupViewPort(NULL); _graphicsManager->screenReset(); - + if (_bVoy->getBoltGroup(0x600)) { RL2Decoder decoder; decoder.loadRL2File("a1100200.rl2", false); decoder.start(); decoder.play(this); - + if (!shouldQuit() && !_eventsManager->_mouseClicked) { doClosingCredits(); if (!shouldQuit() && !_eventsManager->_mouseClicked) { _graphicsManager->screenReset(); - + PictureResource *pic = _bVoy->boltEntry(0x602)._picResource; CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource; @@ -315,7 +315,7 @@ void VoyeurEngine::doClosingCredits() { _graphicsManager->_vPort->drawText(msg); msg += strlen(msg) + 1; } - + if (flags & 0x40) { fi._foreColor = 2; fi._curFont = _bVoy->boltEntry(0x400)._fontResource; @@ -345,7 +345,7 @@ void VoyeurEngine::doClosingCredits() { fi._justifyHeight = 240; fi._pos = Common::Point(198, READ_LE_UINT16(entry)); - _graphicsManager->_vPort->drawText(msg); + _graphicsManager->_vPort->drawText(msg); msg += strlen(msg) + 1; } @@ -500,7 +500,7 @@ void VoyeurEngine::reviewTape() { Common::String msg = _eventsManager->getEvidString(eventNum); _graphicsManager->_backgroundPage->drawText(msg); - + yp += 15; } @@ -527,7 +527,7 @@ void VoyeurEngine::reviewTape() { break; } } - + pt = _eventsManager->getMousePos(); if (tempPos.x >= 68 && tempPos.x <= 277 && tempPos.y >= 31 && tempPos.y <= 154) { tempPos.y -= 2; @@ -545,7 +545,7 @@ void VoyeurEngine::reviewTape() { flipPageAndWait(); _graphicsManager->_drawPtr->_penColor = 0; - _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top); + _graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top); _graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height()); int yp = 45; @@ -642,7 +642,7 @@ void VoyeurEngine::reviewTape() { foundIndex = -1; _eventsManager->_rightClick = 0; } - + if (_eventsManager->_rightClick) foundIndex = 0; @@ -652,7 +652,7 @@ void VoyeurEngine::reviewTape() { _voy->_fadingType = 0; _voy->_viewBounds = nullptr; _graphicsManager->_vPort->setupViewPort(NULL); - + if (_currentVocId != -1) { _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); @@ -693,7 +693,7 @@ void VoyeurEngine::reviewTape() { uint32 secondsDuration = e._computerOff; _eventsManager->getMouseInfo(); - while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() && + while (!_eventsManager->_mouseClicked && _soundManager->getVOCStatus() && _soundManager->getVOCFrame() < secondsDuration) { _eventsManager->getMouseInfo(); _eventsManager->delay(10); @@ -707,7 +707,7 @@ void VoyeurEngine::reviewTape() { case EVTYPE_EVID: _voy->reviewAnEvidEvent(eventIndex); - + _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); _bVoy->getBoltGroup(0x900); @@ -715,7 +715,7 @@ void VoyeurEngine::reviewTape() { case EVTYPE_COMPUTER: _voy->reviewComputerEvent(eventIndex); - + _voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime; _soundManager->stopVOCPlay(); _bVoy->getBoltGroup(0x900); @@ -863,7 +863,7 @@ bool VoyeurEngine::checkForIncriminate() { for (int idx = 0; idx < _voy->_eventCount; ++idx) { VoyeurEvent &evt = _voy->_events[idx]; - + if (evt._type == EVTYPE_VIDEO) { if (evt._audioVideoId == 44 && evt._computerOn <= 40 && (evt._computerOff + evt._computerOn) >= 70) { @@ -908,7 +908,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) { _voy->_vocSecondsOffset = evt._computerOn; _eventsManager->_videoDead = evt._dead; _voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED; - + playAVideoDuration(_audioVideoId, evt._computerOff); _voy->_eventFlags |= EVTFLAG_TIME_DISABLED; @@ -929,7 +929,7 @@ void VoyeurEngine::playAVideoEvent(int eventIndex) { int VoyeurEngine::getChooseButton() { int prevIndex = -2; - Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId + Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(_playStampGroupId + 6)._rectResource->_entries; int selectedIndex = -1; @@ -949,7 +949,7 @@ int VoyeurEngine::getChooseButton() { _eventsManager->getMouseInfo(); selectedIndex = -1; Common::Point pt = _eventsManager->getMousePos(); - + for (uint idx = 0; idx < hotspots.size(); ++idx) { if (hotspots[idx].contains(pt)) { if (!_voy->_victimMurdered || ((int)idx + 1) != _controlPtr->_state->_victimIndex) { @@ -984,7 +984,7 @@ int VoyeurEngine::getChooseButton() { void VoyeurEngine::makeViewFinder() { _graphicsManager->_backgroundPage = _bVoy->boltEntry(0x103)._picResource; - _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage, + _graphicsManager->sDrawPic(_graphicsManager->_backgroundPage, _graphicsManager->_vPort, Common::Point(0, 0)); CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource; @@ -1067,7 +1067,7 @@ void VoyeurEngine::initIFace() { _mansionViewPos = Common::Point((MANSION_MAX_X - MANSION_VIEW_WIDTH) / 2, (MANSION_MAX_Y - MANSION_VIEW_HEIGHT) / 2); doScroll(_mansionViewPos); - + _voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId)._rectResource; // Show the cursor using ScummVM functionality @@ -1150,7 +1150,7 @@ Common::String VoyeurEngine::getDayName() { case 3: case 4: return SATURDAY; - case 17: + case 17: return MONDAY; default: return SUNDAY; @@ -1277,7 +1277,7 @@ void VoyeurEngine::doTimeBar() { if (_voy->_RTVLimit > 0) { if (_voy->_RTVNum > _voy->_RTVLimit || _voy->_RTVNum < 0) _voy->_RTVNum = _voy->_RTVLimit - 1; - + _timeBarVal = _voy->_RTVNum; int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit; int fullHeight = MAX(151 - height, 93); @@ -1308,14 +1308,14 @@ void VoyeurEngine::flashTimeBar() { _graphicsManager->setColor(240, 220, 20, 20); else _graphicsManager->setColor(240, 220, 220, 220); - + _eventsManager->_intPtr._hasPalette = true; _flashTimeFlag = !_flashTimeFlag; } } void VoyeurEngine::checkPhoneCall() { - if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 && + if ((_voy->_RTVLimit - _voy->_RTVNum) >= 36 && _voy->_totalPhoneCalls < 5 && _currentVocId <= 151 && _currentVocId > 146) { if ((_voy->_switchBGNum < _checkPhoneVal || _checkPhoneVal > 180) && !_soundManager->getVOCStatus()) { @@ -1361,9 +1361,9 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) { if (count > 0) { for (int idx = 1; idx <= count; ++idx) { - _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + + _voy->_evPicPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + (evidId + idx) * 2)._picResource; - _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + + _voy->_evCmPtrs[idx - 1] = _bVoy->boltEntry(_voy->_boltGroupId2 + (evidId + idx) * 2 + 1)._cMapResource; } } @@ -1394,7 +1394,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) { break; if (count == 0 || evidIdx >= eventId) continue; - + pic = _voy->_evPicPtrs[arrIndex]; _graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point((384 - pic->_bounds.width()) / 2, diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp index 51fd74e300..a313314a8b 100644 --- a/engines/wintermute/debugger.cpp +++ b/engines/wintermute/debugger.cpp @@ -29,8 +29,8 @@ namespace Wintermute { Console::Console(WintermuteEngine *vm) : GUI::Debugger(), _engineRef(vm) { - DCmd_Register("show_fps", WRAP_METHOD(Console, Cmd_ShowFps)); - DCmd_Register("dump_file", WRAP_METHOD(Console, Cmd_DumpFile)); + registerCmd("show_fps", WRAP_METHOD(Console, Cmd_ShowFps)); + registerCmd("dump_file", WRAP_METHOD(Console, Cmd_DumpFile)); } Console::~Console(void) { @@ -50,7 +50,7 @@ bool Console::Cmd_ShowFps(int argc, const char **argv) { bool Console::Cmd_DumpFile(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: %s <file path> <output file name>\n", argv[0]); + debugPrintf("Usage: %s <file path> <output file name>\n", argv[0]); return true; } @@ -60,7 +60,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) { BaseFileManager *fileManager = BaseEngine::instance().getFileManager(); Common::SeekableReadStream *inFile = fileManager->openFile(filePath); if (!inFile) { - DebugPrintf("File '%s' not found\n", argv[1]); + debugPrintf("File '%s' not found\n", argv[1]); return true; } @@ -77,7 +77,7 @@ bool Console::Cmd_DumpFile(int argc, const char **argv) { delete outFile; delete inFile; - DebugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]); + debugPrintf("Resource file '%s' dumped to file '%s'\n", argv[1], argv[2]); return true; } diff --git a/engines/zvision/core/console.cpp b/engines/zvision/core/console.cpp index 22382bc264..e610f34474 100644 --- a/engines/zvision/core/console.cpp +++ b/engines/zvision/core/console.cpp @@ -45,25 +45,25 @@ namespace ZVision { Console::Console(ZVision *engine) : GUI::Debugger(), _engine(engine) { - DCmd_Register("loadimage", WRAP_METHOD(Console, cmdLoadImage)); - DCmd_Register("loadvideo", WRAP_METHOD(Console, cmdLoadVideo)); - DCmd_Register("loadsound", WRAP_METHOD(Console, cmdLoadSound)); - DCmd_Register("raw2wav", WRAP_METHOD(Console, cmdRawToWav)); - DCmd_Register("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState)); - DCmd_Register("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable)); - DCmd_Register("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV)); - DCmd_Register("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); - DCmd_Register("changelocation", WRAP_METHOD(Console, cmdChangeLocation)); - DCmd_Register("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); - DCmd_Register("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles)); - DCmd_Register("rendertext", WRAP_METHOD(Console, cmdRenderText)); + registerCmd("loadimage", WRAP_METHOD(Console, cmdLoadImage)); + registerCmd("loadvideo", WRAP_METHOD(Console, cmdLoadVideo)); + registerCmd("loadsound", WRAP_METHOD(Console, cmdLoadSound)); + registerCmd("raw2wav", WRAP_METHOD(Console, cmdRawToWav)); + registerCmd("setrenderstate", WRAP_METHOD(Console, cmdSetRenderState)); + registerCmd("generaterendertable", WRAP_METHOD(Console, cmdGenerateRenderTable)); + registerCmd("setpanoramafov", WRAP_METHOD(Console, cmdSetPanoramaFoV)); + registerCmd("setpanoramascale", WRAP_METHOD(Console, cmdSetPanoramaScale)); + registerCmd("changelocation", WRAP_METHOD(Console, cmdChangeLocation)); + registerCmd("dumpfile", WRAP_METHOD(Console, cmdDumpFile)); + registerCmd("parseallscrfiles", WRAP_METHOD(Console, cmdParseAllScrFiles)); + registerCmd("rendertext", WRAP_METHOD(Console, cmdRenderText)); } bool Console::cmdLoadImage(int argc, const char **argv) { if (argc == 4) _engine->getRenderManager()->renderImageToScreen(argv[1], atoi(argv[2]), atoi(argv[3])); else { - DebugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); + debugPrintf("Use loadimage <fileName> <destinationX> <destinationY> to load an image to the screen\n"); return true; } @@ -72,7 +72,7 @@ bool Console::cmdLoadImage(int argc, const char **argv) { bool Console::cmdLoadVideo(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use loadvideo <fileName> to load a video to the screen\n"); + debugPrintf("Use loadvideo <fileName> to load a video to the screen\n"); return true; } @@ -86,7 +86,7 @@ bool Console::cmdLoadVideo(int argc, const char **argv) { bool Console::cmdLoadSound(int argc, const char **argv) { if (!Common::File::exists(argv[1])) { - DebugPrintf("File does not exist\n"); + debugPrintf("File does not exist\n"); return true; } @@ -105,7 +105,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) { Audio::SoundHandle handle; _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle, soundStream, -1, 100, 0, DisposeAfterUse::YES, false, false); } else { - DebugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n"); + debugPrintf("Use loadsound <fileName> [<rate> <isStereo: 1 or 0>] to load a sound\n"); return true; } @@ -114,7 +114,7 @@ bool Console::cmdLoadSound(int argc, const char **argv) { bool Console::cmdRawToWav(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n"); + debugPrintf("Use raw2wav <rawFilePath> <wavFileName> to dump a .RAW file to .WAV\n"); return true; } @@ -124,7 +124,7 @@ bool Console::cmdRawToWav(int argc, const char **argv) { bool Console::cmdSetRenderState(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); + debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); return true; } @@ -137,7 +137,7 @@ bool Console::cmdSetRenderState(int argc, const char **argv) { else if (renderState.matchString("flat", true)) _engine->getRenderManager()->getRenderTable()->setRenderState(RenderTable::FLAT); else - DebugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); + debugPrintf("Use setrenderstate <RenderState: panorama, tilt, flat> to change the current render state\n"); return true; } @@ -150,7 +150,7 @@ bool Console::cmdGenerateRenderTable(int argc, const char **argv) { bool Console::cmdSetPanoramaFoV(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n"); + debugPrintf("Use setpanoramafov <fieldOfView> to change the current panorama field of view\n"); return true; } @@ -161,7 +161,7 @@ bool Console::cmdSetPanoramaFoV(int argc, const char **argv) { bool Console::cmdSetPanoramaScale(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n"); + debugPrintf("Use setpanoramascale <scale> to change the current panorama scale\n"); return true; } @@ -172,7 +172,7 @@ bool Console::cmdSetPanoramaScale(int argc, const char **argv) { bool Console::cmdChangeLocation(int argc, const char **argv) { if (argc != 6) { - DebugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n"); + debugPrintf("Use changelocation <char: world> <char: room> <char:node> <char:view> <int: x position> to change your location\n"); return true; } @@ -183,7 +183,7 @@ bool Console::cmdChangeLocation(int argc, const char **argv) { bool Console::cmdDumpFile(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Use dumpfile <fileName> to dump a file\n"); + debugPrintf("Use dumpfile <fileName> to dump a file\n"); return true; } @@ -205,7 +205,7 @@ bool Console::cmdParseAllScrFiles(int argc, const char **argv) { bool Console::cmdRenderText(int argc, const char **argv) { if (argc != 7) { - DebugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n"); + debugPrintf("Use rendertext <text> <fontNumber> <destX> <destY> <maxWidth> <1 or 0: wrap> to render text\n"); return true; } diff --git a/engines/zvision/sound/zork_raw.cpp b/engines/zvision/sound/zork_raw.cpp index 55353acbb9..edee1fd16e 100644 --- a/engines/zvision/sound/zork_raw.cpp +++ b/engines/zvision/sound/zork_raw.cpp @@ -185,14 +185,14 @@ Audio::RewindableAudioStream *makeRawZorkStream(const Common::String &filePath, char fileIdentifier = (engine->getGameId() == GID_NEMESIS) ? fileName[6] : fileName[7]; if (engine->getGameId() == GID_NEMESIS) { - for (int i = 0; i < 6; ++i) { + for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zNemSoundParamLookupTable); ++i) { if (RawZorkStream::_zNemSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zNemSoundParamLookupTable[i]; foundParams = true; } } } else if (engine->getGameId() == GID_GRANDINQUISITOR) { - for (int i = 0; i < 6; ++i) { + for (uint i = 0; i < ARRAYSIZE(RawZorkStream::_zgiSoundParamLookupTable); ++i) { if (RawZorkStream::_zgiSoundParamLookupTable[i].identifier == fileIdentifier) { soundParams = RawZorkStream::_zgiSoundParamLookupTable[i]; foundParams = true; |
