diff options
Diffstat (limited to 'engines')
165 files changed, 40598 insertions, 1106 deletions
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 6e9a996756..0a53f0c4f4 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -218,7 +218,7 @@ bool AgiMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameD } SaveStateList AgiMetaEngine::listSaves(const char *target) const { - const uint32 AGIflag = MKID_BE('AGI:'); + const uint32 AGIflag = MKTAG('A','G','I',':'); Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); Common::StringArray filenames; char saveDesc[31]; @@ -257,7 +257,7 @@ void AgiMetaEngine::removeSaveState(const char *target, int slot) const { } SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int slot) const { - const uint32 AGIflag = MKID_BE('AGI:'); + const uint32 AGIflag = MKTAG('A','G','I',':'); char fileName[MAXPATHLEN]; sprintf(fileName, "%s.%03d", target, slot); diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index ea041a93c7..10ca797587 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -1003,7 +1003,7 @@ bool Mickey::loadGame() { if (_vm->getSelection(kSelAnyKey) == 0) return false; } else { - if (infile->readUint32BE() != MKID_BE('MICK')) { + if (infile->readUint32BE() != MKTAG('M','I','C','K')) { warning("Mickey::loadGame wrong save game format"); return false; } @@ -1120,7 +1120,7 @@ void Mickey::saveGame() { if (_vm->getSelection(kSelAnyKey) == 0) return; } else { - outfile->writeUint32BE(MKID_BE('MICK')); // header + outfile->writeUint32BE(MKTAG('M','I','C','K')); // header outfile->writeByte(MSA_SAVEGAME_VERSION); outfile->writeByte(_game.iRoom); diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index 643cbd86a9..e97c144872 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -1159,7 +1159,7 @@ void Winnie::saveGame() { if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) return; - outfile->writeUint32BE(MKID_BE('WINN')); // header + outfile->writeUint32BE(MKTAG('W','I','N','N')); // header outfile->writeByte(WTP_SAVEGAME_VERSION); outfile->writeByte(_game.fSound); @@ -1195,7 +1195,7 @@ void Winnie::loadGame() { if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) return; - if (infile->readUint32BE() == MKID_BE('WINN')) { + if (infile->readUint32BE() == MKTAG('W','I','N','N')) { saveVersion = infile->readByte(); if (saveVersion != WTP_SAVEGAME_VERSION) warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, WTP_SAVEGAME_VERSION); diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 94df063609..9194cc642c 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -53,7 +53,7 @@ namespace Agi { -static const uint32 AGIflag = MKID_BE('AGI:'); +static const uint32 AGIflag = MKTAG('A','G','I',':'); int AgiEngine::saveGame(const char *fileName, const char *description) { char gameIDstring[8] = "gameIDX"; diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 10d3d7f1ff..acdc0084c4 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -301,7 +301,7 @@ void MoviePlayerDXA::stopVideo() { void MoviePlayerDXA::startSound() { uint32 offset, size; - if (getSoundTag() == MKID_BE('WAVE')) { + if (getSoundTag() == MKTAG('W','A','V','E')) { size = _fileStream->readUint32BE(); if (_sequenceNum) { diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h index a6e0e3f1ab..f88338ed82 100644 --- a/engines/cine/saveload.h +++ b/engines/cine/saveload.h @@ -71,14 +71,14 @@ enum CineSaveGameFormat { }; /** Identifier for the temporary Operation Stealth savegame format. */ -static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP'); +static const uint32 TEMP_OS_FORMAT_ID = MKTAG('T','E','M','P'); /** The current version number of Operation Stealth's savegame format. */ static const uint32 CURRENT_OS_SAVE_VER = 1; /** Chunk header used by the temporary Operation Stealth savegame format. */ struct ChunkHeader { - uint32 id; ///< Identifier (e.g. MKID_BE('TEMP')) + uint32 id; ///< Identifier (e.g. MKTAG('T','E','M','P')) uint32 version; ///< Version number uint32 size; ///< Size of the chunk after this header in bytes }; diff --git a/engines/engines.mk b/engines/engines.mk index 414edcfc70..f8ff823c13 100644 --- a/engines/engines.mk +++ b/engines/engines.mk @@ -188,6 +188,11 @@ DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE) MODULES += engines/touche endif +ifdef ENABLE_TSAGE +DEFINES += -DENABLE_TSAGE=$(ENABLE_TSAGE) +MODULES += engines/tsage +endif + ifdef ENABLE_TUCKER DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER) MODULES += engines/tucker diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h index eeee03847a..22eb79f4bf 100644 --- a/engines/gob/save/savefile.h +++ b/engines/gob/save/savefile.h @@ -48,8 +48,8 @@ class SaveHeader { public: /** The size of the header. */ static const int kSize = 20; - static const uint32 kID1 = MKID_BE('\0SCV'); - static const uint32 kID2 = MKID_BE('MGOB'); + static const uint32 kID1 = MKTAG(0,'S','C','V'); + static const uint32 kID2 = MKTAG('M','G','O','B'); SaveHeader(uint32 type = 0, uint32 version = 0, uint32 size = 0); @@ -106,7 +106,7 @@ protected: class SavePartMem : public SavePart { public: static const uint32 kVersion = 1; - static const uint32 kID = MKID_BE('PMEM'); + static const uint32 kID = MKTAG('P','M','E','M'); SavePartMem(uint32 size); ~SavePartMem(); @@ -128,7 +128,7 @@ private: class SavePartVars : public SavePart { public: static const uint32 kVersion = 1; - static const uint32 kID = MKID_BE('VARS'); + static const uint32 kID = MKTAG('V','A','R','S'); SavePartVars(GobEngine *vm, uint32 size); ~SavePartVars(); @@ -155,7 +155,7 @@ private: class SavePartSprite : public SavePart { public: static const uint32 kVersion = 2; - static const uint32 kID = MKID_BE('SPRT'); + static const uint32 kID = MKTAG('S','P','R','T'); SavePartSprite(uint32 width, uint32 height, bool trueColor = false); ~SavePartSprite(); @@ -193,7 +193,7 @@ private: class SavePartInfo : public SavePart { public: static const uint32 kVersion = 1; - static const uint32 kID = MKID_BE('INFO'); + static const uint32 kID = MKTAG('I','N','F','O'); /** * The constructor. @@ -235,7 +235,7 @@ private: class SaveContainer { public: static const uint32 kVersion = 1; - static const uint32 kID = MKID_BE('CONT'); + static const uint32 kID = MKTAG('C','O','N','T'); /** * The constructor. diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp index 6a87af8daf..db4134ccb0 100644 --- a/engines/groovie/cursor.cpp +++ b/engines/groovie/cursor.cpp @@ -404,7 +404,7 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) : // Verify the signature uint32 tmp32 = iconsFile.readUint32BE(); uint16 tmp16 = iconsFile.readUint16LE(); - if (tmp32 != MKID_BE('icon') || tmp16 != 1) + if (tmp32 != MKTAG('i','c','o','n') || tmp16 != 1) error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16); diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 7195198a6c..24306c8bfd 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -706,7 +706,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); // First try for compressed MIDI - Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF); + Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKTAG('c','m','i','d'), fileref & 0x3FF); if (file) { // Found the resource, decompress it @@ -715,7 +715,7 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { file = tmp; } else { // Otherwise, it's uncompressed - file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); + file = _vm->_macResFork->getResource(MKTAG('M','i','d','i'), fileref & 0x3FF); if (!file) error("Groovie::Music: Couldn't find resource 0x%04X", fileref); } diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 990e55bcf2..c73792ef8e 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -87,7 +87,9 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _pathfinderFlag = 0; _mouseX = _mouseY = 0; + _nextIdleAnim = 0; _lastIdleScript = -1; + _useSceneIdleAnim = false; _currentTalkSections.STATim = 0; _currentTalkSections.TLKTim = 0; @@ -145,6 +147,11 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _menu = 0; _chatIsNote = false; memset(&_npcScriptData, 0, sizeof(_npcScriptData)); + + _setCharPalFinal = false; + _useCharPal = false; + + memset(_characterFacingCountTable, 0, sizeof(_characterFacingCountTable)); } KyraEngine_HoF::~KyraEngine_HoF() { @@ -1135,8 +1142,6 @@ void KyraEngine_HoF::restorePage0() { } void KyraEngine_HoF::updateCharPal(int unk1) { - static bool unkVar1 = false; - if (!_useCharPal) return; @@ -1152,12 +1157,12 @@ void KyraEngine_HoF::updateCharPal(int unk1) { ++src; } _screen->setScreenPalette(_screen->getPalette(0)); - unkVar1 = true; + _setCharPalFinal = true; _charPalEntry = palEntry; - } else if (unkVar1 || !unk1) { + } else if (_setCharPalFinal || !unk1) { _screen->getPalette(0).copy(_scenePal, palEntry << 4, 16, 112); _screen->setScreenPalette(_screen->getPalette(0)); - unkVar1 = false; + _setCharPalFinal = false; } } @@ -1274,15 +1279,14 @@ int KyraEngine_HoF::getCharacterWalkspeed() const { return _timer->getDelay(0); } -void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) { - static int unkTable1[] = { 0, 0 }; - static const int unkTable2[] = { 17, 0 }; - static const int unkTable3[] = { 10, 0 }; - static const int unkTable4[] = { 24, 0 }; - static const int unkTable5[] = { 19, 0 }; - static const int unkTable6[] = { 21, 0 }; - static const int unkTable7[] = { 31, 0 }; - static const int unkTable8[] = { 26, 0 }; +void KyraEngine_HoF::updateCharAnimFrame(int *table) { + static const int unkFrame1 = 17; + static const int unkFrame2 = 10; + static const int unkFrame3 = 24; + static const int unkFrame4 = 19; + static const int unkFrame5 = 21; + static const int unkFrame6 = 31; + static const int unkFrame7 = 26; Character *character = &_mainCharacter; ++character->animFrame; @@ -1297,46 +1301,46 @@ void KyraEngine_HoF::updateCharAnimFrame(int charId, int *table) { } if (!facing) { - ++unkTable1[charId]; + ++_characterFacingCountTable[0]; } else if (facing == 4) { - ++unkTable1[charId+1]; + ++_characterFacingCountTable[1]; } else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) { if (facing == 7 || facing == 1) { - if (unkTable1[charId] > 2) + if (_characterFacingCountTable[0] > 2) facing = 0; } else { - if (unkTable1[charId+1] > 2) + if (_characterFacingCountTable[1] > 2) facing = 4; } - unkTable1[charId] = 0; - unkTable1[charId+1] = 0; + _characterFacingCountTable[0] = 0; + _characterFacingCountTable[1] = 0; } if (facing == 0) { - if (character->animFrame < unkTable8[charId]) - character->animFrame = unkTable8[charId]; + if (character->animFrame < unkFrame7) + character->animFrame = unkFrame7; - if (character->animFrame > unkTable7[charId]) - character->animFrame = unkTable8[charId]; + if (character->animFrame > unkFrame6) + character->animFrame = unkFrame7; } else if (facing == 4) { - if (character->animFrame < unkTable5[charId]) - character->animFrame = unkTable5[charId]; + if (character->animFrame < unkFrame4) + character->animFrame = unkFrame4; - if (character->animFrame > unkTable4[charId]) - character->animFrame = unkTable5[charId]; + if (character->animFrame > unkFrame3) + character->animFrame = unkFrame4; } else { - if (character->animFrame > unkTable5[charId]) - character->animFrame = unkTable6[charId]; + if (character->animFrame > unkFrame4) + character->animFrame = unkFrame5; - if (character->animFrame == unkTable2[charId]) - character->animFrame = unkTable3[charId]; + if (character->animFrame == unkFrame1) + character->animFrame = unkFrame2; - if (character->animFrame > unkTable2[charId]) - character->animFrame = unkTable3[charId] + 2; + if (character->animFrame > unkFrame1) + character->animFrame = unkFrame2 + 2; } - updateCharacterAnim(charId); + updateCharacterAnim(0); } bool KyraEngine_HoF::checkCharCollision(int x, int y) { @@ -1393,12 +1397,11 @@ void KyraEngine_HoF::showIdleAnim() { if (queryGameFlag(0x159) && _flags.isTalkie) return; - static bool scriptAnimation = false; - if (!scriptAnimation && _flags.isTalkie) { - scriptAnimation = true; + if (!_useSceneIdleAnim && _flags.isTalkie) { + _useSceneIdleAnim = true; randomSceneChat(); } else { - scriptAnimation = false; + _useSceneIdleAnim = false; if (_characterShapeFile > 8) return; diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index b862a89dd0..308698484d 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -574,13 +574,16 @@ protected: // character bool _useCharPal; + bool _setCharPalFinal; int _charPalEntry; uint8 _charPalTable[16]; void updateCharPal(int unk1); void setCharPalEntry(int entry, int value); + int _characterFacingCountTable[2]; + int getCharacterWalkspeed() const; - void updateCharAnimFrame(int num, int *table); + void updateCharAnimFrame(int *table); bool checkCharCollision(int x, int y); @@ -681,6 +684,7 @@ protected: uint32 _nextIdleAnim; int _lastIdleScript; + bool _useSceneIdleAnim; void setNextIdleAnimTimer(); void showIdleAnim(); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index fee7835881..65e78448a5 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -788,7 +788,7 @@ int KyraEngine_MR::getCharacterWalkspeed() const { return _mainCharacter.walkspeed; } -void KyraEngine_MR::updateCharAnimFrame(int character, int *table) { +void KyraEngine_MR::updateCharAnimFrame(int *table) { ++_mainCharacter.animFrame; int facing = _mainCharacter.facing; diff --git a/engines/kyra/kyra_mr.h b/engines/kyra/kyra_mr.h index f5ff3772ba..912c615757 100644 --- a/engines/kyra/kyra_mr.h +++ b/engines/kyra/kyra_mr.h @@ -386,7 +386,7 @@ private: // character int getCharacterWalkspeed() const; - void updateCharAnimFrame(int character, int *table); + void updateCharAnimFrame(int *table); int8 _characterAnimTable[2]; static const uint8 _characterFrameTable[]; diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 53c57c21cd..804097c81d 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -74,6 +74,9 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi _pauseStart = 0; + _pathfinderFlag = 0; + _smoothingPath = false; + _lang = 0; Common::Language lang = Common::parseLanguage(ConfMan.get("language")); if (lang == _flags.fanLang && _flags.replacedLang != Common::UNK_LANG) @@ -236,7 +239,7 @@ int KyraEngine_v2::updateCharPos(int *table, int force) { return 0; _mainCharacter.x1 += _charAddXPosTable[_mainCharacter.facing]; _mainCharacter.y1 += _charAddYPosTable[_mainCharacter.facing]; - updateCharAnimFrame(0, table); + updateCharAnimFrame(table); _updateCharPosNextUpdate = _system->getMillis() + getCharacterWalkspeed() * _tickLength; return 1; } diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index 084b159ee2..9f0aecd78c 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -269,6 +269,7 @@ protected: // pathfinder int _movFacingTable[600]; int _pathfinderFlag; + bool _smoothingPath; int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize); @@ -340,7 +341,7 @@ protected: uint32 _updateCharPosNextUpdate; virtual int getCharacterWalkspeed() const = 0; - virtual void updateCharAnimFrame(int num, int *table) = 0; + virtual void updateCharAnimFrame(int *table) = 0; // chat int _vocHigh; diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 7003d8c38f..5928c40f92 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -898,7 +898,9 @@ void LoLEngine::startupNew() { memset(_globalScriptVars2, 0x100, 8); - static int selectIds[] = { -9, -1, -8, -5 }; + static const int selectIds[] = { -9, -1, -8, -5 }; + assert(_charSelection >= 0); + assert(_charSelection < ARRAYSIZE(selectIds)); addCharacter(selectIds[_charSelection]); gui_enableDefaultPlayfieldButtons(); diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 8372bf9ad1..9948c52001 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -102,7 +102,7 @@ protected: enum KyraResources { kLoadAll = -1, - // This list has to match orderwise (and thus value wise) the static data list of "tools/create_kyradat/create_kyradat.h"! + // This list has to match orderwise (and thus value wise) the static data list of "devtools/create_kyradat/create_kyradat.h"! k1ForestSeq = 1, k1KallakWritingSeq, k1KyrandiaLogoSeq, diff --git a/engines/kyra/resource_intern.cpp b/engines/kyra/resource_intern.cpp index f26cb8fb26..1dc084f14d 100644 --- a/engines/kyra/resource_intern.cpp +++ b/engines/kyra/resource_intern.cpp @@ -356,7 +356,7 @@ Common::Archive *ResLoaderPak::load(Common::ArchiveMemberPtr memberFile, Common: const uint32 magic = stream.readUint32BE(); - if (magic != MKID_BE('SCVM')) + if (magic != MKTAG('S','C','V','M')) error("LINKLIST file does not contain 'SCVM' header"); const uint32 links = stream.readUint32BE(); diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index cd5ef52b92..44579c3377 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -47,13 +47,13 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab header.flags = 0; header.thumbnail = 0; - if (type == MKID_BE('KYRA') || type == MKID_BE('ARYK')) { // old Kyra1 header ID + if (type == MKTAG('K','Y','R','A') || type == MKTAG('A','R','Y','K')) { // old Kyra1 header ID header.gameID = GI_KYRA1; header.oldHeader = true; - } else if (type == MKID_BE('HOFS')) { // old Kyra2 header ID + } else if (type == MKTAG('H','O','F','S')) { // old Kyra2 header ID header.gameID = GI_KYRA2; header.oldHeader = true; - } else if (type == MKID_BE('WWSV')) { + } else if (type == MKTAG('W','W','S','V')) { header.gameID = in->readByte(); } else { // try checking for original save header @@ -71,12 +71,12 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab type = in->readUint32BE(); header.version = in->readUint16LE(); - if (type == MKID_BE('MBL3') && header.version == 100) { + if (type == MKTAG('M','B','L','3') && header.version == 100) { saveOk = true; header.description = descriptionBuffer; header.gameID = GI_KYRA2; break; - } else if (type == MKID_BE('MBL4') && header.version == 102) { + } else if (type == MKTAG('M','B','L','4') && header.version == 102) { saveOk = true; header.description = descriptionBuffer; header.gameID = GI_KYRA3; @@ -94,7 +94,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab } header.version = in->readUint32BE(); - if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKID_BE('ARYK') && header.version > 3)) + if (header.version > CURRENT_SAVE_VERSION || (header.oldHeader && header.version > 8) || (type == MKTAG('A','R','Y','K') && header.version > 3)) return kRSHEInvalidVersion; // Versions prior to 9 are using a fixed length description field @@ -190,7 +190,7 @@ Common::WriteStream *KyraEngine_v1::openSaveForWriting(const char *filename, con } // Savegame version - out->writeUint32BE(MKID_BE('WWSV')); + out->writeUint32BE(MKTAG('W','W','S','V')); out->writeByte(_flags.gameID); out->writeUint32BE(CURRENT_SAVE_VERSION); out->write(saveName, strlen(saveName)+1); diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp index f0c26acd54..fdfbceb521 100644 --- a/engines/kyra/scene_v2.cpp +++ b/engines/kyra/scene_v2.cpp @@ -86,15 +86,16 @@ int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int m x &= ~3; toX &= ~3; y &= ~1; toY &= ~1; int size = KyraEngine_v1::findWay(x, y, toX, toY, moveTable, moveTableSize); - static bool usePostProcess = false; - if (size && !usePostProcess) { - usePostProcess = true; + + if (size && !_smoothingPath) { + _smoothingPath = true; int temp = pathfinderInitPositionTable(moveTable); temp = pathfinderInitPositionIndexTable(temp, x, y); pathfinderFinializePath(moveTable, temp, x, y, moveTableSize); - usePostProcess = false; + _smoothingPath = false; } - return usePostProcess ? size : getMoveTableSize(moveTable); + + return _smoothingPath ? size : getMoveTableSize(moveTable); } bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) { diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index 0343cbfeae..956bf39b5a 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -68,14 +68,14 @@ EMCInterpreter::EMCInterpreter(KyraEngine_v1 *vm) : _vm(vm), _scriptData(0), _fi bool EMCInterpreter::callback(Common::IFFChunk &chunk) { switch (chunk._type) { - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): _scriptData->text = new byte[chunk._size]; assert(_scriptData->text); if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size) error("Couldn't read TEXT chunk from file '%s'", _filename); break; - case MKID_BE('ORDR'): + case MKTAG('O','R','D','R'): _scriptData->ordr = new uint16[chunk._size >> 1]; assert(_scriptData->ordr); if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size) @@ -85,7 +85,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) { _scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]); break; - case MKID_BE('DATA'): + case MKTAG('D','A','T','A'): _scriptData->data = new uint16[chunk._size >> 1]; assert(_scriptData->data); if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size) diff --git a/engines/kyra/script.h b/engines/kyra/script.h index 68620829bb..faa80a3f21 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -84,9 +84,9 @@ public: // Both lead to some problems in our IFF parser, either reading after the end // of file or producing a "Chunk overread" error message. To work around this // we need to adjust the size field properly. - if (_formType == MKID_BE('EMC2')) + if (_formType == MKTAG('E','M','C','2')) _formChunk.size -= 8; - else if (_formType == MKID_BE('AVFS')) + else if (_formType == MKTAG('A','V','F','S')) _formChunk.size += 4; } }; diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 28f18a1f79..1e978caf15 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -115,14 +115,14 @@ TIMInterpreter::~TIMInterpreter() { bool TIMInterpreter::callback(Common::IFFChunk &chunk) { switch (chunk._type) { - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): _tim->text = new byte[chunk._size]; assert(_tim->text); if (chunk._stream->read(_tim->text, chunk._size) != chunk._size) error("Couldn't read TEXT chunk from file '%s'", _filename); break; - case MKID_BE('AVTL'): + case MKTAG('A','V','T','L'): _avtlChunkSize = chunk._size >> 1; _tim->avtl = new uint16[_avtlChunkSize]; assert(_tim->avtl); diff --git a/engines/kyra/vqa.cpp b/engines/kyra/vqa.cpp index 382ec2429d..b3371793de 100644 --- a/engines/kyra/vqa.cpp +++ b/engines/kyra/vqa.cpp @@ -204,7 +204,7 @@ bool VQAMovie::open(const char *filename) { if (!_file) return false; - if (_file->readUint32BE() != MKID_BE('FORM')) { + if (_file->readUint32BE() != MKTAG('F','O','R','M')) { warning("VQAMovie::open: Cannot find `FORM' tag"); return false; } @@ -212,7 +212,7 @@ bool VQAMovie::open(const char *filename) { // For now, we ignore the size of the FORM chunk. _file->readUint32BE(); - if (_file->readUint32BE() != MKID_BE('WVQA')) { + if (_file->readUint32BE() != MKTAG('W','V','Q','A')) { warning("WQAMovie::open: Cannot find `WVQA' tag"); return false; } @@ -228,7 +228,7 @@ bool VQAMovie::open(const char *filename) { uint32 size = _file->readUint32BE(); switch (tag) { - case MKID_BE('VQHD'): // VQA header + case MKTAG('V','Q','H','D'): // VQA header _header.version = _file->readUint16LE(); _header.flags = _file->readUint16LE(); _header.numFrames = _file->readUint16LE(); @@ -304,7 +304,7 @@ bool VQAMovie::open(const char *filename) { foundHeader = true; break; - case MKID_BE('FINF'): // Frame info + case MKTAG('F','I','N','F'): // Frame info if (!foundHeader) { warning("VQAMovie::open: Found `FINF' before `VQHD'"); return false; @@ -343,7 +343,7 @@ bool VQAMovie::open(const char *filename) { if (_file->eos()) break; - if (scanTag == MKID_BE('VQFR')) { + if (scanTag == MKTAG('V','Q','F','R')) { _frameInfo[0] = (_file->pos() - 8) | 0x80000000; break; } @@ -421,7 +421,7 @@ void VQAMovie::displayFrame(uint frameNum) { int32 end; switch (tag) { - case MKID_BE('SND0'): // Uncompressed sound + case MKTAG('S','N','D','0'): // Uncompressed sound foundSound = true; inbuf = (byte *)malloc(size); _file->read(inbuf, size); @@ -429,7 +429,7 @@ void VQAMovie::displayFrame(uint frameNum) { _stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); break; - case MKID_BE('SND1'): // Compressed sound, almost like AUD + case MKTAG('S','N','D','1'): // Compressed sound, almost like AUD foundSound = true; outsize = _file->readUint16LE(); insize = _file->readUint16LE(); @@ -449,13 +449,13 @@ void VQAMovie::displayFrame(uint frameNum) { } break; - case MKID_BE('SND2'): // Compressed sound + case MKTAG('S','N','D','2'): // Compressed sound foundSound = true; warning("VQAMovie::displayFrame: `SND2' is not implemented"); _file->seek(size, SEEK_CUR); break; - case MKID_BE('VQFR'): + case MKTAG('V','Q','F','R'): foundFrame = true; end = _file->pos() + size - 8; @@ -464,49 +464,49 @@ void VQAMovie::displayFrame(uint frameNum) { size = _file->readUint32BE(); switch (tag) { - case MKID_BE('CBF0'): // Full codebook + case MKTAG('C','B','F','0'): // Full codebook _file->read(_codeBook, size); break; - case MKID_BE('CBFZ'): // Full codebook + case MKTAG('C','B','F','Z'): // Full codebook inbuf = (byte *)allocBuffer(0, size); _file->read(inbuf, size); Screen::decodeFrame4(inbuf, _codeBook, _codeBookSize); break; - case MKID_BE('CBP0'): // Partial codebook + case MKTAG('C','B','P','0'): // Partial codebook _compressedCodeBook = false; _file->read(_partialCodeBook + _partialCodeBookSize, size); _partialCodeBookSize += size; _numPartialCodeBooks++; break; - case MKID_BE('CBPZ'): // Partial codebook + case MKTAG('C','B','P','Z'): // Partial codebook _compressedCodeBook = true; _file->read(_partialCodeBook + _partialCodeBookSize, size); _partialCodeBookSize += size; _numPartialCodeBooks++; break; - case MKID_BE('CPL0'): // Palette + case MKTAG('C','P','L','0'): // Palette assert(size <= 3 * 256); _file->read(_screen->getPalette(0).getData(), size); break; - case MKID_BE('CPLZ'): // Palette + case MKTAG('C','P','L','Z'): // Palette inbuf = (byte *)allocBuffer(0, size); _file->read(inbuf, size); Screen::decodeFrame4(inbuf, _screen->getPalette(0).getData(), 768); break; - case MKID_BE('VPT0'): // Frame data + case MKTAG('V','P','T','0'): // Frame data assert(size / 2 <= _numVectorPointers); for (i = 0; i < size / 2; i++) _vectorPointers[i] = _file->readUint16LE(); break; - case MKID_BE('VPTZ'): // Frame data + case MKTAG('V','P','T','Z'): // Frame data inbuf = (byte *)allocBuffer(0, size); outbuf = (byte *)allocBuffer(1, 2 * _numVectorPointers); @@ -613,13 +613,13 @@ void VQAMovie::play() { } switch (tag) { - case MKID_BE('SND0'): // Uncompressed sound + case MKTAG('S','N','D','0'): // Uncompressed sound inbuf = (byte *)malloc(size); _file->read(inbuf, size); _stream->queueBuffer(inbuf, size, DisposeAfterUse::YES, Audio::FLAG_UNSIGNED); break; - case MKID_BE('SND1'): // Compressed sound + case MKTAG('S','N','D','1'): // Compressed sound outsize = _file->readUint16LE(); insize = _file->readUint16LE(); @@ -636,12 +636,12 @@ void VQAMovie::play() { } break; - case MKID_BE('SND2'): // Compressed sound + case MKTAG('S','N','D','2'): // Compressed sound warning("VQAMovie::play: `SND2' is not implemented"); _file->seek(size, SEEK_CUR); break; - case MKID_BE('CMDS'): // Unused tag, always empty in kyra3 + case MKTAG('C','M','D','S'): // Unused tag, always empty in kyra3 _file->seek(size, SEEK_CUR); break; diff --git a/engines/m4/assets.h b/engines/m4/assets.h index 3ae7fb2e22..940646b5f2 100644 --- a/engines/m4/assets.h +++ b/engines/m4/assets.h @@ -33,16 +33,16 @@ namespace M4 { // Sequence chunks -#define CHUNK_SCEN MKID_BE('SCEN') -#define CHUNK_MACH MKID_BE('MACH') -#define CHUNK_SEQU MKID_BE('SEQU') -#define CHUNK_DATA MKID_BE('DATA') -#define CHUNK_CELS MKID_BE('CELS') +#define CHUNK_SCEN MKTAG('S','C','E','N') +#define CHUNK_MACH MKTAG('M','A','C','H') +#define CHUNK_SEQU MKTAG('S','E','Q','U') +#define CHUNK_DATA MKTAG('D','A','T','A') +#define CHUNK_CELS MKTAG('C','E','L','S') // Sprite chunks -#define HEAD_M4SS MKID_BE('M4SS') //'M4SS' -#define CELS__PAL MKID_BE(' PAL') //' PAL' -#define CELS___SS MKID_BE(' SS') //' SS' +#define HEAD_M4SS MKTAG('M','4','S','S') //'M4SS' +#define CELS__PAL MKTAG(' ','P','A','L') //' PAL' +#define CELS___SS MKTAG(' ',' ','S','S') //' SS' #define SPRITE_SET_CHAR_INFO 4 diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp index 70c30d28f2..2d1b8e7e4f 100644 --- a/engines/m4/converse.cpp +++ b/engines/m4/converse.cpp @@ -45,35 +45,35 @@ namespace M4 { // Conversation chunks // Header -#define HEAD_CONV MKID_BE('CONV') // conversation -#define CHUNK_DECL MKID_BE('DECL') // declaration -#define CHUNK_NODE MKID_BE('NODE') // node -#define CHUNK_LNOD MKID_BE('LNOD') // linear node -#define CHUNK_ETRY MKID_BE('ETRY') // entry -#define CHUNK_TEXT MKID_BE('TEXT') // text -#define CHUNK_MESG MKID_BE('MESG') // message +#define HEAD_CONV MKTAG('C','O','N','V') // conversation +#define CHUNK_DECL MKTAG('D','E','C','L') // declaration +#define CHUNK_NODE MKTAG('N','O','D','E') // node +#define CHUNK_LNOD MKTAG('L','N','O','D') // linear node +#define CHUNK_ETRY MKTAG('E','T','R','Y') // entry +#define CHUNK_TEXT MKTAG('T','E','X','T') // text +#define CHUNK_MESG MKTAG('M','E','S','G') // message // Conversation chunks - entry related (unconditional) -#define CHUNK_RPLY MKID_BE('RPLY') // reply -#define CHUNK_HIDE MKID_BE('HIDE') // hide entry -#define CHUNK_UHID MKID_BE('UHID') // unhide entry -#define CHUNK_DSTR MKID_BE('DSTR') // destroy entry +#define CHUNK_RPLY MKTAG('R','P','L','Y') // reply +#define CHUNK_HIDE MKTAG('H','I','D','E') // hide entry +#define CHUNK_UHID MKTAG('U','H','I','D') // unhide entry +#define CHUNK_DSTR MKTAG('D','S','T','R') // destroy entry // Conversation chunks - entry related (conditional) -#define CHUNK_CRPL MKID_BE('CRPL') // reply -#define CHUNK_CHDE MKID_BE('CHDE') // hide entry -#define CHUNK_CUHD MKID_BE('CUHD') // unhide entry -#define CHUNK_CDST MKID_BE('DDTS') // destroy entry +#define CHUNK_CRPL MKTAG('C','R','P','L') // reply +#define CHUNK_CHDE MKTAG('C','H','D','E') // hide entry +#define CHUNK_CUHD MKTAG('C','U','H','D') // unhide entry +#define CHUNK_CDST MKTAG('D','D','T','S') // destroy entry // Conversation chunks - branching and logic (unconditional) -#define CHUNK_ASGN MKID_BE('ASGN') // assign -#define CHUNK_GOTO MKID_BE('GOTO') // goto chunk -#define CHUNK_EXIT MKID_BE('EXIT') // exit/return from goto +#define CHUNK_ASGN MKTAG('A','S','G','N') // assign +#define CHUNK_GOTO MKTAG('G','O','T','O') // goto chunk +#define CHUNK_EXIT MKTAG('E','X','I','T') // exit/return from goto // Conversation chunks - branching and logic (conditional) -#define CHUNK_CASN MKID_BE('CASN') // assign -#define CHUNK_CCGO MKID_BE('CCGO') // goto chunk -#define CHUNK_CEGO MKID_BE('CEGO') // exit/return from goto +#define CHUNK_CASN MKTAG('C','A','S','N') // assign +#define CHUNK_CCGO MKTAG('C','C','G','O') // goto chunk +#define CHUNK_CEGO MKTAG('C','E','G','O') // exit/return from goto // Others -#define CHUNK_FALL MKID_BE('FALL') // fallthrough -#define CHUNK_WRPL MKID_BE('WRPL') // weighted reply chunk -#define CHUNK_WPRL MKID_BE('WPRL') // weighted preply chunk +#define CHUNK_FALL MKTAG('F','A','L','L') // fallthrough +#define CHUNK_WRPL MKTAG('W','R','P','L') // weighted reply chunk +#define CHUNK_WPRL MKTAG('W','P','R','L') // weighted preply chunk ConversationView::ConversationView(MadsM4Engine *vm): View(vm, Common::Rect(0, diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp index cba32c2225..3ed419675d 100644 --- a/engines/m4/font.cpp +++ b/engines/m4/font.cpp @@ -81,7 +81,7 @@ Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) { void Font::setFontM4(const char *filename) { Common::SeekableReadStream *fontFile = _vm->res()->openFile(filename); - if (fontFile->readUint32LE() != MKID_BE('FONT')) { + if (fontFile->readUint32LE() != MKTAG('F','O','N','T')) { debugCN(kDebugGraphics, "Font::Font: FONT tag expected\n"); return; } @@ -92,7 +92,7 @@ void Font::setFontM4(const char *filename) { //debugCN(kDebugGraphics, "Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize); - if (fontFile->readUint32LE() != MKID_BE('WIDT')) { + if (fontFile->readUint32LE() != MKTAG('W','I','D','T')) { debugCN(kDebugGraphics, "Font::Font: WIDT tag expected\n"); return; } @@ -100,7 +100,7 @@ void Font::setFontM4(const char *filename) { _charWidths = new uint8[256]; fontFile->read(_charWidths, 256); - if (fontFile->readUint32LE() != MKID_BE('OFFS')) { + if (fontFile->readUint32LE() != MKTAG('O','F','F','S')) { debugCN(kDebugGraphics, "Font::Font: OFFS tag expected\n"); return; } @@ -110,7 +110,7 @@ void Font::setFontM4(const char *filename) { for (int i = 0; i < 256; i++) _charOffs[i] = fontFile->readUint16LE(); - if (fontFile->readUint32LE() != MKID_BE('PIXS')) { + if (fontFile->readUint32LE() != MKTAG('P','I','X','S')) { debugCN(kDebugGraphics, "Font::Font: PIXS tag expected\n"); return; } diff --git a/engines/made/database.cpp b/engines/made/database.cpp index 2aa378edf5..8d06aa0085 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -659,7 +659,7 @@ bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String } uint32 header = in->readUint32BE(); - if (header != MKID_BE('SGAM')) { + if (header != MKTAG('S','G','A','M')) { warning("Save game header missing"); delete in; return false; @@ -696,7 +696,7 @@ int16 GameDatabaseV3::savegame(const char *filename, const char *description, in return 6; } strncpy(desc, description, 64); - out->writeUint32BE(MKID_BE('SGAM')); + out->writeUint32BE(MKTAG('S','G','A','M')); out->writeUint32LE(size); out->writeUint16LE(version); out->write(desc, 64); @@ -715,7 +715,7 @@ int16 GameDatabaseV3::loadgame(const char *filename, int16 version) { } uint32 header = in->readUint32BE(); - if (header != MKID_BE('SGAM')) { + if (header != MKTAG('S','G','A','M')) { warning("Save game header missing"); delete in; return 1; diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 87640f2b67..e37bd87a7e 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -50,14 +50,14 @@ bool PmvPlayer::play(const char *filename) { uint32 chunkType, chunkSize, prevChunkSize = 0; readChunk(chunkType, chunkSize); // "MOVE" - if (chunkType != MKID_BE('MOVE')) { + if (chunkType != MKTAG('M','O','V','E')) { warning("Unexpected PMV video header, expected 'MOVE'"); delete _fd; return false; } readChunk(chunkType, chunkSize); // "MHED" - if (chunkType != MKID_BE('MHED')) { + if (chunkType != MKTAG('M','H','E','D')) { warning("Unexpected PMV video header, expected 'MHED'"); delete _fd; return false; @@ -111,7 +111,7 @@ bool PmvPlayer::play(const char *filename) { int32 frameTime = _vm->_system->getMillis(); readChunk(chunkType, chunkSize); - if (chunkType != MKID_BE('MFRM')) { + if (chunkType != MKTAG('M','F','R','M')) { warning("Unknown chunk type"); } diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index f8582aec40..e556e4ab38 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -57,7 +57,7 @@ PictureResource::~PictureResource() { } void PictureResource::load(byte *source, int size) { - if (READ_BE_UINT32(source) == MKID_BE('Flex')) { + if (READ_BE_UINT32(source) == MKTAG('F','l','e','x')) { loadChunked(source, size); } else { loadRaw(source, size); @@ -126,13 +126,13 @@ void PictureResource::loadChunked(byte *source, int size) { debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize); - if (chunkType == MKID_BE('Rect')) { + if (chunkType == MKTAG('R','e','c','t')) { debug(0, "Rect"); sourceS->skip(4); height = sourceS->readUint16BE(); width = sourceS->readUint16BE(); debug(0, "width = %d; height = %d", width, height); - } else if (chunkType == MKID_BE('fMap')) { + } else if (chunkType == MKTAG('f','M','a','p')) { debug(0, "fMap"); lineSize = sourceS->readUint16BE(); sourceS->skip(11); @@ -140,21 +140,21 @@ void PictureResource::loadChunked(byte *source, int size) { cmdOffs = sourceS->pos(); sourceS->skip(chunkSize - 14); debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs); - } else if (chunkType == MKID_BE('fLCo')) { + } else if (chunkType == MKTAG('f','L','C','o')) { debug(0, "fLCo"); sourceS->skip(9); pixelFlags = sourceS->readByte(); pixelOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs); - } else if (chunkType == MKID_BE('fPix')) { + } else if (chunkType == MKTAG('f','P','i','x')) { debug(0, "fPix"); sourceS->skip(9); maskFlags = sourceS->readByte(); maskOffs = sourceS->pos(); sourceS->skip(chunkSize - 10); debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs); - } else if (chunkType == MKID_BE('fGCo')) { + } else if (chunkType == MKTAG('f','G','C','o')) { debug(0, "fGCo"); _hasPalette = true; _paletteColorCount = chunkSize / 3; diff --git a/engines/made/resource.h b/engines/made/resource.h index 5d5664b4c7..ade6a23029 100644 --- a/engines/made/resource.h +++ b/engines/made/resource.h @@ -49,16 +49,16 @@ const int kMaxResourceCacheSize = 400 * 1024; enum ResourceType { - kResARCH = MKID_BE('ARCH'), - kResFREE = MKID_BE('FREE'), - kResOMNI = MKID_BE('OMNI'), - kResFLEX = MKID_BE('FLEX'), - kResSNDS = MKID_BE('SNDS'), - kResANIM = MKID_BE('ANIM'), - kResMENU = MKID_BE('MENU'), - kResFONT = MKID_BE('FONT'), - kResXMID = MKID_BE('XMID'), - kResMIDI = MKID_BE('MIDI') + kResARCH = MKTAG('A','R','C','H'), + kResFREE = MKTAG('F','R','E','E'), + kResOMNI = MKTAG('O','M','N','I'), + kResFLEX = MKTAG('F','L','E','X'), + kResSNDS = MKTAG('S','N','D','S'), + kResANIM = MKTAG('A','N','I','M'), + kResMENU = MKTAG('M','E','N','U'), + kResFONT = MKTAG('F','O','N','T'), + kResXMID = MKTAG('X','M','I','D'), + kResMIDI = MKTAG('M','I','D','I') }; struct ResourceSlot; diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 6dce147513..ee67c9f23c 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -563,7 +563,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { // deriven. debugN("\n\nDumping scripts for %s\'s card %d!\n", argv[1], (uint16)atoi(argv[3])); debugN("==================================\n\n"); - Common::SeekableReadStream *cardStream = _vm->getResource(MKID_BE('CARD'), (uint16)atoi(argv[3])); + Common::SeekableReadStream *cardStream = _vm->getResource(MKTAG('C','A','R','D'), (uint16)atoi(argv[3])); cardStream->seek(4); RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false); for (uint32 i = 0; i < scriptList.size(); i++) { @@ -576,7 +576,7 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { debugN("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3])); debugN("===========================================\n\n"); - Common::SeekableReadStream *hsptStream = _vm->getResource(MKID_BE('HSPT'), (uint16)atoi(argv[3])); + Common::SeekableReadStream *hsptStream = _vm->getResource(MKTAG('H','S','P','T'), (uint16)atoi(argv[3])); uint16 hotspotCount = hsptStream->readUint16BE(); diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index 9233a8497c..b4969f990a 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -221,7 +221,7 @@ void MacCursorManager::setCursor(uint16 id) { } // Try a color cursor first - Common::SeekableReadStream *stream = _resFork->getResource(MKID_BE('crsr'), id); + Common::SeekableReadStream *stream = _resFork->getResource(MKTAG('c','r','s','r'), id); if (stream) { byte *cursor, *palette; @@ -239,7 +239,7 @@ void MacCursorManager::setCursor(uint16 id) { } // Fall back to b&w cursors - stream = _resFork->getResource(MKID_BE('CURS'), id); + stream = _resFork->getResource(MKTAG('C','U','R','S'), id); if (stream) { setMacXorCursor(stream); diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index c31df3010d..cad24b55f1 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -121,6 +121,7 @@ static const PlainGameDescriptor mohawkGames[] = { {"csworld", "Where in the World is Carmen Sandiego?"}, {"csamtrak", "Where in America is Carmen Sandiego? (The Great Amtrak Train Adventure)"}, {"carmentq", "Carmen Sandiego's ThinkQuick Challenge"}, + {"carmentqc", "Carmen Sandiego's ThinkQuick Challenge Custom Question Creator"}, {"maggiesfa", "Maggie's Farmyard Adventure"}, {"jamesmath", "James Discovers/Explores Math"}, {"treehouse", "The Treehouse"}, diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index 27ee3401f5..a8f9ee557b 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -610,6 +610,21 @@ static const MohawkGameDescription gameDescriptions[] = { { { + "carmentqc", + "", + AD_ENTRY1("Outline.txt", "6a281eefe72987afb0f8fb6cf84553f5"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV5, + 0, + 0 + }, + + { + { "maggiesfa", "", AD_ENTRY1("Outline", "b7dc6e65fa9e80784a5bb8b557aa37c4"), @@ -869,6 +884,22 @@ static const MohawkGameDescription gameDescriptions[] = { "TORTOISE.EXE" }, + // From Scarlatti in bug #3275626 + { + { + "tortoise", + "Demo v1.1", + AD_ENTRY1("TORTOISE.512", "14400a3358a3f1148e4d4b47bc3523c9"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "TORTOISE.EXE" + }, + { { "tortoise", @@ -929,6 +960,22 @@ static const MohawkGameDescription gameDescriptions[] = { "ARTHUR.EXE" }, + // From Scarlatti in bug #3275626 + { + { + "arthur", + "Demo v1.1", + AD_ENTRY1("ARTHUR.512", "dabdd466dea26ab5ecb9415cf73f8601"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "ARTHUR.EXE" + }, + { { "arthur", @@ -1006,6 +1053,22 @@ static const MohawkGameDescription gameDescriptions[] = { "GRANDMA.EXE" }, + // From Scarlatti in bug #3275626 + { + { + "grandma", + "Demo v1.1", + AD_ENTRY1("GRANDMA.512", "4f616647245bb4e37e6dab7557dad304"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "GRANDMA.EXE" + }, + { { "grandma", @@ -1036,6 +1099,23 @@ static const MohawkGameDescription gameDescriptions[] = { "Living Books Player" }, + // Ruff's Bone 1.0 + // From pacifist + { + { + "ruff", + "", + AD_ENTRY1("RUFF.512", "3dbda0de6f47a64d1714d89f5a5f60d1"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + "RUFF.EXE" + }, + { { "ruff", @@ -1051,36 +1131,35 @@ static const MohawkGameDescription gameDescriptions[] = { "RUFF.EXE" }, + // From Scarlatti in bug #3275626 { { "ruff", "Demo", - AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), + AD_ENTRY1("RUFF.512", "07b9d013e2400d61ca268892a76de4d2"), Common::EN_ANY, - Common::kPlatformMacintosh, + Common::kPlatformWindows, ADGF_DEMO, Common::GUIO_NONE }, GType_LIVINGBOOKSV1, GF_DEMO, - "Living Books Player" + "RUFF.EXE" }, - // Ruff's Bone 1.0 - // From pacifist { { "ruff", - "", - AD_ENTRY1("RUFF.512", "3dbda0de6f47a64d1714d89f5a5f60d1"), + "Demo", + AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, + Common::kPlatformMacintosh, + ADGF_DEMO, Common::GUIO_NONE }, GType_LIVINGBOOKSV1, - 0, - "RUFF.EXE" + GF_DEMO, + "Living Books Player" }, { @@ -1113,6 +1192,22 @@ static const MohawkGameDescription gameDescriptions[] = { "NEWKID.EXE" }, + // From Scarlatti in bug #3275626 + { + { + "newkid", + "Demo v1.1", + AD_ENTRY1("NEWKID.512", "de576f3481f62e84eda03b4d2307492b"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "NEWKID.EXE" + }, + { { "newkid", @@ -1174,6 +1269,22 @@ static const MohawkGameDescription gameDescriptions[] = { "BIRTHDAY.EXE" }, + // From Scarlatti in bug #3275626 + { + { + "arthurbday", + "Demo", + AD_ENTRY1("BIRTHDAY.512", "2946b1e06f59ea607b8b29dfc6ba8976"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "BIRTHDAY.EXE" + }, + { { "arthurbday", @@ -1219,6 +1330,22 @@ static const MohawkGameDescription gameDescriptions[] = { "Little Monster at School" }, + // From Scarlatti in bug #3275626 + { + { + "lilmonster", + "Demo", + AD_ENTRY1("MONSTER.512", "029e57f1fc8dd1f93f6623a1841f0df2"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + "MONSTER.EXE" + }, + { { "catinthehat", diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp index 542cc9645d..7f6c3cc43a 100644 --- a/engines/mohawk/livingbooks.cpp +++ b/engines/mohawk/livingbooks.cpp @@ -72,6 +72,48 @@ Common::Rect MohawkEngine_LivingBooks::readRect(Common::SeekableSubReadStreamEnd return rect; } +LBPage::LBPage(MohawkEngine_LivingBooks *vm) : _vm(vm) { + _code = NULL; + _mhk = NULL; + + _baseId = 0; + _cascade = false; +} + +void LBPage::open(MohawkArchive *mhk, uint16 baseId) { + _mhk = mhk; + _baseId = baseId; + + _vm->addArchive(_mhk); + if (_vm->hasResource(ID_BCOD, baseId)) + _code = new LBCode(_vm, baseId); + + loadBITL(baseId); + for (uint i = 0; i < _items.size(); i++) + _vm->addItem(_items[i]); + + for (uint32 i = 0; i < _items.size(); i++) + _items[i]->init(); +} + +void LBPage::itemDestroyed(LBItem *item) { + for (uint i = 0; i < _items.size(); i++) + if (item == _items[i]) { + _items.remove_at(i); + return; + } + error("itemDestroyed didn't find item"); +} + +LBPage::~LBPage() { + delete _code; + _vm->removeItems(_items); + for (uint i = 0; i < _items.size(); i++) + delete _items[i]; + _vm->removeArchive(_mhk); + delete _mhk; +} + MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) { _needsUpdate = false; _needsRedraw = false; @@ -82,11 +124,11 @@ MohawkEngine_LivingBooks::MohawkEngine_LivingBooks(OSystem *syst, const MohawkGa _alreadyShowedIntro = false; - _code = NULL; - _rnd = new Common::RandomSource(); g_eventRec.registerRandomSource(*_rnd, "livingbooks"); + _page = NULL; + const Common::FSNode gameDataDir(ConfMan.get("path")); // Rugrats SearchMan.addSubDirectoryMatching(gameDataDir, "program"); @@ -281,16 +323,9 @@ void MohawkEngine_LivingBooks::destroyPage() { _eventQueue.clear(); - delete _code; - _code = NULL; - - for (uint32 i = 0; i < _items.size(); i++) - delete _items[i]; - _items.clear(); - - for (uint32 i = 0; i < _mhk.size(); i++) - delete _mhk[i]; - _mhk.clear(); + delete _page; + assert(_items.empty()); + _page = NULL; _notifyEvents.clear(); @@ -342,7 +377,8 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) { MohawkArchive *pageArchive = createMohawkArchive(); if (!filename.empty() && pageArchive->open(filename)) { - _mhk.push_back(pageArchive); + _page = new LBPage(this); + _page->open(pageArchive, 1000); } else { delete pageArchive; debug(2, "Could not find page %d.%d for '%s'", page, subpage, name.c_str()); @@ -360,7 +396,7 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) { } } - debug(1, "Stack Version: %d", getResourceVersion()); + debug(1, "Page Version: %d", _page->getResourceVersion()); _curMode = mode; _curPage = page; @@ -370,13 +406,6 @@ bool MohawkEngine_LivingBooks::loadPage(LBMode mode, uint page, uint subpage) { _gfx->setPalette(1000); - if (hasResource(ID_BCOD, 1000)) - _code = new LBCode(this); - - loadBITL(1000); - for (uint32 i = 0; i < _items.size(); i++) - _items[i]->init(); - _phase = 0; _introDone = false; @@ -523,6 +552,7 @@ void MohawkEngine_LivingBooks::updatePage() { _items.remove_at(i); i--; delete delayedEvent.item; + _page->itemDestroyed(delayedEvent.item); if (_focus == delayedEvent.item) _focus = NULL; break; @@ -550,6 +580,39 @@ void MohawkEngine_LivingBooks::updatePage() { } } +void MohawkEngine_LivingBooks::addArchive(MohawkArchive *archive) { + _mhk.push_back(archive); +} + +void MohawkEngine_LivingBooks::removeArchive(MohawkArchive *archive) { + for (uint i = 0; i < _mhk.size(); i++) { + if (archive != _mhk[i]) + continue; + _mhk.remove_at(i); + return; + } + + error("removeArchive didn't find archive"); +} + +void MohawkEngine_LivingBooks::addItem(LBItem *item) { + _items.push_back(item); +} + +void MohawkEngine_LivingBooks::removeItems(const Common::Array<LBItem *> &items) { + for (uint i = 0; i < items.size(); i++) { + bool found = false; + for (uint16 j = 0; j < _items.size(); j++) { + if (items[i] != _items[j]) + continue; + found = true; + _items.remove_at(j); + break; + } + assert(found); + } +} + LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) { for (uint16 i = 0; i < _items.size(); i++) if (_items[i]->getId() == id) @@ -558,6 +621,14 @@ LBItem *MohawkEngine_LivingBooks::getItemById(uint16 id) { return NULL; } +LBItem *MohawkEngine_LivingBooks::getItemByName(Common::String name) { + for (uint16 i = 0; i < _items.size(); i++) + if (_items[i]->getName() == name) + return _items[i]; + + return NULL; +} + void MohawkEngine_LivingBooks::setFocus(LBItem *focus) { _focus = focus; } @@ -624,9 +695,9 @@ void MohawkEngine_LivingBooks::lockSound(LBItem *owner, bool lock) { } } -// Only 1 VSRN resource per stack, Id 1000 -uint16 MohawkEngine_LivingBooks::getResourceVersion() { - Common::SeekableReadStream *versionStream = getResource(ID_VRSN, 1000); +// Only 1 VSRN resource per page +uint16 LBPage::getResourceVersion() { + Common::SeekableReadStream *versionStream = _vm->getResource(ID_VRSN, _baseId); // FIXME: some V2 games have very strange version entries if (versionStream->size() != 2) @@ -638,43 +709,43 @@ uint16 MohawkEngine_LivingBooks::getResourceVersion() { return version; } -void MohawkEngine_LivingBooks::loadBITL(uint16 resourceId) { - Common::SeekableSubReadStreamEndian *bitlStream = wrapStreamEndian(ID_BITL, resourceId); +void LBPage::loadBITL(uint16 resourceId) { + Common::SeekableSubReadStreamEndian *bitlStream = _vm->wrapStreamEndian(ID_BITL, resourceId); while (true) { - Common::Rect rect = readRect(bitlStream); + Common::Rect rect = _vm->readRect(bitlStream); uint16 type = bitlStream->readUint16(); LBItem *res; switch (type) { case kLBPictureItem: - res = new LBPictureItem(this, rect); + res = new LBPictureItem(_vm, this, rect); break; case kLBAnimationItem: - res = new LBAnimationItem(this, rect); + res = new LBAnimationItem(_vm, this, rect); break; case kLBPaletteItem: - res = new LBPaletteItem(this, rect); + res = new LBPaletteItem(_vm, this, rect); break; case kLBGroupItem: - res = new LBGroupItem(this, rect); + res = new LBGroupItem(_vm, this, rect); break; case kLBSoundItem: - res = new LBSoundItem(this, rect); + res = new LBSoundItem(_vm, this, rect); break; case kLBLiveTextItem: - res = new LBLiveTextItem(this, rect); + res = new LBLiveTextItem(_vm, this, rect); break; case kLBMovieItem: - res = new LBMovieItem(this, rect); + res = new LBMovieItem(_vm, this, rect); break; case kLBMiniGameItem: - res = new LBMiniGameItem(this, rect); + res = new LBMiniGameItem(_vm, this, rect); break; default: warning("Unknown item type %04x", type); case 3: // often used for buttons - res = new LBItem(this, rect); + res = new LBItem(_vm, this, rect); break; } @@ -1802,7 +1873,7 @@ LBScriptEntry::~LBScriptEntry() { delete subentries[i]; } -LBItem::LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : _vm(vm), _rect(rect) { +LBItem::LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : _vm(vm), _page(page), _rect(rect) { _phase = 0; _loopMode = 0; @@ -1926,13 +1997,14 @@ LBScriptEntry *LBItem::parseScriptEntry(uint16 type, uint16 &size, Common::Seeka debug(4, "%d targets with targeting type %04x", count, targetingType); // FIXME: targeting by name + uint oldAlign = size % 2; for (uint i = 0; i < count; i++) { Common::String target = _vm->readString(stream); warning("ignoring target '%s' in script entry", target.c_str()); size -= target.size() + 1; } - if (size % 2 == 1) { + if (size % 2 != oldAlign) { stream->skip(1); size--; } @@ -2190,9 +2262,9 @@ void LBItem::readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEnd { assert(size == 4); uint offset = stream->readUint32(); - if (!_vm->_code) + if (!_page->_code) error("no BCOD?"); - _vm->_code->runCode(this, offset); + _page->_code->runCode(this, offset); } break; @@ -2659,9 +2731,9 @@ int LBItem::runScriptEntry(LBScriptEntry *entry) { break; case kLBOpSendExpression: - if (!_vm->_code) + if (!_page->_code) error("no BCOD?"); - _vm->_code->runCode(this, entry->offset); + _page->_code->runCode(this, entry->offset); break; case kLBOpRunSubentries: @@ -2694,10 +2766,10 @@ int LBItem::runScriptEntry(LBScriptEntry *entry) { case kLBOpJumpUnlessExpression: case kLBOpBreakExpression: case kLBOpJumpToExpression: - if (!_vm->_code) + if (!_page->_code) error("no BCOD?"); { - LBValue r = _vm->_code->runCode(this, entry->offset); + LBValue r = _page->_code->runCode(this, entry->offset); // FIXME return r.integer; } @@ -2973,7 +3045,7 @@ bool LBItem::checkCondition(const Common::String &condition) { return false; // unreachable } -LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBSoundItem::LBSoundItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBSoundItem"); _running = false; } @@ -3019,7 +3091,7 @@ void LBSoundItem::stop() { LBItem::stop(); } -LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBGroupItem::LBGroupItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBGroupItem"); _starting = false; } @@ -3134,7 +3206,7 @@ void LBGroupItem::stop() { } } -LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBPaletteItem::LBPaletteItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBPaletteItem"); _fadeInStart = 0; @@ -3219,7 +3291,7 @@ void LBPaletteItem::update() { LBItem::update(); } -LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBLiveTextItem::LBLiveTextItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { _currentPhrase = 0xFFFF; _currentWord = 0xFFFF; debug(3, "new LBLiveTextItem"); @@ -3466,7 +3538,7 @@ void LBLiveTextItem::notify(uint16 data, uint16 from) { LBItem::notify(data, from); } -LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBPictureItem::LBPictureItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBPictureItem"); } @@ -3509,7 +3581,7 @@ void LBPictureItem::draw() { _vm->_gfx->copyAnimImageToScreen(_resourceId, _rect.left, _rect.top); } -LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBAnimationItem::LBAnimationItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { _anim = NULL; _running = false; debug(3, "new LBAnimationItem"); @@ -3608,7 +3680,7 @@ void LBAnimationItem::draw() { _anim->draw(); } -LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBMovieItem::LBMovieItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBMovieItem"); } @@ -3637,7 +3709,7 @@ bool LBMovieItem::togglePlaying(bool playing, bool restart) { return LBItem::togglePlaying(playing, restart); } -LBMiniGameItem::LBMiniGameItem(MohawkEngine_LivingBooks *vm, Common::Rect rect) : LBItem(vm, rect) { +LBMiniGameItem::LBMiniGameItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect) : LBItem(vm, page, rect) { debug(3, "new LBMiniGameItem"); } diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h index 3eff039385..cd3b206d57 100644 --- a/engines/mohawk/livingbooks.h +++ b/engines/mohawk/livingbooks.h @@ -237,6 +237,7 @@ enum { }; class MohawkEngine_LivingBooks; +class LBPage; class LBGraphics; class LBAnimation; @@ -357,7 +358,7 @@ class LBItem { friend class LBCode; public: - LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect); + LBItem(MohawkEngine_LivingBooks *vm, LBPage *page, Common::Rect rect); virtual ~LBItem(); void readFrom(Common::SeekableSubReadStreamEndian *stream); @@ -385,11 +386,14 @@ public: virtual void notify(uint16 data, uint16 from); // 0x1A uint16 getId() { return _itemId; } + const Common::String &getName() { return _desc; } + const Common::Rect &getRect() { return _rect; } uint16 getSoundPriority() { return _soundMode; } bool isAmbient() { return _isAmbient; } protected: MohawkEngine_LivingBooks *_vm; + LBPage *_page; void setNextTime(uint16 min, uint16 max); void setNextTime(uint16 min, uint16 max, uint32 start); @@ -425,7 +429,7 @@ protected: class LBSoundItem : public LBItem { public: - LBSoundItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBSoundItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); ~LBSoundItem(); void update(); @@ -443,7 +447,7 @@ struct GroupEntry { class LBGroupItem : public LBItem { public: - LBGroupItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBGroupItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream); @@ -467,7 +471,7 @@ protected: class LBPaletteItem : public LBItem { public: - LBPaletteItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBPaletteItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); ~LBPaletteItem(); void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream); @@ -494,7 +498,7 @@ struct LiveTextPhrase { class LBLiveTextItem : public LBItem { public: - LBLiveTextItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBLiveTextItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream); @@ -523,7 +527,7 @@ protected: class LBPictureItem : public LBItem { public: - LBPictureItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBPictureItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); void readData(uint16 type, uint16 size, Common::SeekableSubReadStreamEndian *stream); @@ -534,7 +538,7 @@ public: class LBAnimationItem : public LBItem { public: - LBAnimationItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBAnimationItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); ~LBAnimationItem(); void setEnabled(bool enabled); @@ -555,7 +559,7 @@ protected: class LBMovieItem : public LBItem { public: - LBMovieItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBMovieItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); ~LBMovieItem(); void update(); @@ -564,14 +568,14 @@ public: class LBMiniGameItem : public LBItem { public: - LBMiniGameItem(MohawkEngine_LivingBooks *_vm, Common::Rect rect); + LBMiniGameItem(MohawkEngine_LivingBooks *_vm, LBPage *page, Common::Rect rect); ~LBMiniGameItem(); bool togglePlaying(bool playing, bool restart); }; struct NotifyEvent { - NotifyEvent(uint t, uint p) : type(t), param(p) { } + NotifyEvent(uint t, uint p) : type(t), param(p), newUnknown(0), newMode(0), newPage(0), newSubpage(0) { } uint type; uint param; @@ -594,6 +598,30 @@ struct DelayedEvent { DelayedEventType type; }; +class LBPage { +public: + LBPage(MohawkEngine_LivingBooks *vm); + ~LBPage(); + + void open(MohawkArchive *mhk, uint16 baseId); + uint16 getResourceVersion(); + + void itemDestroyed(LBItem *item); + + LBCode *_code; + +protected: + MohawkEngine_LivingBooks *_vm; + + MohawkArchive *_mhk; + Common::Array<LBItem *> _items; + + uint16 _baseId; + bool _cascade; + + void loadBITL(uint16 resourceId); +}; + class MohawkEngine_LivingBooks : public MohawkEngine { protected: Common::Error run(); @@ -614,7 +642,13 @@ public: Common::Rect readRect(Common::SeekableSubReadStreamEndian *stream); GUI::Debugger *getDebugger() { return _console; } + void addArchive(MohawkArchive *archive); + void removeArchive(MohawkArchive *Archive); + void addItem(LBItem *item); + void removeItems(const Common::Array<LBItem *> &items); + LBItem *getItemById(uint16 id); + LBItem *getItemByName(Common::String name); void setFocus(LBItem *focus); void setEnableForAll(bool enable, LBItem *except = 0); @@ -633,11 +667,13 @@ public: void prevPage(); void nextPage(); - LBCode *_code; - // TODO: make private Common::HashMap<Common::String, LBValue> _variables; + // helper functions, also used by LBProxyItem + Common::String getFileNameFromConfig(const Common::String §ion, const Common::String &key, Common::String &leftover); + MohawkArchive *createMohawkArchive() const; + private: LivingBooksConsole *_console; Common::ConfigFile _bookInfoFile; @@ -651,6 +687,7 @@ private: LBMode _curMode; uint16 _curPage, _curSubPage; uint16 _phase; + LBPage *_page; Common::Array<LBItem *> _items; Common::Queue<DelayedEvent> _eventQueue; LBItem *_focus; @@ -663,8 +700,6 @@ private: uint16 _soundLockOwner; uint16 _maxSoundPriority; - uint16 getResourceVersion(); - void loadBITL(uint16 resourceId); void loadSHP(uint16 resourceId); bool tryDefaultPage(); @@ -698,10 +733,6 @@ private: Common::String getStringFromConfig(const Common::String §ion, const Common::String &key); Common::String getStringFromConfig(const Common::String §ion, const Common::String &key, Common::String &leftover); int getIntFromConfig(const Common::String §ion, const Common::String &key); - Common::String getFileNameFromConfig(const Common::String §ion, const Common::String &key, Common::String &leftover); - - // Platform/Version functions - MohawkArchive *createMohawkArchive() const; }; } // End of namespace Mohawk diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp index c0718d941a..84f69af2ac 100644 --- a/engines/mohawk/livingbooks_code.cpp +++ b/engines/mohawk/livingbooks_code.cpp @@ -71,6 +71,19 @@ bool LBValue::isZero() const { return toInt() == 0; // FIXME } +Common::String LBValue::toString() const { + switch (type) { + case kLBValueString: + return string; + case kLBValueInteger: + return Common::String::format("%d", integer); + case kLBValueReal: + return Common::String::format("%f", real); + default: + return string; // FIXME + } +} + int LBValue::toInt() const { return integer; // FIXME } @@ -79,8 +92,38 @@ double LBValue::toDouble() const { return real; // FIXME } -LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) { - Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, 1000); +Common::Point LBValue::toPoint() const { + switch (type) { + case kLBValueString: + // FIXME + return Common::Point(); + case kLBValueInteger: + return Common::Point(integer, integer); + case kLBValuePoint: + return point; + default: + error("failed to convert to point"); + } +} + +Common::Rect LBValue::toRect() const { + switch (type) { + case kLBValueString: + // FIXME + return Common::Rect(); + case kLBValueInteger: + return Common::Rect(integer, integer, integer, integer); + case kLBValueRect: + return rect; + case kLBValueItemPtr: + return item->getRect(); + default: + error("failed to convert to rect"); + } +} + +LBCode::LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId) : _vm(vm) { + Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, baseId); uint32 totalSize = bcodStream->readUint32(); if (totalSize != (uint32)bcodStream->size()) @@ -206,7 +249,7 @@ LBValue LBCode::runCode(byte terminator) { if (_currToken == terminator || _currToken == kTokenEndOfFile) break; if (_currToken != kTokenEndOfStatement && _currToken != kTokenEndOfFile) - error("missing EOS"); + error("missing EOS (got %02x)", _currToken); debugN("\n"); } @@ -214,8 +257,29 @@ LBValue LBCode::runCode(byte terminator) { } void LBCode::parseStatement() { - // FIXME: logical operators parseComparisons(); + + if (_currToken != kTokenAnd && _currToken != kTokenOr) + return; + byte op = _currToken; + if (op == kTokenAnd) + debugN(" && "); + else + debugN(" || "); + + nextToken(); + parseComparisons(); + + LBValue val2 = _stack.pop(); + LBValue val1 = _stack.pop(); + bool result; + if (op == kTokenAnd) + result = !val1.isZero() && !val2.isZero(); + else + result = !val1.isZero() || !val2.isZero(); + + debugN(" [--> %s]", result ? "true" : "false"); + _stack.push(result); } void LBCode::parseComparisons() { @@ -253,7 +317,7 @@ void LBCode::parseComparisons() { error("comparison didn't get enough values"); LBValue val2 = _stack.pop(); LBValue val1 = _stack.pop(); - bool result; + bool result = false; // FIXME: should work for non-integers!! switch (comparison) { case kTokenEquals: @@ -277,17 +341,50 @@ void LBCode::parseComparisons() { } debugN(" [--> %s]", result ? "true" : "false"); - _stack.push(result ? 1 : 0); + _stack.push(result); } void LBCode::parseConcat() { parseArithmetic1(); - // FIXME: string concat + + if (_currToken != kTokenConcat) + return; + + debugN(" & "); + nextToken(); + parseArithmetic1(); + + LBValue val2 = _stack.pop(); + LBValue val1 = _stack.pop(); + Common::String result = val1.toString() + val2.toString(); + debugN(" [--> \"%s\"]", result.c_str()); + _stack.push(result); } void LBCode::parseArithmetic1() { parseArithmetic2(); - // FIXME: -/+ math operators + + if (_currToken != kTokenMinus && _currToken != kTokenPlus) + return; + + byte op = _currToken; + if (op == kTokenMinus) + debugN(" - "); + else if (op == kTokenPlus) + debugN(" + "); + + nextToken(); + parseArithmetic2(); + + LBValue val2 = _stack.pop(); + LBValue val1 = _stack.pop(); + LBValue result; + // TODO: cope with non-integers + if (op == kTokenMinus) + result = val1.toInt() - val2.toInt(); + else + result = val1.toInt() + val2.toInt(); + _stack.push(result); } void LBCode::parseArithmetic2() { @@ -310,10 +407,11 @@ void LBCode::parseMain() { Common::String varname = _currValue.string; debugN("%s", varname.c_str()); nextToken(); - if (varname == "self") { + if (varname.equalsIgnoreCase("self")) { _stack.push(LBValue(_currSource)); if (_currToken == kTokenAssign) error("attempted assignment to self"); + break; } else if (_currToken == kTokenAssign) { debugN(" = "); nextToken(); @@ -326,7 +424,16 @@ void LBCode::parseMain() { } else { _stack.push(_vm->_variables[varname]); } - // FIXME: pre/postincrement + // FIXME: pre/postincrement for non-integers + if (_currToken == kTokenPlusPlus) { + debugN("++"); + _vm->_variables[varname].integer++; + nextToken(); + } else if (_currToken == kTokenMinusMinus) { + debugN("--"); + _vm->_variables[varname].integer--; + nextToken(); + } } break; @@ -348,6 +455,17 @@ void LBCode::parseMain() { nextToken(); break; + case kTokenTrue: + debugN("TRUE"); + _stack.push(true); + nextToken(); + break; + case kTokenFalse: + debugN("FALSE"); + _stack.push(false); + nextToken(); + break; + case kTokenOpenBracket: debugN("("); nextToken(); @@ -442,6 +560,21 @@ Common::Array<LBValue> LBCode::readParams() { return params; } +Common::Rect LBCode::getRectFromParams(const Common::Array<LBValue> ¶ms) { + if (params.size() == 0) { + assert(_currSource); + return _currSource->getRect(); + } else if (params.size() == 1) { + const LBValue &val = params[0]; + LBItem *item = _vm->getItemByName(val.toString()); + if (item) + return item->getRect(); + else + return val.toRect(); + } else + error("getRectFromParams got called with weird state"); +} + struct CodeCommandInfo { const char *name; typedef void (LBCode::*CommandFunc)(const Common::Array<LBValue> ¶ms); @@ -457,16 +590,16 @@ CodeCommandInfo generalCommandInfo[NUM_GENERAL_COMMANDS] = { { "max", 0 }, { "min", 0 }, { "abs", 0 }, - { "getRect", 0 }, // also "makeRect" + { "getRect", &LBCode::cmdGetRect }, // also "makeRect" { "makePt", 0 }, // also "makePair" - { "topleft", 0 }, - { "bottomright", 0 }, + { "topLeft", &LBCode::cmdTopLeft }, + { "bottomRight", &LBCode::cmdBottomRight }, { "mousePos", 0 }, - { "top", 0 }, - { "left", 0 }, - { "bottom", 0 }, + { "top", &LBCode::cmdTop }, + { "left", &LBCode::cmdLeft }, + { "bottom", &LBCode::cmdBottom }, // 0x10 - { "right", 0 }, + { "right", &LBCode::cmdRight }, { "xpos", 0 }, { "ypos", 0 }, { "playFrom", 0 }, @@ -607,6 +740,67 @@ void LBCode::cmdUnimplemented(const Common::Array<LBValue> ¶ms) { warning("unimplemented command called"); } +void LBCode::cmdGetRect(const Common::Array<LBValue> ¶ms) { + if (params.size() < 2) { + _stack.push(getRectFromParams(params)); + } else if (params.size() == 2) { + Common::Point p1 = params[0].toPoint(); + Common::Point p2 = params[1].toPoint(); + _stack.push(Common::Rect(p1.x, p1.y, p2.x, p2.y)); + } else if (params.size() == 4) { + _stack.push(Common::Rect(params[0].toInt(), params[1].toInt(), params[2].toInt(), params[3].toInt())); + } else + error("incorrect number of parameters (%d) to getRect", params.size()); +} + +void LBCode::cmdTopLeft(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to topLeft", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(Common::Point(rect.top, rect.left)); +} + +void LBCode::cmdBottomRight(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to bottomRight", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(Common::Point(rect.bottom, rect.right)); +} + +void LBCode::cmdTop(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to top", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(rect.top); +} + +void LBCode::cmdLeft(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to left", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(rect.left); +} + +void LBCode::cmdBottom(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to bottom", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(rect.bottom); +} + +void LBCode::cmdRight(const Common::Array<LBValue> ¶ms) { + if (params.size() > 1) + error("too many parameters (%d) to right", params.size()); + + Common::Rect rect = getRectFromParams(params); + _stack.push(rect.right); +} + void LBCode::cmdSetPlayParams(const Common::Array<LBValue> ¶ms) { if (params.size() > 8) error("too many parameters (%d) to setPlayParams", params.size()); @@ -785,6 +979,16 @@ void LBCode::runNotifyCommand() { } break; + case kLBNotifyQuit: + { + debugN("quit"); + Common::Array<LBValue> params = readParams(); + if (params.size() != 0) + error("incorrect number of parameters (%d) to quit", params.size()); + _vm->addNotifyEvent(NotifyEvent(kLBNotifyQuit, 0)); + } + break; + default: error("unknown notify command %02x in code", commandType); } diff --git a/engines/mohawk/livingbooks_code.h b/engines/mohawk/livingbooks_code.h index 71174cc09e..cd9ac1004a 100644 --- a/engines/mohawk/livingbooks_code.h +++ b/engines/mohawk/livingbooks_code.h @@ -57,6 +57,14 @@ struct LBValue { type = kLBValueString; string = str; } + LBValue(const Common::Point &p) { + type = kLBValuePoint; + point = p; + } + LBValue(const Common::Rect &r) { + type = kLBValueRect; + rect = r; + } LBValue(LBItem *itm) { type = kLBValueItemPtr; item = itm; @@ -99,8 +107,11 @@ struct LBValue { bool isNumeric() const; bool isZero() const; + Common::String toString() const; int toInt() const; double toDouble() const; + Common::Point toPoint() const; + Common::Rect toRect() const; }; enum { @@ -169,7 +180,7 @@ enum { class LBCode { public: - LBCode(MohawkEngine_LivingBooks *vm); + LBCode(MohawkEngine_LivingBooks *vm, uint16 baseId); ~LBCode(); LBValue runCode(LBItem *src, uint32 offset); @@ -199,12 +210,21 @@ protected: void parseMain(); Common::Array<LBValue> readParams(); + Common::Rect getRectFromParams(const Common::Array<LBValue> ¶ms); + void runGeneralCommand(); void runItemCommand(); void runNotifyCommand(); public: void cmdUnimplemented(const Common::Array<LBValue> ¶ms); + void cmdGetRect(const Common::Array<LBValue> ¶ms); + void cmdTopLeft(const Common::Array<LBValue> ¶ms); + void cmdBottomRight(const Common::Array<LBValue> ¶ms); + void cmdTop(const Common::Array<LBValue> ¶ms); + void cmdLeft(const Common::Array<LBValue> ¶ms); + void cmdBottom(const Common::Array<LBValue> ¶ms); + void cmdRight(const Common::Array<LBValue> ¶ms); void cmdSetPlayParams(const Common::Array<LBValue> ¶ms); void cmdSetKeyEvent(const Common::Array<LBValue> ¶ms); void cmdSetHitTest(const Common::Array<LBValue> ¶ms); diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h index 18e8f80fb2..07c727951c 100644 --- a/engines/mohawk/resource.h +++ b/engines/mohawk/resource.h @@ -34,102 +34,102 @@ namespace Mohawk { // Main FourCC's -#define ID_MHWK MKID_BE('MHWK') // Main FourCC -#define ID_RSRC MKID_BE('RSRC') // Resource Directory Tag +#define ID_MHWK MKTAG('M','H','W','K') // Main FourCC +#define ID_RSRC MKTAG('R','S','R','C') // Resource Directory Tag // Myst Resource FourCC's -#define ID_CLRC MKID_BE('CLRC') // Cursor Hotspots -#define ID_EXIT MKID_BE('EXIT') // Card Exit Scripts -#define ID_HINT MKID_BE('HINT') // Cursor Hints -#define ID_INIT MKID_BE('INIT') // Card Entrance Scripts -#define ID_MSND MKID_BE('MSND') // Standard Mohawk Sound -#define ID_RLST MKID_BE('RLST') // Resource List, Specifies HotSpots -#define ID_RSFL MKID_BE('RSFL') // ??? (system.dat only) -#define ID_VIEW MKID_BE('VIEW') // Card Details -#define ID_WDIB MKID_BE('WDIB') // LZ-Compressed Windows Bitmap +#define ID_CLRC MKTAG('C','L','R','C') // Cursor Hotspots +#define ID_EXIT MKTAG('E','X','I','T') // Card Exit Scripts +#define ID_HINT MKTAG('H','I','N','T') // Cursor Hints +#define ID_INIT MKTAG('I','N','I','T') // Card Entrance Scripts +#define ID_MSND MKTAG('M','S','N','D') // Standard Mohawk Sound +#define ID_RLST MKTAG('R','L','S','T') // Resource List, Specifies HotSpots +#define ID_RSFL MKTAG('R','S','F','L') // ??? (system.dat only) +#define ID_VIEW MKTAG('V','I','E','W') // Card Details +#define ID_WDIB MKTAG('W','D','I','B') // LZ-Compressed Windows Bitmap // Myst Masterpiece Edition Resource FourCC's (In addition to Myst FourCC's) -#define ID_HELP MKID_BE('HELP') // Help Chunk -#define ID_MJMP MKID_BE('MJMP') // MSND Jumps (To reduce MSND duplication) -#define ID_PICT MKID_BE('PICT') // JPEG/PICT/WDIB Image +#define ID_HELP MKTAG('H','E','L','P') // Help Chunk +#define ID_MJMP MKTAG('M','J','M','P') // MSND Jumps (To reduce MSND duplication) +#define ID_PICT MKTAG('P','I','C','T') // JPEG/PICT/WDIB Image // Riven Resource FourCC's -#define ID_BLST MKID_BE('BLST') // Card Hotspot Enabling Lists -#define ID_CARD MKID_BE('CARD') // Card Scripts -#define ID_FLST MKID_BE('FLST') // Card SFXE Lists -#define ID_HSPT MKID_BE('HSPT') // Card Hotspots -#define ID_MLST MKID_BE('MLST') // Card Movie Lists -#define ID_NAME MKID_BE('NAME') // Object Names -#define ID_PLST MKID_BE('PLST') // Card Picture Lists -#define ID_RMAP MKID_BE('RMAP') // Card Codes -#define ID_SFXE MKID_BE('SFXE') // Water Effect Animations -#define ID_SLST MKID_BE('SLST') // Card Ambient Sound Lists -#define ID_TMOV MKID_BE('tMOV') // QuickTime Movie +#define ID_BLST MKTAG('B','L','S','T') // Card Hotspot Enabling Lists +#define ID_CARD MKTAG('C','A','R','D') // Card Scripts +#define ID_FLST MKTAG('F','L','S','T') // Card SFXE Lists +#define ID_HSPT MKTAG('H','S','P','T') // Card Hotspots +#define ID_MLST MKTAG('M','L','S','T') // Card Movie Lists +#define ID_NAME MKTAG('N','A','M','E') // Object Names +#define ID_PLST MKTAG('P','L','S','T') // Card Picture Lists +#define ID_RMAP MKTAG('R','M','A','P') // Card Codes +#define ID_SFXE MKTAG('S','F','X','E') // Water Effect Animations +#define ID_SLST MKTAG('S','L','S','T') // Card Ambient Sound Lists +#define ID_TMOV MKTAG('t','M','O','V') // QuickTime Movie // Riven Saved Game FourCC's -#define ID_VARS MKID_BE('VARS') // Variable Values -#define ID_VERS MKID_BE('VERS') // Version Info -#define ID_ZIPS MKID_BE('ZIPS') // Zip Mode Status +#define ID_VARS MKTAG('V','A','R','S') // Variable Values +#define ID_VERS MKTAG('V','E','R','S') // Version Info +#define ID_ZIPS MKTAG('Z','I','P','S') // Zip Mode Status // Zoombini Resource FourCC's -#define ID_SND MKID_BE('\0SND') // Standard Mohawk Sound -#define ID_CURS MKID_BE('CURS') // Cursor -#define ID_SCRB MKID_BE('SCRB') // Feature Script -#define ID_SCRS MKID_BE('SCRS') // Snoid Script -#define ID_NODE MKID_BE('NODE') // Walk Node -#define ID_PATH MKID_BE('PATH') // Walk Path -#define ID_SHPL MKID_BE('SHPL') // Shape List +#define ID_SND MKTAG( 0 ,'S','N','D') // Standard Mohawk Sound +#define ID_CURS MKTAG('C','U','R','S') // Cursor +#define ID_SCRB MKTAG('S','C','R','B') // Feature Script +#define ID_SCRS MKTAG('S','C','R','S') // Snoid Script +#define ID_NODE MKTAG('N','O','D','E') // Walk Node +#define ID_PATH MKTAG('P','A','T','H') // Walk Path +#define ID_SHPL MKTAG('S','H','P','L') // Shape List // Living Books Resource FourCC's -#define ID_TCUR MKID_BE('tCUR') // Cursor -#define ID_BITL MKID_BE('BITL') // Book Item List -#define ID_CTBL MKID_BE('CTBL') // Color Table -#define ID_SCRP MKID_BE('SCRP') // Script -#define ID_SPR MKID_BE('SPR#') // Sprite? -#define ID_VRSN MKID_BE('VRSN') // Version -#define ID_ANI MKID_BE('ANI ') // Animation -#define ID_SHP MKID_BE('SHP#') // Shape -#define ID_WAV MKID_BE('WAV ') // Old Sound Resource -#define ID_BMAP MKID_BE('BMAP') // Old Mohawk Bitmap -#define ID_BCOD MKID_BE('BCOD') // Book Code +#define ID_TCUR MKTAG('t','C','U','R') // Cursor +#define ID_BITL MKTAG('B','I','T','L') // Book Item List +#define ID_CTBL MKTAG('C','T','B','L') // Color Table +#define ID_SCRP MKTAG('S','C','R','P') // Script +#define ID_SPR MKTAG('S','P','R','#') // Sprite? +#define ID_VRSN MKTAG('V','R','S','N') // Version +#define ID_ANI MKTAG('A','N','I',' ') // Animation +#define ID_SHP MKTAG('S','H','P','#') // Shape +#define ID_WAV MKTAG('W','A','V',' ') // Old Sound Resource +#define ID_BMAP MKTAG('B','M','A','P') // Old Mohawk Bitmap +#define ID_BCOD MKTAG('B','C','O','D') // Book Code // JamesMath Resource FourCC's -#define ID_TANM MKID_BE('tANM') // Animation? -#define ID_TMFO MKID_BE('tMFO') // ??? +#define ID_TANM MKTAG('t','A','N','M') // Animation? +#define ID_TMFO MKTAG('t','M','F','O') // ??? // CSTime Resource FourCC's -#define ID_CINF MKID_BE('CINF') // Case Info -#define ID_CONV MKID_BE('CONV') // Conversation -#define ID_HOTS MKID_BE('HOTS') // Hotspot -#define ID_INVO MKID_BE('INVO') // Inventory Object -#define ID_QARS MKID_BE('QARS') // Question and Responses -#define ID_SCEN MKID_BE('SCEN') // Scene -#define ID_STRI MKID_BE('STRI') // String Entry? +#define ID_CINF MKTAG('C','I','N','F') // Case Info +#define ID_CONV MKTAG('C','O','N','V') // Conversation +#define ID_HOTS MKTAG('H','O','T','S') // Hotspot +#define ID_INVO MKTAG('I','N','V','O') // Inventory Object +#define ID_QARS MKTAG('Q','A','R','S') // Question and Responses +#define ID_SCEN MKTAG('S','C','E','N') // Scene +#define ID_STRI MKTAG('S','T','R','I') // String Entry? // Mohawk Wave Tags -#define ID_WAVE MKID_BE('WAVE') // Game Sound (Third Tag) -#define ID_ADPC MKID_BE('ADPC') // Game Sound Chunk -#define ID_DATA MKID_BE('Data') // Game Sound Chunk -#define ID_CUE MKID_BE('Cue#') // Game Sound Chunk +#define ID_WAVE MKTAG('W','A','V','E') // Game Sound (Third Tag) +#define ID_ADPC MKTAG('A','D','P','C') // Game Sound Chunk +#define ID_DATA MKTAG('D','a','t','a') // Game Sound Chunk +#define ID_CUE MKTAG('C','u','e','#') // Game Sound Chunk // Mohawk MIDI Tags -#define ID_MIDI MKID_BE('MIDI') // Game Sound (Third Tag), instead of WAVE -#define ID_PRG MKID_BE('Prg#') // MIDI Patch +#define ID_MIDI MKTAG('M','I','D','I') // Game Sound (Third Tag), instead of WAVE +#define ID_PRG MKTAG('P','r','g','#') // MIDI Patch // Common Resource FourCC's -#define ID_TBMP MKID_BE('tBMP') // Standard Mohawk Bitmap -#define ID_TWAV MKID_BE('tWAV') // Standard Mohawk Sound -#define ID_TPAL MKID_BE('tPAL') // Standard Mohawk Palette -#define ID_TCNT MKID_BE('tCNT') // Shape Count (CSWorld, CSAmtrak, JamesMath) -#define ID_TSCR MKID_BE('tSCR') // Script (CSWorld, CSAmtrak, Treehouse) -#define ID_STRL MKID_BE('STRL') // String List (Zoombini, CSWorld, CSAmtrak) -#define ID_TBMH MKID_BE('tBMH') // Standard Mohawk Bitmap -#define ID_TMID MKID_BE('tMID') // Standard Mohawk MIDI -#define ID_REGS MKID_BE('REGS') // Registration Data - Shape Offsets (Zoombini, Treehouse) -#define ID_BYTS MKID_BE('BYTS') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak) -#define ID_INTS MKID_BE('INTS') // uint16 Array? (CSWorld, CSAmtrak) -#define ID_BBOX MKID_BE('BBOX') // Boxes? (CSWorld, CSAmtrak) -#define ID_SYSX MKID_BE('SYSX') // MIDI Sysex +#define ID_TBMP MKTAG('t','B','M','P') // Standard Mohawk Bitmap +#define ID_TWAV MKTAG('t','W','A','V') // Standard Mohawk Sound +#define ID_TPAL MKTAG('t','P','A','L') // Standard Mohawk Palette +#define ID_TCNT MKTAG('t','C','N','T') // Shape Count (CSWorld, CSAmtrak, JamesMath) +#define ID_TSCR MKTAG('t','S','C','R') // Script (CSWorld, CSAmtrak, Treehouse) +#define ID_STRL MKTAG('S','T','R','L') // String List (Zoombini, CSWorld, CSAmtrak) +#define ID_TBMH MKTAG('t','B','M','H') // Standard Mohawk Bitmap +#define ID_TMID MKTAG('t','M','I','D') // Standard Mohawk MIDI +#define ID_REGS MKTAG('R','E','G','S') // Registration Data - Shape Offsets (Zoombini, Treehouse) +#define ID_BYTS MKTAG('B','Y','T','S') // Byte Array? (Used as Database Entry in CSWorld, CSAmtrak) +#define ID_INTS MKTAG('I','N','T','S') // uint16 Array? (CSWorld, CSAmtrak) +#define ID_BBOX MKTAG('B','B','O','X') // Boxes? (CSWorld, CSAmtrak) +#define ID_SYSX MKTAG('S','Y','S','X') // MIDI Sysex struct FileTable { uint32 offset; diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index b4ae50b74a..9759f14699 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -479,7 +479,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags); } else if (dataChunk.encoding == kCodecADPCM) { uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8; - return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMIma, dataChunk.sampleRate, dataChunk.channels, blockAlign); + return Audio::makeADPCMStream(dataChunk.audioData, DisposeAfterUse::YES, dataSize, Audio::kADPCMDVI, dataChunk.sampleRate, dataChunk.channels, blockAlign); } else if (dataChunk.encoding == kCodecMPEG2) { #ifdef USE_MAD return Audio::makeMP3Stream(dataChunk.audioData, DisposeAfterUse::YES); diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index 98770b9a6d..133b7bef6c 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -91,7 +91,7 @@ NSArchive::NSArchive(Common::SeekableReadStream *stream, Common::Platform platfo if (features & GF_DEMO) { isSmallArchive = stream->size() == SIZEOF_SMALL_ARCHIVE; } else if (features & GF_LANG_MULT) { - isSmallArchive = (stream->readUint32BE() != MKID_BE('NDOS')); + isSmallArchive = (stream->readUint32BE() != MKTAG('N','D','O','S')); } } @@ -801,7 +801,7 @@ void AmigaDisk_ns::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 b uint16 planeSize = bytesPerPlane * height; for (uint32 i = 0; i < numFrames; i++) { - if (READ_BE_UINT32(src) == MKID_BE('DLTA')) { + if (READ_BE_UINT32(src) == MKTAG('D','L','T','A')) { uint size = READ_BE_UINT32(src + 4); diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp index 7b16df52bf..b130b27a89 100644 --- a/engines/queen/display.cpp +++ b/engines/queen/display.cpp @@ -843,19 +843,19 @@ void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dst uint32 size = READ_BE_UINT32(src + 4); src += 8; switch (type) { - case MKID_BE('BMHD'): { + case MKTAG('B','M','H','D'): { *w = READ_BE_UINT16(src + 0); *h = READ_BE_UINT16(src + 2); planeCount = src[8]; planePitch = ((*w + 15) >> 4) * 2; } break; - case MKID_BE('CMAP'): { + case MKTAG('C','M','A','P'): { assert(palStart <= palEnd && palEnd <= size / 3); memcpy(pal, src + palStart * 3, (palEnd - palStart) * 3); } break; - case MKID_BE('BODY'): { + case MKTAG('B','O','D','Y'): { uint32 planarSize = (*h) * planeCount * planePitch; uint8 *planarBuf = new uint8[planarSize]; uint8 *dstPlanar = planarBuf; diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp index 692e38179a..519f028cda 100644 --- a/engines/queen/queen.cpp +++ b/engines/queen/queen.cpp @@ -403,7 +403,7 @@ Common::InSaveFile *QueenEngine::readGameStateHeader(int slot, GameStateHeader * char name[20]; makeGameStateName(slot, name); Common::InSaveFile *file = _saveFileMan->openForLoading(name); - if (file && file->readUint32BE() == MKID_BE('SCVM')) { + if (file && file->readUint32BE() == MKTAG('S','C','V','M')) { gsh->version = file->readUint32BE(); gsh->flags = file->readUint32BE(); gsh->dataSize = file->readUint32BE(); diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp index a70d1f1613..e8519ee68b 100644 --- a/engines/queen/resource.cpp +++ b/engines/queen/resource.cpp @@ -132,7 +132,7 @@ void Resource::loadTextFile(const char *filename, Common::StringArray &stringLis bool Resource::detectVersion(DetectedGameVersion *ver, Common::File *f) { memset(ver, 0, sizeof(DetectedGameVersion)); - if (f->readUint32BE() == MKID_BE('QTBL')) { + if (f->readUint32BE() == MKTAG('Q','T','B','L')) { f->read(ver->str, 6); f->skip(2); ver->compression = f->readByte(); @@ -269,7 +269,7 @@ void Resource::seekResourceFile(int num, uint32 offset) { void Resource::readTableFile(uint8 version, uint32 offset) { Common::File tableFile; tableFile.open(_tableFilename); - if (tableFile.isOpen() && tableFile.readUint32BE() == MKID_BE('QTBL')) { + if (tableFile.isOpen() && tableFile.readUint32BE() == MKTAG('Q','T','B','L')) { uint32 tableVersion = tableFile.readUint32BE(); if (version > tableVersion) { error("The game you are trying to play requires version %d of queen.tbl, " diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index f8c06bff8c..b1bcc99295 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -264,7 +264,7 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s if (version < 4) warning("This savegame is not endian-safe. There may be problems"); - if (type != MKID_BE('SAGA')) { + if (type != MKTAG('S','A','G','A')) { error("SagaEngine::load wrong save game format"); } diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp index 2ec2099c8d..21cf0ef4c1 100644 --- a/engines/saga/resource_hrs.cpp +++ b/engines/saga/resource_hrs.cpp @@ -62,7 +62,7 @@ bool ResourceContext_HRS::loadResV2(uint32 contextSize) { readElement(_file, origin); // Check if the file is valid - if (origin.id != MKID_BE('HRES')) { // header + if (origin.id != MKTAG('H','R','E','S')) { // header return false; } diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp index 42c4dc05e8..089757ca27 100644 --- a/engines/saga/resource_rsc.cpp +++ b/engines/saga/resource_rsc.cpp @@ -30,7 +30,7 @@ namespace Saga { -#define ID_MIDI MKID_BE('Midi') +#define ID_MIDI MKTAG('M','i','d','i') bool ResourceContext_RSC::loadMacMIDI() { // Sanity check diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index c5388d6878..9edb79fa7c 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -151,7 +151,7 @@ void SagaEngine::fillSaveList() { _saveHeader.version = in->readUint32LE(); in->read(_saveHeader.name, sizeof(_saveHeader.name)); - if (_saveHeader.type != MKID_BE('SAGA')) { + if (_saveHeader.type != MKTAG('S','A','G','A')) { warning("SagaEngine::load wrong save %s format", name); i++; continue; @@ -175,7 +175,7 @@ void SagaEngine::save(const char *fileName, const char *saveName) { return; } - _saveHeader.type = MKID_BE('SAGA'); + _saveHeader.type = MKTAG('S','A','G','A'); _saveHeader.size = 0; _saveHeader.version = CURRENT_SAGA_VER; // Note that IHNM has a smaller save title size than ITE @@ -287,7 +287,7 @@ void SagaEngine::load(const char *fileName) { if (_saveHeader.version < 4) warning("This savegame is not endian-safe. There may be problems"); - if (_saveHeader.type != MKID_BE('SAGA')) { + if (_saveHeader.type != MKTAG('S','A','G','A')) { error("SagaEngine::load wrong save game format"); } diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp index 3ae2f19e1b..bd1d6e5d84 100644 --- a/engines/saga/script.cpp +++ b/engines/saga/script.cpp @@ -160,7 +160,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) { } // Script export segment (lookup table) - uint32 saga2ExportSegId = MKID_BE('_EXP'); + uint32 saga2ExportSegId = MKTAG('_','E','X','P'); int32 entryNum = _scriptContext->getEntryNum(saga2ExportSegId); if (entryNum < 0) error("Unable to locate the script's export segment"); @@ -176,7 +176,7 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) { // Script data segment /* - uint32 saga2DataSegId = MKID_BE('__DA'); + uint32 saga2DataSegId = MKTAG('_','_','D','A'); entryNum = _scriptContext->getEntryNum(saga2DataSegId); if (entryNum < 0) error("Unable to locate the script's data segment"); diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 5a6b1859cd..0433479a09 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -903,7 +903,7 @@ void GfxPalette::loadMacIconBarPalette() { if (!g_sci->hasMacIconBar()) return; - Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKID_BE('clut'), 150); + Common::SeekableReadStream *clutStream = g_sci->getMacExecutable()->getResource(MKTAG('c','l','u','t'), 150); if (!clutStream) error("Could not find clut 150 for the Mac icon bar"); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 32f54c7e23..f619780c7c 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -360,7 +360,6 @@ byte GfxScreen::isFillMatch(int16 x, int16 y, byte screenMask, byte t_color, byt int offset = y * _width + x; byte match = 0; - // FIXME: if (screenMask & GFX_SCREEN_MASK_VISUAL) { if (!isEGA) { if (*(_visualScreen + offset) == t_color) diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 61df02acf9..4caa77b0ae 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1488,7 +1488,7 @@ void ResourceManager::readResourcePatchesBase36() { Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); uint32 tag = stream->readUint32BE(); - if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) { + if (tag == MKTAG('R','I','F','F') || tag == MKTAG('F','O','R','M')) { delete stream; processWavePatch(resource36, name); continue; @@ -1497,7 +1497,7 @@ void ResourceManager::readResourcePatchesBase36() { // Check for SOL as well tag = (tag << 16) | stream->readUint16BE(); - if (tag != MKID_BE('SOL\0')) { + if (tag != MKTAG('S','O','L',0)) { delete stream; continue; } @@ -1746,25 +1746,25 @@ struct MacResTag { }; static const MacResTag macResTagMap[] = { - { MKID_BE('V56 '), kResourceTypeView }, - { MKID_BE('P56 '), kResourceTypePic }, - { MKID_BE('SCR '), kResourceTypeScript }, - { MKID_BE('TEX '), kResourceTypeText }, - { MKID_BE('SND '), kResourceTypeSound }, - { MKID_BE('VOC '), kResourceTypeVocab }, - { MKID_BE('FON '), kResourceTypeFont }, - { MKID_BE('CURS'), kResourceTypeCursor }, - { MKID_BE('crsr'), kResourceTypeCursor }, - { MKID_BE('Pat '), kResourceTypePatch }, - { MKID_BE('PAL '), kResourceTypePalette }, - { MKID_BE('snd '), kResourceTypeAudio }, - { MKID_BE('MSG '), kResourceTypeMessage }, - { MKID_BE('HEP '), kResourceTypeHeap }, - { MKID_BE('IBIN'), kResourceTypeMacIconBarPictN }, - { MKID_BE('IBIS'), kResourceTypeMacIconBarPictS }, - { MKID_BE('PICT'), kResourceTypeMacPict }, - { MKID_BE('SYN '), kResourceTypeSync }, - { MKID_BE('SYNC'), kResourceTypeSync } + { MKTAG('V','5','6',' '), kResourceTypeView }, + { MKTAG('P','5','6',' '), kResourceTypePic }, + { MKTAG('S','C','R',' '), kResourceTypeScript }, + { MKTAG('T','E','X',' '), kResourceTypeText }, + { MKTAG('S','N','D',' '), kResourceTypeSound }, + { MKTAG('V','O','C',' '), kResourceTypeVocab }, + { MKTAG('F','O','N',' '), kResourceTypeFont }, + { MKTAG('C','U','R','S'), kResourceTypeCursor }, + { MKTAG('c','r','s','r'), kResourceTypeCursor }, + { MKTAG('P','a','t',' '), kResourceTypePatch }, + { MKTAG('P','A','L',' '), kResourceTypePalette }, + { MKTAG('s','n','d',' '), kResourceTypeAudio }, + { MKTAG('M','S','G',' '), kResourceTypeMessage }, + { MKTAG('H','E','P',' '), kResourceTypeHeap }, + { MKTAG('I','B','I','N'), kResourceTypeMacIconBarPictN }, + { MKTAG('I','B','I','S'), kResourceTypeMacIconBarPictS }, + { MKTAG('P','I','C','T'), kResourceTypeMacPict }, + { MKTAG('S','Y','N',' '), kResourceTypeSync }, + { MKTAG('S','Y','N','C'), kResourceTypeSync } }; static Common::Array<uint32> resTypeToMacTags(ResourceType type) { diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 386bfb37f5..6e74553f56 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -53,9 +53,9 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, co fileStream->seek(0, SEEK_SET); uint32 compressionType = fileStream->readUint32BE(); switch (compressionType) { - case MKID_BE('MP3 '): - case MKID_BE('OGG '): - case MKID_BE('FLAC'): + case MKTAG('M','P','3',' '): + case MKTAG('O','G','G',' '): + case MKTAG('F','L','A','C'): // Detected a compressed audio volume _audioCompressionType = compressionType; // Now read the whole offset mapping table for later usage @@ -91,7 +91,7 @@ bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) { bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { // Check for WAVE files here uint32 riffTag = file->readUint32BE(); - if (riffTag == MKID_BE('RIFF')) { + if (riffTag == MKTAG('R','I','F','F')) { _headerSize = 0; size = file->readUint32LE() + 8; file->seek(-8, SEEK_CUR); diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 73f471b247..53311b4252 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -195,7 +195,7 @@ static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSiz uint32 tag = audioStream->readUint32BE(); - if (tag != MKID_BE('SOL\0')) { + if (tag != MKTAG('S','O','L',0)) { warning("No 'SOL' FourCC found"); return false; } @@ -290,17 +290,17 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 Common::SeekableReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES); switch (audioCompressionType) { - case MKID_BE('MP3 '): + case MKTAG('M','P','3',' '): #ifdef USE_MAD audioSeekStream = Audio::makeMP3Stream(compressedStream, DisposeAfterUse::YES); #endif break; - case MKID_BE('OGG '): + case MKTAG('O','G','G',' '): #ifdef USE_VORBIS audioSeekStream = Audio::makeVorbisStream(compressedStream, DisposeAfterUse::YES); #endif break; - case MKID_BE('FLAC'): + case MKTAG('F','L','A','C'): #ifdef USE_FLAC audioSeekStream = Audio::makeFLACStream(compressedStream, DisposeAfterUse::YES); #endif @@ -319,7 +319,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); data = readSOLAudio(&dataStream, size, audioFlags, flags); } - } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('RIFF')) { + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('R','I','F','F')) { // WAVE detected Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); @@ -331,7 +331,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 waveStream->seek(0, SEEK_SET); audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); - } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) { + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKTAG('F','O','R','M')) { // AIFF detected Common::SeekableReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index f674a502d6..9eef867aeb 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -611,7 +611,7 @@ void MidiPlayer_Midi::readMt32DrvData() { int size = f.size(); // Skip before-SysEx text - if (size == 1773 || size == 1759) // XMAS88 / KQ4 early + if (size == 1773 || size == 1759 || size == 1747) // XMAS88 / KQ4 early (0.000.253 / 0.000.274) f.seek(0x59); else if (size == 2771) // LSL2 early f.seek(0x29); diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 39db47b102..13581c4b45 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -1853,8 +1853,8 @@ void Actor::animateLimb(int limb, int f) { byte *akos = _vm->getResourceAddress(rtCostume, _costume); assert(akos); - aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos); - akfo = _vm->findResourceData(MKID_BE('AKFO'), akos); + aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos); + akfo = _vm->findResourceData(MKTAG('A','K','F','O'), akos); size = _vm->getResourceDataSize(akfo) / 2; @@ -2374,7 +2374,7 @@ void Actor::remapActorPaletteColor(int color, int new_color) { return; } - akpl = _vm->findResourceData(MKID_BE('AKPL'), akos); + akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos); if (!akpl) { debugC(DEBUG_ACTORS, "Actor::remapActorPaletteColor: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume); return; @@ -2409,7 +2409,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold) return; } - akpl = _vm->findResourceData(MKID_BE('AKPL'), akos); + akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos); if (!akpl) { debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d, costume %d doesn't contain an AKPL block", _number, _costume); return; @@ -2418,7 +2418,7 @@ void Actor::remapActorPalette(int r_fact, int g_fact, int b_fact, int threshold) // Get the number palette entries akpl_size = _vm->getResourceDataSize(akpl); - rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos); + rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos); if (!rgbs) { debugC(DEBUG_ACTORS, "Actor::remapActorPalette: Can't remap actor %d costume %d doesn't contain an RGB block", _number, _costume); @@ -2535,19 +2535,19 @@ void ScummEngine_v71he::postProcessAuxQueue() { if (_game.heversion >= 72) dy -= a->getElevation(); - const uint8 *akax = findResource(MKID_BE('AKAX'), cost); + const uint8 *akax = findResource(MKTAG('A','K','A','X'), cost); assert(akax); const uint8 *auxd = findPalInPals(akax, ae->subIndex) - _resourceHeaderSize; assert(auxd); - const uint8 *frel = findResourceData(MKID_BE('FREL'), auxd); + const uint8 *frel = findResourceData(MKTAG('F','R','E','L'), auxd); if (frel) { error("unhandled FREL block"); } - const uint8 *disp = findResourceData(MKID_BE('DISP'), auxd); + const uint8 *disp = findResourceData(MKTAG('D','I','S','P'), auxd); if (disp) { error("unhandled DISP block"); } - const uint8 *axfd = findResourceData(MKID_BE('AXFD'), auxd); + const uint8 *axfd = findResourceData(MKTAG('A','X','F','D'), auxd); assert(axfd); uint16 comp = READ_LE_UINT16(axfd); @@ -2567,7 +2567,7 @@ void ScummEngine_v71he::postProcessAuxQueue() { error("unimplemented compression type %d", comp); } } - const uint8 *axur = findResourceData(MKID_BE('AXUR'), auxd); + const uint8 *axur = findResourceData(MKTAG('A','X','U','R'), auxd); if (axur) { uint16 n = READ_LE_UINT16(axur); axur += 2; while (n--) { @@ -2579,7 +2579,7 @@ void ScummEngine_v71he::postProcessAuxQueue() { axur += 8; } } - const uint8 *axer = findResourceData(MKID_BE('AXER'), auxd); + const uint8 *axer = findResourceData(MKTAG('A','X','E','R'), auxd); if (axer) { a->_auxBlock.visible = true; a->_auxBlock.r.left = (int16)READ_LE_UINT16(axer + 0) + dx; diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp index 354a1d4491..8acbb8058e 100644 --- a/engines/scumm/akos.cpp +++ b/engines/scumm/akos.cpp @@ -146,7 +146,7 @@ void AkosCostumeLoader::loadCostume(int id) { bool AkosCostumeLoader::hasManyDirections() { const AkosHeader *akhd; - akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos); + akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos); return (akhd->flags & 2) != 0; } @@ -170,12 +170,12 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) { else anim = newDirToOldDir(a->getFacing()) + frame * 4; - akhd = (const AkosHeader *)_vm->findResourceData(MKID_BE('AKHD'), _akos); + akhd = (const AkosHeader *)_vm->findResourceData(MKTAG('A','K','H','D'), _akos); if (anim >= READ_LE_UINT16(&akhd->num_anims)) return; - r = _vm->findResourceData(MKID_BE('AKCH'), _akos); + r = _vm->findResourceData(MKTAG('A','K','C','H'), _akos); assert(r); offs = READ_LE_UINT16(r + anim * sizeof(uint16)); @@ -183,8 +183,8 @@ void AkosCostumeLoader::costumeDecodeData(Actor *a, int frame, uint usemask) { return; r += offs; - const uint8 *akstPtr = _vm->findResourceData(MKID_BE('AKST'), _akos); - const uint8 *aksfPtr = _vm->findResourceData(MKID_BE('AKSF'), _akos); + const uint8 *akstPtr = _vm->findResourceData(MKTAG('A','K','S','T'), _akos); + const uint8 *aksfPtr = _vm->findResourceData(MKTAG('A','K','S','F'), _akos); i = 0; mask = READ_LE_UINT16(r); r += 2; @@ -341,21 +341,21 @@ void AkosRenderer::setCostume(int costume, int shadow) { const byte *akos = _vm->getResourceAddress(rtCostume, costume); assert(akos); - akhd = (const AkosHeader *) _vm->findResourceData(MKID_BE('AKHD'), akos); - akof = (const AkosOffset *) _vm->findResourceData(MKID_BE('AKOF'), akos); - akci = _vm->findResourceData(MKID_BE('AKCI'), akos); - aksq = _vm->findResourceData(MKID_BE('AKSQ'), akos); - akcd = _vm->findResourceData(MKID_BE('AKCD'), akos); - akpl = _vm->findResourceData(MKID_BE('AKPL'), akos); + akhd = (const AkosHeader *) _vm->findResourceData(MKTAG('A','K','H','D'), akos); + akof = (const AkosOffset *) _vm->findResourceData(MKTAG('A','K','O','F'), akos); + akci = _vm->findResourceData(MKTAG('A','K','C','I'), akos); + aksq = _vm->findResourceData(MKTAG('A','K','S','Q'), akos); + akcd = _vm->findResourceData(MKTAG('A','K','C','D'), akos); + akpl = _vm->findResourceData(MKTAG('A','K','P','L'), akos); _codec = READ_LE_UINT16(&akhd->codec); - akct = _vm->findResourceData(MKID_BE('AKCT'), akos); - rgbs = _vm->findResourceData(MKID_BE('RGBS'), akos); + akct = _vm->findResourceData(MKTAG('A','K','C','T'), akos); + rgbs = _vm->findResourceData(MKTAG('R','G','B','S'), akos); xmap = 0; if (shadow) { const uint8 *xmapPtr = _vm->getResourceAddress(rtImage, shadow); assert(xmapPtr); - xmap = _vm->findResourceData(MKID_BE('XMAP'), xmapPtr); + xmap = _vm->findResourceData(MKTAG('X','M','A','P'), xmapPtr); assert(xmap); } } @@ -1384,8 +1384,8 @@ bool ScummEngine_v6::akos_increaseAnims(const byte *akos, Actor *a) { uint size; bool result; - aksq = findResourceData(MKID_BE('AKSQ'), akos); - akfo = findResourceData(MKID_BE('AKFO'), akos); + aksq = findResourceData(MKTAG('A','K','S','Q'), akos); + akfo = findResourceData(MKTAG('A','K','F','O'), akos); size = getResourceDataSize(akfo) / 2; diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp index f49635d10f..bb3c4bcc02 100644 --- a/engines/scumm/cursor.cpp +++ b/engines/scumm/cursor.cpp @@ -240,7 +240,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) { room = getObjectRoom(img); findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room); - imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), foir.obim); + imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), foir.obim); if (_game.version == 8) { setCursorHotspot(READ_LE_UINT32(&imhd->v8.hotspot[0].x), @@ -270,7 +270,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) { if (size > sizeof(_grabbedCursor)) error("setCursorFromImg: Cursor image too large"); - bomp = findResource(MKID_BE('BOMP'), dataptr); + bomp = findResource(MKTAG('B','O','M','P'), dataptr); } if (bomp != NULL) diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 0db77a1b7d..a6a97ec426 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -283,7 +283,7 @@ void Gdi::loadTiles(byte *roomptr) { #ifdef USE_RGB_COLOR void GdiPCEngine::loadTiles(byte *roomptr) { - decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), roomptr)); + decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), roomptr)); } #endif @@ -858,7 +858,7 @@ void ScummEngine::initBGBuffers(int height) { _gdi->_numZBuffer = 2; } else if (_game.features & GF_SMALL_HEADER) { int off; - ptr = findResourceData(MKID_BE('SMAP'), room); + ptr = findResourceData(MKTAG('S','M','A','P'), room); _gdi->_numZBuffer = 0; if (_game.features & GF_16COLOR) @@ -873,13 +873,13 @@ void ScummEngine::initBGBuffers(int height) { } } else if (_game.version == 8) { // in V8 there is no RMIH and num z buffers is in RMHD - ptr = findResource(MKID_BE('RMHD'), room); + ptr = findResource(MKTAG('R','M','H','D'), room); _gdi->_numZBuffer = READ_LE_UINT32(ptr + 24) + 1; } else if (_game.heversion >= 70) { - ptr = findResource(MKID_BE('RMIH'), room); + ptr = findResource(MKTAG('R','M','I','H'), room); _gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1; } else { - ptr = findResource(MKID_BE('RMIH'), findResource(MKID_BE('RMIM'), room)); + ptr = findResource(MKTAG('R','M','I','H'), findResource(MKTAG('R','M','I','M'), room)); _gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1; } assert(_gdi->_numZBuffer >= 1 && _gdi->_numZBuffer <= 8); @@ -1647,9 +1647,9 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage) if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8) zplane_list[0] = ptr; else if (bmapImage) - zplane_list[0] = _vm->findResource(MKID_BE('BMAP'), ptr); + zplane_list[0] = _vm->findResource(MKTAG('B','M','A','P'), ptr); else - zplane_list[0] = _vm->findResource(MKID_BE('SMAP'), ptr); + zplane_list[0] = _vm->findResource(MKTAG('S','M','A','P'), ptr); if (_zbufferDisabled) numzbuf = 0; @@ -1692,11 +1692,11 @@ int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage) } } else { const uint32 zplane_tags[] = { - MKID_BE('ZP00'), - MKID_BE('ZP01'), - MKID_BE('ZP02'), - MKID_BE('ZP03'), - MKID_BE('ZP04') + MKTAG('Z','P','0','0'), + MKTAG('Z','P','0','1'), + MKTAG('Z','P','0','2'), + MKTAG('Z','P','0','3'), + MKTAG('Z','P','0','4') }; for (i = 1; i < numzbuf; i++) { @@ -1733,7 +1733,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const // Skip to the BSTR->WRAP->OFFS chunk smap_ptr = ptr + 24; } else { - smap_ptr = _vm->findResource(MKID_BE('SMAP'), ptr); + smap_ptr = _vm->findResource(MKTAG('S','M','A','P'), ptr); assert(smap_ptr); } @@ -1741,7 +1741,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const const byte *tmsk_ptr = NULL; if (_vm->_game.heversion >= 72) { - tmsk_ptr = _vm->findResource(MKID_BE('TMSK'), ptr); + tmsk_ptr = _vm->findResource(MKTAG('T','M','S','K'), ptr); } if (y + height > vs->h) { @@ -2011,7 +2011,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) { byte *mask_ptr; const byte *zplane_list[9]; - const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr); + const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr); assert(bmap_ptr); byte code = *bmap_ptr++; @@ -2091,7 +2091,7 @@ void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) { } void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h) { - const byte *bmap_ptr = _vm->findResourceData(MKID_BE('BMAP'), ptr); + const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr); assert(bmap_ptr); byte code = *bmap_ptr++; @@ -2828,10 +2828,10 @@ void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint void GdiPCEngine::decodePCEngineGfx(const byte *room) { uint16* stripOffsets; - decodePCEngineTileData(_vm->findResourceData(MKID_BE('TILE'), room)); - decodePCEngineMaskData(_vm->findResourceData(MKID_BE('ZP00'), room)); + decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), room)); + decodePCEngineMaskData(_vm->findResourceData(MKTAG('Z','P','0','0'), room)); - const byte* smap_ptr = _vm->findResourceData(MKID_BE('IM00'), room); + const byte* smap_ptr = _vm->findResourceData(MKTAG('I','M','0','0'), room); smap_ptr++; // roomID int numStrips = *smap_ptr++; int numRows = *smap_ptr++; diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp index 7840b9df20..e3e25c161c 100644 --- a/engines/scumm/he/animation_he.cpp +++ b/engines/scumm/he/animation_he.cpp @@ -112,7 +112,7 @@ void MoviePlayer::handleNextFrame() { if (_flags & 2) { uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum); assert(dstPtr); - uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); + uint8 *dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0); assert(dst); copyFrameToBuffer(dst, kDstResource, 0, 0, _vm->_screenWidth * _vm->_bytesPerPixel); } else if (_flags & 1) { diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp index 79bb47aafc..a16af73135 100644 --- a/engines/scumm/he/cup_player_he.cpp +++ b/engines/scumm/he/cup_player_he.cpp @@ -47,7 +47,7 @@ bool CUP_Player::open(const char *filename) { if (_fileStream.open(filename)) { uint32 tag = _fileStream.readUint32BE(); _fileStream.readUint32BE(); - if (tag == MKID_BE('BEAN')) { + if (tag == MKTAG('B','E','A','N')) { _playbackRate = kDefaultPlaybackRate; _width = kDefaultVideoWidth; _height = kDefaultVideoHeight; @@ -168,7 +168,7 @@ void CUP_Player::updateSfx() { assert(sfxIndex >= 0 && sfxIndex < _sfxCount); uint32 offset = READ_LE_UINT32(_sfxBuffer + sfxIndex * 4) - 8; uint8 *soundData = _sfxBuffer + offset; - if (READ_BE_UINT32(soundData) == MKID_BE('DATA')) { + if (READ_BE_UINT32(soundData) == MKTAG('D','A','T','A')) { uint32 soundSize = READ_BE_UINT32(soundData + 4); _mixer->playStream(Audio::Mixer::kSFXSoundType, &sfxChannel->handle, Audio::makeLoopingAudioStream( @@ -208,19 +208,19 @@ bool CUP_Player::parseNextHeaderTag(Common::SeekableReadStream &dataStream) { uint32 next = dataStream.pos() + size; debug(1, "New header tag %s %d dataSize %d", tag2str(tag), size, _dataSize); switch (tag) { - case MKID_BE('HEAD'): + case MKTAG('H','E','A','D'): handleHEAD(dataStream, size); break; - case MKID_BE('SFXB'): + case MKTAG('S','F','X','B'): handleSFXB(dataStream, size); break; - case MKID_BE('RGBS'): + case MKTAG('R','G','B','S'): handleRGBS(dataStream, size); break; - case MKID_BE('DATA'): + case MKTAG('D','A','T','A'): _dataSize = size; return false; - case MKID_BE('GFXB'): + case MKTAG('G','F','X','B'): // this is never triggered default: warning("Unhandled tag %s", tag2str(tag)); @@ -236,34 +236,34 @@ bool CUP_Player::parseNextBlockTag(Common::SeekableReadStream &dataStream) { uint32 next = dataStream.pos() + size; debug(1, "New block tag %s %d dataSize %d", tag2str(tag), size, _dataSize); switch (tag) { - case MKID_BE('FRAM'): + case MKTAG('F','R','A','M'): handleFRAM(dataStream, size); break; - case MKID_BE('LZSS'): + case MKTAG('L','Z','S','S'): if (handleLZSS(dataStream, size) && _outLzssBufSize != 0) { Common::MemoryReadStream memoryStream(_outLzssBufData, _outLzssBufSize); parseNextBlockTag(memoryStream); } break; - case MKID_BE('RATE'): + case MKTAG('R','A','T','E'): handleRATE(dataStream, size); break; - case MKID_BE('RGBS'): + case MKTAG('R','G','B','S'): handleRGBS(dataStream, size); break; - case MKID_BE('SNDE'): + case MKTAG('S','N','D','E'): handleSNDE(dataStream, size); break; - case MKID_BE('TOIL'): + case MKTAG('T','O','I','L'): handleTOIL(dataStream, size); break; - case MKID_BE('SRLE'): + case MKTAG('S','R','L','E'): handleSRLE(dataStream, size); break; - case MKID_BE('BLOK'): + case MKTAG('B','L','O','K'): _dataSize -= size + 8; return false; - case MKID_BE('WRLE'): + case MKTAG('W','R','L','E'): // this is never triggered default: warning("Unhandled tag %s", tag2str(tag)); @@ -283,10 +283,10 @@ void CUP_Player::handleSFXB(Common::SeekableReadStream &dataStream, uint32 dataS if (dataSize > 16) { // WRAP and OFFS chunks uint32 tag = dataStream.readUint32BE(); uint32 size = dataStream.readUint32BE(); - if (tag == MKID_BE('WRAP')) { + if (tag == MKTAG('W','R','A','P')) { tag = dataStream.readUint32BE(); size = dataStream.readUint32BE(); - if (tag == MKID_BE('OFFS')) { + if (tag == MKTAG('O','F','F','S')) { _sfxCount = (size - 8) / 4; _sfxBuffer = (uint8 *)malloc(dataSize - 16); if (_sfxBuffer) { @@ -439,12 +439,12 @@ static void decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const u bool CUP_Player::handleLZSS(Common::SeekableReadStream &dataStream, uint32 dataSize) { uint32 tag = dataStream.readUint32BE(); uint32 size = dataStream.readUint32BE(); - if (tag == MKID_BE('LZHD')) { + if (tag == MKTAG('L','Z','H','D')) { uint32 compressionType = dataStream.readUint32LE(); uint32 compressionSize = dataStream.readUint32LE(); tag = dataStream.readUint32BE(); size = dataStream.readUint32BE(); - if (tag == MKID_BE('DATA') && compressionType == 0x2000) { + if (tag == MKTAG('D','A','T','A') && compressionType == 0x2000) { if (_inLzssBufSize < size - 16) { free(_inLzssBufData); _inLzssBufSize = size - 16; diff --git a/engines/scumm/he/floodfill_he.cpp b/engines/scumm/he/floodfill_he.cpp index 491b91c17e..026a848828 100644 --- a/engines/scumm/he/floodfill_he.cpp +++ b/engines/scumm/he/floodfill_he.cpp @@ -240,7 +240,7 @@ void Wiz::fillWizFlood(const WizParameters *params) { if (params->processFlags & kWPFNewState) { state = params->img.state; } - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); @@ -258,7 +258,7 @@ void Wiz::fillWizFlood(const WizParameters *params) { color = params->fillColor; } if (imageRect.contains(px, py)) { - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(wizd); FloodFillState *ffs = new FloodFillState; diff --git a/engines/scumm/he/palette_he.cpp b/engines/scumm/he/palette_he.cpp index b42d6e97e2..7f517c56ed 100644 --- a/engines/scumm/he/palette_he.cpp +++ b/engines/scumm/he/palette_he.cpp @@ -192,7 +192,7 @@ void ScummEngine_v90he::setHEPaletteFromCostume(int palSlot, int resId) { assertRange(1, palSlot, _numPalettes, "palette"); const uint8 *data = getResourceAddress(rtCostume, resId); assert(data); - const uint8 *rgbs = findResourceData(MKID_BE('RGBS'), data); + const uint8 *rgbs = findResourceData(MKTAG('R','G','B','S'), data); assert(rgbs); setHEPaletteFromPtr(palSlot, rgbs); } @@ -202,7 +202,7 @@ void ScummEngine_v90he::setHEPaletteFromImage(int palSlot, int resId, int state) assertRange(1, palSlot, _numPalettes, "palette"); uint8 *data = getResourceAddress(rtImage, resId); assert(data); - const uint8 *rgbs = findWrappedBlock(MKID_BE('RGBS'), data, state, 0); + const uint8 *rgbs = findWrappedBlock(MKTAG('R','G','B','S'), data, state, 0); if (rgbs) setHEPaletteFromPtr(palSlot, rgbs); } @@ -212,7 +212,7 @@ void ScummEngine_v90he::setHEPaletteFromRoom(int palSlot, int resId, int state) assertRange(1, palSlot, _numPalettes, "palette"); const uint8 *data = getResourceAddress(rtRoom, resId); assert(data); - const uint8 *pals = findResourceData(MKID_BE('PALS'), data); + const uint8 *pals = findResourceData(MKTAG('P','A','L','S'), data); assert(pals); const uint8 *rgbs = findPalInPals(pals, state); assert(rgbs); diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 9349e70eb9..ecb094f29b 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -332,7 +332,7 @@ int ScummEngine_v72he::getSoundResourceSize(int id) { if (!ptr) return 0; - if (READ_BE_UINT32(ptr) == MKID_BE('RIFF')) { + if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F')) { byte flags; int rate; @@ -344,11 +344,11 @@ int ScummEngine_v72he::getSoundResourceSize(int id) { } } else { ptr += 8 + READ_BE_UINT32(ptr + 12); - if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) { + if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) { ptr += READ_BE_UINT32(ptr + 4); } - assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT')); + assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T')); size = READ_BE_UINT32(ptr + 4) - 8; } } diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index ca4a65ac74..69063a1837 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -2999,7 +2999,7 @@ void ScummEngine_v100he::decodeParseString(int m, int n) { case 78: { byte *dataPtr = getResourceAddress(rtTalkie, pop()); - byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0); + byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0); size = getResourceDataSize(text); memcpy(name, text, size); printString(m, name); diff --git a/engines/scumm/he/script_v71he.cpp b/engines/scumm/he/script_v71he.cpp index 46a8868949..a800a7d85c 100644 --- a/engines/scumm/he/script_v71he.cpp +++ b/engines/scumm/he/script_v71he.cpp @@ -88,15 +88,15 @@ byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) { } byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool errorFlag) { - if (READ_BE_UINT32(ptr) == MKID_BE('MULT')) { + if (READ_BE_UINT32(ptr) == MKTAG('M','U','L','T')) { byte *offs, *wrap; uint32 size; - wrap = heFindResource(MKID_BE('WRAP'), ptr); + wrap = heFindResource(MKTAG('W','R','A','P'), ptr); if (wrap == NULL) return NULL; - offs = heFindResourceData(MKID_BE('OFFS'), wrap); + offs = heFindResourceData(MKTAG('O','F','F','S'), wrap); if (offs == NULL) return NULL; @@ -109,7 +109,7 @@ byte *ScummEngine_v71he::findWrappedBlock(uint32 tag, byte *ptr, int state, bool if (offs) return offs; - offs = heFindResourceData(MKID_BE('DEFA'), ptr); + offs = heFindResourceData(MKTAG('D','E','F','A'), ptr); if (offs == NULL) return NULL; diff --git a/engines/scumm/he/script_v72he.cpp b/engines/scumm/he/script_v72he.cpp index 8aaf16e81b..17bd29d826 100644 --- a/engines/scumm/he/script_v72he.cpp +++ b/engines/scumm/he/script_v72he.cpp @@ -2039,7 +2039,7 @@ void ScummEngine_v72he::decodeParseString(int m, int n) { case 0xE1: { byte *dataPtr = getResourceAddress(rtTalkie, pop()); - byte *text = findWrappedBlock(MKID_BE('TEXT'), dataPtr, 0, 0); + byte *text = findWrappedBlock(MKTAG('T','E','X','T'), dataPtr, 0, 0); size = getResourceDataSize(text); memcpy(name, text, size); printString(m, name); diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp index 4770f28cbc..4fd7caebf5 100644 --- a/engines/scumm/he/sound_he.cpp +++ b/engines/scumm/he/sound_he.cpp @@ -499,11 +499,11 @@ byte *findSoundTag(uint32 tag, byte *ptr) { byte *endPtr; uint32 offset, size; - if (READ_BE_UINT32(ptr) == MKID_BE('WSOU')) { + if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) { ptr += 8; } - if (READ_BE_UINT32(ptr) != MKID_BE('RIFF')) + if (READ_BE_UINT32(ptr) != MKTAG('R','I','F','F')) return NULL; endPtr = (ptr + 12); @@ -591,14 +591,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) } // Support for sound in later HE games - if (READ_BE_UINT32(ptr) == MKID_BE('RIFF') || READ_BE_UINT32(ptr) == MKID_BE('WSOU')) { + if (READ_BE_UINT32(ptr) == MKTAG('R','I','F','F') || READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) { uint16 compType; int blockAlign; int codeOffs = -1; priority = (soundID > _vm->_numSounds) ? 255 : *(ptr + 18); - byte *sbngPtr = findSoundTag(MKID_BE('SBNG'), ptr); + byte *sbngPtr = findSoundTag(MKTAG('S','B','N','G'), ptr); if (sbngPtr != NULL) { codeOffs = sbngPtr - ptr + 8; } @@ -611,7 +611,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) return; } - if (READ_BE_UINT32(ptr) == MKID_BE('WSOU')) + if (READ_BE_UINT32(ptr) == MKTAG('W','S','O','U')) ptr += 8; size = READ_LE_UINT32(ptr + 4); @@ -675,7 +675,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID); } // Support for sound in Humongous Entertainment games - else if (READ_BE_UINT32(ptr) == MKID_BE('DIGI') || READ_BE_UINT32(ptr) == MKID_BE('TALK')) { + else if (READ_BE_UINT32(ptr) == MKTAG('D','I','G','I') || READ_BE_UINT32(ptr) == MKTAG('T','A','L','K')) { byte *sndPtr = ptr; int codeOffs = -1; @@ -693,12 +693,12 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) return; } - if (READ_BE_UINT32(ptr) == MKID_BE('SBNG')) { + if (READ_BE_UINT32(ptr) == MKTAG('S','B','N','G')) { codeOffs = ptr - sndPtr + 8; ptr += READ_BE_UINT32(ptr + 4); } - assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT')); + assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T')); size = READ_BE_UINT32(ptr + 4) - 8; if (heOffset < 0 || heOffset > size) { // Occurs when making fireworks in puttmoon @@ -734,14 +734,14 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) Audio::makeLoopingAudioStream(stream, (heFlags & 1) ? 0 : 1), soundID); } // Support for PCM music in 3DO versions of Humongous Entertainment games - else if (READ_BE_UINT32(ptr) == MKID_BE('MRAW')) { + else if (READ_BE_UINT32(ptr) == MKTAG('M','R','A','W')) { priority = *(ptr + 18); rate = READ_LE_UINT16(ptr + 22); // Skip DIGI (8) and HSHD (24) blocks ptr += 32; - assert(READ_BE_UINT32(ptr) == MKID_BE('SDAT')); + assert(READ_BE_UINT32(ptr) == MKTAG('S','D','A','T')); size = READ_BE_UINT32(ptr + 4) - 8; byte *sound = (byte *)malloc(size); @@ -753,7 +753,7 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags) stream = Audio::makeRawStream(sound, size, rate, 0); _mixer->playStream(Audio::Mixer::kMusicSoundType, NULL, stream, soundID); } - else if (READ_BE_UINT32(ptr) == MKID_BE('MIDI')) { + else if (READ_BE_UINT32(ptr) == MKTAG('M','I','D','I')) { if (_vm->_imuse) { // This is used in the DOS version of Fatty Bear's // Birthday Surprise to change the note on the piano @@ -833,9 +833,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { chan = i; } - if (!findSoundTag(MKID_BE('data'), snd1Ptr)) { - sbng1Ptr = heFindResource(MKID_BE('SBNG'), snd1Ptr); - sbng2Ptr = heFindResource(MKID_BE('SBNG'), snd2Ptr); + if (!findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) { + sbng1Ptr = heFindResource(MKTAG('S','B','N','G'), snd1Ptr); + sbng2Ptr = heFindResource(MKTAG('S','B','N','G'), snd2Ptr); } if (sbng1Ptr != NULL && sbng2Ptr != NULL) { @@ -879,10 +879,10 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { } } - if (findSoundTag(MKID_BE('data'), snd1Ptr)) { - sdat1Ptr = findSoundTag(MKID_BE('data'), snd1Ptr); + if (findSoundTag(MKTAG('d','a','t','a'), snd1Ptr)) { + sdat1Ptr = findSoundTag(MKTAG('d','a','t','a'), snd1Ptr); assert(sdat1Ptr); - sdat2Ptr = findSoundTag(MKID_BE('data'), snd2Ptr); + sdat2Ptr = findSoundTag(MKTAG('d','a','t','a'), snd2Ptr); assert(sdat2Ptr); if (!_sndDataSize) @@ -890,9 +890,9 @@ void ScummEngine_v80he::createSound(int snd1id, int snd2id) { sdat2size = READ_LE_UINT32(sdat2Ptr + 4) - 8; } else { - sdat1Ptr = heFindResource(MKID_BE('SDAT'), snd1Ptr); + sdat1Ptr = heFindResource(MKTAG('S','D','A','T'), snd1Ptr); assert(sdat1Ptr); - sdat2Ptr = heFindResource(MKID_BE('SDAT'), snd2Ptr); + sdat2Ptr = heFindResource(MKTAG('S','D','A','T'), snd2Ptr); assert(sdat2Ptr); _sndDataSize = READ_BE_UINT32(sdat1Ptr + 4) - 8; diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 3d1aa5b048..16cbadd65b 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -1445,21 +1445,21 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int if (shadow) { dataPtr = _vm->getResourceAddress(rtImage, shadow); assert(dataPtr); - xmapPtr = _vm->findResourceData(MKID_BE('XMAP'), dataPtr); + xmapPtr = _vm->findResourceData(MKTAG('X','M','A','P'), dataPtr); assert(xmapPtr); } dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); uint32 comp = READ_LE_UINT32(wizh + 0x0); uint32 width = READ_LE_UINT32(wizh + 0x4); uint32 height = READ_LE_UINT32(wizh + 0x8); debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(wizd); uint8 *mask = NULL; @@ -1467,28 +1467,28 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum); assert(maskPtr); - wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), maskPtr, maskState, 0); + wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), maskPtr, maskState, 0); assert(wizh); assert(comp == 2 && READ_LE_UINT32(wizh + 0x0) == 1); width = READ_LE_UINT32(wizh + 0x4); height = READ_LE_UINT32(wizh + 0x8); - mask = _vm->findWrappedBlock(MKID_BE('WIZD'), maskPtr, maskState, 0); + mask = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), maskPtr, maskState, 0); assert(mask); } if (flags & kWIFHasPalette) { - uint8 *pal = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0); + uint8 *pal = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0); assert(pal); _vm->setPaletteFromPtr(pal, 256); } uint8 *rmap = NULL; if (flags & kWIFRemapPalette) { - rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0); + rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0); assert(rmap); if (_vm->_game.heversion <= 80 || READ_BE_UINT32(rmap) != 0x01234567) { - uint8 *rgbs = _vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0); + uint8 *rgbs = _vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0); assert(rgbs); _vm->remapHEPalette(rgbs, rmap + 4); } @@ -1526,7 +1526,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int if (dstResNum) { uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum); assert(dstPtr); - dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); + dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0); assert(dst); getWizImageDim(dstResNum, 0, cw, ch); dstPitch = cw * _vm->_bytesPerPixel; @@ -1567,7 +1567,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int int transColor = -1; if (_vm->VAR_WIZ_TCOLOR != 0xFF) { - uint8 *trns = _vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0); + uint8 *trns = _vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0); transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1; } @@ -1817,7 +1817,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int assert(_vm->_bytesPerPixel == 1); uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); - srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(srcWizBuf); freeBuffer = false; } @@ -1827,7 +1827,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int } else { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); - srcWizBuf = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + srcWizBuf = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(srcWizBuf); freeBuffer = false; } @@ -1842,7 +1842,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int if (dstResNum) { uint8 *dstPtr = _vm->getResourceAddress(rtImage, dstResNum); assert(dstPtr); - dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); + dst = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dstPtr, 0, 0); assert(dst); getWizImageDim(dstResNum, 0, dstw, dsth); dstpitch = dstw * _vm->_bytesPerPixel; @@ -2185,7 +2185,7 @@ void Wiz::fillWizRect(const WizParameters *params) { } uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum); if (dataPtr) { - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); @@ -2210,7 +2210,7 @@ void Wiz::fillWizRect(const WizParameters *params) { } if (areaRect.intersects(imageRect)) { areaRect.clip(imageRect); - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(wizd); int dx = areaRect.width(); int dy = areaRect.height(); @@ -2256,7 +2256,7 @@ void Wiz::fillWizLine(const WizParameters *params) { } uint8 *dataPtr = _vm->getResourceAddress(rtImage, params->img.resNum); if (dataPtr) { - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); @@ -2274,7 +2274,7 @@ void Wiz::fillWizLine(const WizParameters *params) { if (params->processFlags & kWPFFillColor) { color = params->fillColor; } - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(wizd); int x1 = params->box2.left; int y1 = params->box2.top; @@ -2309,7 +2309,7 @@ void Wiz::fillWizPixel(const WizParameters *params) { if (params->processFlags & kWPFNewState) { state = params->img.state; } - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); @@ -2327,7 +2327,7 @@ void Wiz::fillWizPixel(const WizParameters *params) { color = params->fillColor; } if (imageRect.contains(px, py)) { - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), dataPtr, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); assert(wizd); *(wizd + py * w + px) = color; } @@ -2342,7 +2342,7 @@ void Wiz::remapWizImagePal(const WizParameters *params) { const uint8 *index = params->remapIndex; uint8 *iwiz = _vm->getResourceAddress(rtImage, params->img.resNum); assert(iwiz); - uint8 *rmap = _vm->findWrappedBlock(MKID_BE('RMAP'), iwiz, st, 0); + uint8 *rmap = _vm->findWrappedBlock(MKTAG('R','M','A','P'), iwiz, st, 0); assert(rmap); WRITE_BE_UINT32(rmap, 0x01234567); while (num--) { @@ -2380,7 +2380,7 @@ void Wiz::processWizImage(const WizParameters *params) { if (f) { uint32 id = f->readUint32BE(); - if (id == MKID_BE('AWIZ') || id == MKID_BE('MULT')) { + if (id == MKTAG('A','W','I','Z') || id == MKTAG('M','U','L','T')) { uint32 size = f->readUint32BE(); f->seek(0, SEEK_SET); byte *p = _vm->_res->createResource(rtImage, params->img.resNum, size); @@ -2510,7 +2510,7 @@ void Wiz::processWizImage(const WizParameters *params) { void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); w = READ_LE_UINT32(wizh + 0x4); h = READ_LE_UINT32(wizh + 0x8); @@ -2519,7 +2519,7 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId); assert(dataPtr); - uint8 *spotPtr = _vm->findWrappedBlock(MKID_BE('SPOT'), dataPtr, state, 0); + uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0); if (spotPtr) { x = READ_LE_UINT32(spotPtr + 0); y = READ_LE_UINT32(spotPtr + 4); @@ -2537,17 +2537,17 @@ int Wiz::getWizImageData(int resNum, int state, int type) { switch (type) { case 0: - wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), dataPtr, state, 0); + wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); return READ_LE_UINT32(wizh + 0x0); case 1: - return (_vm->findWrappedBlock(MKID_BE('RGBS'), dataPtr, state, 0) != NULL) ? 1 : 0; + return (_vm->findWrappedBlock(MKTAG('R','G','B','S'), dataPtr, state, 0) != NULL) ? 1 : 0; case 2: - return (_vm->findWrappedBlock(MKID_BE('RMAP'), dataPtr, state, 0) != NULL) ? 1 : 0; + return (_vm->findWrappedBlock(MKTAG('R','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0; case 3: - return (_vm->findWrappedBlock(MKID_BE('TRNS'), dataPtr, state, 0) != NULL) ? 1 : 0; + return (_vm->findWrappedBlock(MKTAG('T','R','N','S'), dataPtr, state, 0) != NULL) ? 1 : 0; case 4: - return (_vm->findWrappedBlock(MKID_BE('XMAP'), dataPtr, state, 0) != NULL) ? 1 : 0; + return (_vm->findWrappedBlock(MKTAG('X','M','A','P'), dataPtr, state, 0) != NULL) ? 1 : 0; default: error("getWizImageData: Unknown type %d", type); } @@ -2556,14 +2556,14 @@ int Wiz::getWizImageData(int resNum, int state, int type) { int Wiz::getWizImageStates(int resNum) { const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); - if (READ_BE_UINT32(dataPtr) == MKID_BE('MULT')) { + if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) { const byte *offs, *wrap; - wrap = _vm->findResource(MKID_BE('WRAP'), dataPtr); + wrap = _vm->findResource(MKTAG('W','R','A','P'), dataPtr); if (wrap == NULL) return 1; - offs = _vm->findResourceData(MKID_BE('OFFS'), wrap); + offs = _vm->findResourceData(MKTAG('O','F','F','S'), wrap); if (offs == NULL) return 1; @@ -2577,12 +2577,12 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags int ret = 0; uint8 *data = _vm->getResourceAddress(rtImage, resNum); assert(data); - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); int h = READ_LE_UINT32(wizh + 0x8); - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0); assert(wizd); if (x >= 0 && x < w && y >= 0 && y < h) { if (flags & kWIFFlipX) { @@ -2627,12 +2627,12 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) { uint16 color = 0; uint8 *data = _vm->getResourceAddress(rtImage, resNum); assert(data); - uint8 *wizh = _vm->findWrappedBlock(MKID_BE('WIZH'), data, state, 0); + uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); int w = READ_LE_UINT32(wizh + 0x4); int h = READ_LE_UINT32(wizh + 0x8); - uint8 *wizd = _vm->findWrappedBlock(MKID_BE('WIZD'), data, state, 0); + uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0); assert(wizd); switch (c) { case 0: @@ -2671,13 +2671,13 @@ int ScummEngine_v90he::computeWizHistogram(int resNum, int state, int x, int y, Common::Rect rCapt(x, y, w + 1, h + 1); uint8 *data = getResourceAddress(rtImage, resNum); assert(data); - uint8 *wizh = findWrappedBlock(MKID_BE('WIZH'), data, state, 0); + uint8 *wizh = findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); w = READ_LE_UINT32(wizh + 0x4); h = READ_LE_UINT32(wizh + 0x8); Common::Rect rWiz(w, h); - uint8 *wizd = findWrappedBlock(MKID_BE('WIZD'), data, state, 0); + uint8 *wizd = findWrappedBlock(MKTAG('W','I','Z','D'), data, state, 0); assert(wizd); if (rCapt.intersects(rWiz)) { rCapt.clip(rWiz); diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 6c626cdf4e..07fd99c809 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -150,22 +150,22 @@ bool IMuseInternal::isMT32(int sound) { tag = READ_BE_UINT32(ptr + 4); switch (tag) { - case MKID_BE('ADL '): - case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects - case MKID_BE('SPK '): + case MKTAG('A','D','L',' '): + case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects + case MKTAG('S','P','K',' '): return false; - case MKID_BE('AMI '): - case MKID_BE('ROL '): + case MKTAG('A','M','I',' '): + case MKTAG('R','O','L',' '): return true; - case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2 + case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2 return true; - case MKID_BE('GMD '): + case MKTAG('G','M','D',' '): return false; - case MKID_BE('MIDI'): // Occurs in Sam & Max + case MKTAG('M','I','D','I'): // Occurs in Sam & Max // HE games use Roland music if (ptr[12] == 'H' && ptr[13] == 'S') return true; @@ -197,20 +197,20 @@ bool IMuseInternal::isMIDI(int sound) { tag = READ_BE_UINT32(ptr + 4); switch (tag) { - case MKID_BE('ADL '): - case MKID_BE('ASFX'): // Special AD class for old AdLib sound effects - case MKID_BE('SPK '): + case MKTAG('A','D','L',' '): + case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects + case MKTAG('S','P','K',' '): return false; - case MKID_BE('AMI '): - case MKID_BE('ROL '): + case MKTAG('A','M','I',' '): + case MKTAG('R','O','L',' '): return true; - case MKID_BE('MAC '): // Occurs in the Mac version of FOA and MI2 + case MKTAG('M','A','C',' '): // Occurs in the Mac version of FOA and MI2 return true; - case MKID_BE('GMD '): - case MKID_BE('MIDI'): // Occurs in Sam & Max + case MKTAG('G','M','D',' '): + case MKTAG('M','I','D','I'): // Occurs in Sam & Max return true; } diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 516a0497fa..3831689def 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -31,6 +31,7 @@ #include "scumm/sound.h" #include "scumm/imuse_digi/dimuse.h" #include "scumm/imuse_digi/dimuse_bndmgr.h" +#include "scumm/imuse_digi/dimuse_codecs.h" #include "scumm/imuse_digi/dimuse_track.h" #include "audio/audiostream.h" diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp index f10f17f3d8..cb894d77cc 100644 --- a/engines/scumm/imuse_digi/dimuse_bndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_bndmgr.cpp @@ -28,6 +28,7 @@ #include "scumm/util.h" #include "scumm/file.h" #include "scumm/imuse_digi/dimuse_bndmgr.h" +#include "scumm/imuse_digi/dimuse_codecs.h" namespace Scumm { @@ -92,7 +93,7 @@ int BundleDirCache::matchFile(const char *filename) { error("BundleDirCache::matchFileFile() Can't find free slot for file bundle dir cache"); tag = file.readUint32BE(); - if (tag == MKID_BE('LB23')) + if (tag == MKTAG('L','B','2','3')) _budleDirCache[freeSlot].isCompressed = true; offset = file.readUint32BE(); @@ -112,7 +113,7 @@ int BundleDirCache::matchFile(const char *filename) { int32 z = 0; int32 z2; - if (tag == MKID_BE('LB23')) { + if (tag == MKTAG('L','B','2','3')) { file.read(_budleDirCache[freeSlot].bundleTable[i].filename, 24); } else { for (z2 = 0; z2 < 8; z2++) @@ -224,7 +225,7 @@ bool BundleMgr::loadCompTable(int32 index) { assert(_numCompItems > 0); _file->seek(8, SEEK_CUR); - if (tag != MKID_BE('COMP')) { + if (tag != MKTAG('C','O','M','P')) { error("BundleMgr::loadCompTable() Compressed sound %d (%s:%d) invalid (%s)", index, _file->getName(), _bundleTable[index].offset, tag2str(tag)); return false; } diff --git a/engines/scumm/imuse_digi/dimuse_bndmgr.h b/engines/scumm/imuse_digi/dimuse_bndmgr.h index a78697a854..bed1ac6549 100644 --- a/engines/scumm/imuse_digi/dimuse_bndmgr.h +++ b/engines/scumm/imuse_digi/dimuse_bndmgr.h @@ -107,14 +107,6 @@ public: int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **compFinal, int headerSize, bool headerOutside); }; -namespace BundleCodecs { - -uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size); -void initializeImcTables(); -int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize); - -} // End of namespace BundleCodecs - } // End of namespace Scumm #endif diff --git a/engines/scumm/imuse_digi/dimuse_codecs.cpp b/engines/scumm/imuse_digi/dimuse_codecs.cpp index 62a006c56b..fd9deb7b44 100644 --- a/engines/scumm/imuse_digi/dimuse_codecs.cpp +++ b/engines/scumm/imuse_digi/dimuse_codecs.cpp @@ -25,6 +25,9 @@ #include "common/scummsys.h" #include "common/endian.h" #include "common/util.h" +#include "scumm/imuse_digi/dimuse_codecs.h" + +#include "audio/decoders/adpcm_intern.h" namespace Scumm { @@ -59,23 +62,10 @@ uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size) { * varies the size of each "packet" between 2 and 7 bits. */ -static byte _imcTableEntryBitCount[89]; - -static const int16 imcTable[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493,10442,11487,12635,13899, - 15289,16818,18500,20350,22385,24623,27086,29794, - 32767 -}; +static byte *_destImcTable = NULL; +static uint32 *_destImcTable2 = NULL; +// This table is the "big brother" of Audio::ADPCMStream::_stepAdjustTable. static const byte imxOtherTable[6][64] = { { 0xFF, @@ -116,23 +106,47 @@ static const byte imxOtherTable[6][64] = { } }; +void releaseImcTables() { + free(_destImcTable); + free(_destImcTable2); +} + void initializeImcTables() { int pos; - for (pos = 0; pos < ARRAYSIZE(imcTable); ++pos) { - byte put = 0; - int32 tableValue = ((imcTable[pos] * 4) / 7) / 2; + if (!_destImcTable) _destImcTable = (byte *)calloc(89, sizeof(byte)); + if (!_destImcTable2) _destImcTable2 = (uint32 *)calloc(89 * 64, sizeof(uint32)); + + for (pos = 0; pos <= 88; ++pos) { + byte put = 1; + int32 tableValue = ((Audio::Ima_ADPCMStream::_imaTable[pos] * 4) / 7) / 2; while (tableValue != 0) { tableValue /= 2; put++; } - if (put < 2) { - put = 2; + if (put < 3) { + put = 3; + } + if (put > 8) { + put = 8; } - if (put > 7) { - put = 7; + _destImcTable[pos] = put - 1; + } + + for (int n = 0; n < 64; n++) { + for (pos = 0; pos <= 88; ++pos) { + int32 count = 32; + int32 put = 0; + int32 tableValue = Audio::Ima_ADPCMStream::_imaTable[pos]; + do { + if ((count & n) != 0) { + put += tableValue; + } + count /= 2; + tableValue /= 2; + } while (count != 0); + _destImcTable2[n + pos * 64] = put; } - _imcTableEntryBitCount[pos] = put; } } @@ -183,8 +197,128 @@ static int32 compDecode(byte *src, byte *dst) { } #undef NextBit +int32 decompressADPCM(byte *compInput, byte *compOutput, int channels) { + byte *src; + + // Decoder for the the IMA ADPCM variants used in COMI. + // Contrary to regular IMA ADPCM, this codec uses a variable + // bitsize for the encoded data. + + const int MAX_CHANNELS = 2; + int32 outputSamplesLeft; + int32 destPos; + int16 firstWord; + byte initialTablePos[MAX_CHANNELS] = {0, 0}; + int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7}; + int32 initialOutputWord[MAX_CHANNELS] = {0, 0}; + int32 totalBitOffset, curTablePos, outputWord; + byte *dst; + int i; + + // We only support mono and stereo + assert(channels == 1 || channels == 2); + + src = compInput; + dst = compOutput; + outputSamplesLeft = 0x1000; + + // Every data packet contains 0x2000 bytes of audio data + // when extracted. In order to encode bigger data sets, + // one has to split the data into multiple blocks. + // + // Every block starts with a 2 byte word. If that word is + // non-zero, it indicates the size of a block of raw audio + // data (not encoded) following it. That data we simply copy + // to the output buffer and the proceed by decoding the + // remaining data. + // + // If on the other hand the word is zero, then what follows + // are 7*channels bytes containing seed data for the decoder. + firstWord = READ_BE_UINT16(src); + src += 2; + if (firstWord != 0) { + // Copy raw data + memcpy(dst, src, firstWord); + dst += firstWord; + src += firstWord; + assert((firstWord & 1) == 0); + outputSamplesLeft -= firstWord / 2; + } else { + // Read the seed values for the decoder. + for (i = 0; i < channels; i++) { + initialTablePos[i] = *src; + src += 1; + initialimcTableEntry[i] = READ_BE_UINT32(src); + src += 4; + initialOutputWord[i] = READ_BE_UINT32(src); + src += 4; + } + } + + totalBitOffset = 0; + // The channels are encoded separately. + for (int chan = 0; chan < channels; chan++) { + // Read initial state (this makes it possible for the data stream + // to be split & spread across multiple data chunks. + curTablePos = initialTablePos[chan]; + //imcTableEntry = initialimcTableEntry[chan]; + outputWord = initialOutputWord[chan]; + + // We need to interleave the channels in the output; we achieve + // that by using a variables dest offset: + destPos = chan * 2; + + const int bound = (channels == 1) + ? outputSamplesLeft + : ((chan == 0) + ? (outputSamplesLeft+1) / 2 + : outputSamplesLeft / 2); + for (i = 0; i < bound; ++i) { + // Determine the size (in bits) of the next data packet + const int32 curTableEntryBitCount = _destImcTable[curTablePos]; + assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7); + + // Read the next data packet + const byte *readPos = src + (totalBitOffset >> 3); + const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7)); + const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount)); + + // Advance read position to the next data packet + totalBitOffset += curTableEntryBitCount; + + // Decode the data packet into a delta value for the output signal. + const byte signBitMask = (1 << (curTableEntryBitCount - 1)); + const byte dataBitMask = (signBitMask - 1); + const byte data = (packet & dataBitMask); + + const int32 tmpA = (data << (7 - curTableEntryBitCount)); + const int32 imcTableEntry = Audio::Ima_ADPCMStream::_imaTable[curTablePos] >> (curTableEntryBitCount - 1); + int32 delta = imcTableEntry + _destImcTable2[tmpA + (curTablePos * 64)]; + + // The topmost bit in the data packet tells is a sign bit + if ((packet & signBitMask) != 0) { + delta = -delta; + } + + // Accumulate the delta onto the output data + outputWord += delta; + + // Clip outputWord to 16 bit signed, and write it into the destination stream + outputWord = CLIP<int32>(outputWord, -0x8000, 0x7fff); + WRITE_BE_UINT16(dst + destPos, outputWord); + destPos += channels << 1; + + // Adjust the curTablePos + curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data]; + curTablePos = CLIP<int32>(curTablePos, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1); + } + } + + return 0x2000; +} + int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize) { - int32 outputSize, channels; + int32 outputSize; int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z; byte *src, *t_table, *p, *ptr; byte t_tmp1, t_tmp2; @@ -506,132 +640,7 @@ int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inpu case 13: case 15: - if (codec == 13) { - channels = 1; - } else { - channels = 2; - } - - { - // Decoder for the the IMA ADPCM variants used in COMI. - // Contrary to regular IMA ADPCM, this codec uses a variable - // bitsize for the encoded data. - - const int MAX_CHANNELS = 2; - int32 outputSamplesLeft; - int32 destPos; - int16 firstWord; - byte initialTablePos[MAX_CHANNELS] = {0, 0}; - //int32 initialimcTableEntry[MAX_CHANNELS] = {7, 7}; - int32 initialOutputWord[MAX_CHANNELS] = {0, 0}; - int32 totalBitOffset, curTablePos, outputWord; - byte *dst; - int i; - - // We only support mono and stereo - assert(channels == 1 || channels == 2); - - src = compInput; - dst = compOutput; - outputSize = 0x2000; - outputSamplesLeft = 0x1000; - - // Every data packet contains 0x2000 bytes of audio data - // when extracted. In order to encode bigger data sets, - // one has to split the data into multiple blocks. - // - // Every block starts with a 2 byte word. If that word is - // non-zero, it indicates the size of a block of raw audio - // data (not encoded) following it. That data we simply copy - // to the output buffer and the proceed by decoding the - // remaining data. - // - // If on the other hand the word is zero, then what follows - // are 7*channels bytes containing seed data for the decoder. - firstWord = READ_BE_UINT16(src); - src += 2; - if (firstWord != 0) { - // Copy raw data - memcpy(dst, src, firstWord); - dst += firstWord; - src += firstWord; - assert((firstWord & 1) == 0); - outputSamplesLeft -= firstWord / 2; - } else { - // Read the seed values for the decoder. - for (i = 0; i < channels; i++) { - initialTablePos[i] = *src; - src += 1; - //initialimcTableEntry[i] = READ_BE_UINT32(src); - src += 4; - initialOutputWord[i] = READ_BE_UINT32(src); - src += 4; - } - } - - totalBitOffset = 0; - // The channels are encoded separately. - for (int chan = 0; chan < channels; chan++) { - // Read initial state (this makes it possible for the data stream - // to be split & spread across multiple data chunks. - curTablePos = initialTablePos[chan]; - //imcTableEntry = initialimcTableEntry[chan]; - outputWord = initialOutputWord[chan]; - - // We need to interleave the channels in the output; we achieve - // that by using a variables dest offset: - destPos = chan * 2; - - const int bound = (channels == 1) - ? outputSamplesLeft - : ((chan == 0) - ? (outputSamplesLeft+1) / 2 - : outputSamplesLeft / 2); - for (i = 0; i < bound; ++i) { - // Determine the size (in bits) of the next data packet - const int32 curTableEntryBitCount = _imcTableEntryBitCount[curTablePos]; - assert(2 <= curTableEntryBitCount && curTableEntryBitCount <= 7); - - // Read the next data packet - const byte *readPos = src + (totalBitOffset >> 3); - const uint16 readWord = (uint16)(READ_BE_UINT16(readPos) << (totalBitOffset & 7)); - const byte packet = (byte)(readWord >> (16 - curTableEntryBitCount)); - - // Advance read position to the next data packet - totalBitOffset += curTableEntryBitCount; - - // Decode the data packet into a delta value for the output signal. - const byte signBitMask = (1 << (curTableEntryBitCount - 1)); - const byte dataBitMask = (signBitMask - 1); - const byte data = (packet & dataBitMask); - - int32 delta = imcTable[curTablePos] * (2 * data + 1) >> (curTableEntryBitCount - 1); - - // The topmost bit in the data packet tells is a sign bit - if ((packet & signBitMask) != 0) { - delta = -delta; - } - - // Accumulate the delta onto the output data - outputWord += delta; - - // Clip outputWord to 16 bit signed, and write it into the destination stream - if (outputWord > 0x7fff) - outputWord = 0x7fff; - if (outputWord < -0x8000) - outputWord = -0x8000; - WRITE_BE_UINT16(dst + destPos, outputWord); - destPos += channels << 1; - - // Adjust the curTablePos - curTablePos += (int8)imxOtherTable[curTableEntryBitCount - 2][data]; - if (curTablePos < 0) - curTablePos = 0; - else if (curTablePos >= ARRAYSIZE(imcTable)) - curTablePos = ARRAYSIZE(imcTable) - 1; - } - } - } + outputSize = decompressADPCM(compInput, compOutput, (codec == 13) ? 1 : 2); break; default: diff --git a/engines/scumm/imuse_digi/dimuse_codecs.h b/engines/scumm/imuse_digi/dimuse_codecs.h new file mode 100644 index 0000000000..71fd24c3ac --- /dev/null +++ b/engines/scumm/imuse_digi/dimuse_codecs.h @@ -0,0 +1,44 @@ +/* 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. + * + * $URL$ + * $Id$ + */ + +#ifndef SCUMM_IMUSE_DIGI_CODECS_H +#define SCUMM_IMUSE_DIGI_CODECS_H + +#include "common/scummsys.h" + +namespace Scumm { + +namespace BundleCodecs { + +uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size); +int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inputSize); + +void initializeImcTables(); +void releaseImcTables(); + +} // End of namespace BundleCodecs + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp index 00074a951a..2cd90c4f2b 100644 --- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp +++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp @@ -34,8 +34,9 @@ #include "scumm/scumm.h" #include "scumm/util.h" #include "scumm/imuse_digi/dimuse.h" -#include "scumm/imuse_digi/dimuse_sndmgr.h" #include "scumm/imuse_digi/dimuse_bndmgr.h" +#include "scumm/imuse_digi/dimuse_codecs.h" +#include "scumm/imuse_digi/dimuse_sndmgr.h" namespace Scumm { @@ -56,6 +57,7 @@ ImuseDigiSndMgr::~ImuseDigiSndMgr() { } delete _cacheBundleDir; + BundleCodecs::releaseImcTables(); } void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs, int &numMarkers) { @@ -65,32 +67,32 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i do { tag = READ_BE_UINT32(ptr); ptr += 4; switch (tag) { - case MKID_BE('STOP'): - case MKID_BE('FRMT'): - case MKID_BE('DATA'): + case MKTAG('S','T','O','P'): + case MKTAG('F','R','M','T'): + case MKTAG('D','A','T','A'): size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): if (!scumm_stricmp((const char *)(ptr + 8), "exit")) numMarkers++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('REGN'): + case MKTAG('R','E','G','N'): numRegions++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('JUMP'): + case MKTAG('J','U','M','P'): numJumps++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('SYNC'): + case MKTAG('S','Y','N','C'): numSyncs++; size = READ_BE_UINT32(ptr); ptr += size + 4; break; default: error("ImuseDigiSndMgr::countElements() Unknown sfx header '%s'", tag2str(tag)); } - } while (tag != MKID_BE('DATA')); + } while (tag != MKTAG('D','A','T','A')); } void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, SoundDesc *sound, int32 offset, int32 size) { @@ -98,7 +100,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou file->seek(offset, SEEK_SET); uint32 tag = file->readUint32BE(); - assert(tag == MKID_BE('RMAP')); + assert(tag == MKTAG('R','M','A','P')); int32 version = file->readUint32BE(); if (version != 3) { if (version == 2) { @@ -153,7 +155,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::SeekableReadStream *file, Sou } void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { - if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) { + if (READ_BE_UINT32(ptr) == MKTAG('C','r','e','a')) { bool quit = false; int len; @@ -222,7 +224,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { } offset += len; } - } else if (READ_BE_UINT32(ptr) == MKID_BE('iMUS')) { + } else if (READ_BE_UINT32(ptr) == MKTAG('i','M','U','S')) { uint32 tag; int32 size = 0; byte *s_ptr = ptr; @@ -250,13 +252,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { do { tag = READ_BE_UINT32(ptr); ptr += 4; switch (tag) { - case MKID_BE('FRMT'): + case MKTAG('F','R','M','T'): ptr += 12; sound->bits = READ_BE_UINT32(ptr); ptr += 4; sound->freq = READ_BE_UINT32(ptr); ptr += 4; sound->channels = READ_BE_UINT32(ptr); ptr += 4; break; - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): if (!scumm_stricmp((const char *)(ptr + 8), "exit")) { sound->marker[curIndexMarker].pos = READ_BE_UINT32(ptr + 4); sound->marker[curIndexMarker].length = strlen((const char *)(ptr + 8)) + 1; @@ -267,16 +269,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { } size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('STOP'): + case MKTAG('S','T','O','P'): size = READ_BE_UINT32(ptr); ptr += size + 4; break; - case MKID_BE('REGN'): + case MKTAG('R','E','G','N'): ptr += 4; sound->region[curIndexRegion].offset = READ_BE_UINT32(ptr); ptr += 4; sound->region[curIndexRegion].length = READ_BE_UINT32(ptr); ptr += 4; curIndexRegion++; break; - case MKID_BE('JUMP'): + case MKTAG('J','U','M','P'): ptr += 4; sound->jump[curIndexJump].offset = READ_BE_UINT32(ptr); ptr += 4; sound->jump[curIndexJump].dest = READ_BE_UINT32(ptr); ptr += 4; @@ -284,7 +286,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { sound->jump[curIndexJump].fadeDelay = READ_BE_UINT32(ptr); ptr += 4; curIndexJump++; break; - case MKID_BE('SYNC'): + case MKTAG('S','Y','N','C'): size = READ_BE_UINT32(ptr); ptr += 4; sound->sync[curIndexSync].size = size; sound->sync[curIndexSync].ptr = new byte[size]; @@ -293,13 +295,13 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) { curIndexSync++; ptr += size; break; - case MKID_BE('DATA'): + case MKTAG('D','A','T','A'): ptr += 4; break; default: error("ImuseDigiSndMgr::prepareSound(%d/%s) Unknown sfx header '%s'", sound->soundId, sound->name, tag2str(tag)); } - } while (tag != MKID_BE('DATA')); + } while (tag != MKTAG('D','A','T','A')); sound->offsetData = ptr - s_ptr; } else { error("ImuseDigiSndMgr::prepareSound(): Unknown sound format"); diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp index f2e50382b3..a82c0ae408 100644 --- a/engines/scumm/insane/insane.cpp +++ b/engines/scumm/insane/insane.cpp @@ -1413,7 +1413,7 @@ int32 Insane::smush_setupSanWithFlu(const char *filename, int32 setupsan2, int32 _smush_setupsan1 = setupsan1; /* skip FLUP marker */ - if (READ_BE_UINT32(fluPtr) == MKID_BE('FLUP')) + if (READ_BE_UINT32(fluPtr) == MKTAG('F','L','U','P')) tmp += 8; _smush_setupsan2 = setupsan2; diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp index d56017c6f5..7f250e45e0 100644 --- a/engines/scumm/nut_renderer.cpp +++ b/engines/scumm/nut_renderer.cpp @@ -95,7 +95,7 @@ void NutRenderer::loadFont(const char *filename) { } uint32 tag = file.readUint32BE(); - if (tag != MKID_BE('ANIM')) { + if (tag != MKTAG('A','N','I','M')) { error("NutRenderer::loadFont() there is no ANIM chunk in font header"); } @@ -104,7 +104,7 @@ void NutRenderer::loadFont(const char *filename) { file.read(dataSrc, length); file.close(); - if (READ_BE_UINT32(dataSrc) != MKID_BE('AHDR')) { + if (READ_BE_UINT32(dataSrc) != MKTAG('A','H','D','R')) { error("NutRenderer::loadFont() there is no AHDR chunk in font header"); } @@ -142,12 +142,12 @@ void NutRenderer::loadFont(const char *filename) { offset = 0; for (l = 0; l < _numChars; l++) { offset += READ_BE_UINT32(dataSrc + offset + 4) + 8; - if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FRME')) { + if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','R','M','E')) { error("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset); break; } offset += 8; - if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FOBJ')) { + if (READ_BE_UINT32(dataSrc + offset) != MKTAG('F','O','B','J')) { error("NutRenderer::loadFont(%s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, l, offset); break; } diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index c44043ca81..c2547f74f4 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -416,7 +416,7 @@ void ScummEngine::getObjectXYPos(int object, int &x, int &y, int &dir) { debug(0, "getObjectXYPos: Can't find object %d", object); return; } - imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr); + imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr); assert(imhd); if (_game.version == 8) { switch (FROM_LE_32(imhd->v8.version)) { @@ -655,7 +655,7 @@ void ScummEngine::drawObject(int obj, int arg) { flags |= Gdi::dbDrawMaskOnAll; #ifdef ENABLE_HE - if (_game.heversion >= 70 && findResource(MKID_BE('SMAP'), ptr) == NULL) + if (_game.heversion >= 70 && findResource(MKTAG('S','M','A','P'), ptr) == NULL) _gdi->drawBMAPObject(ptr, &_virtscr[kMainVirtScreen], obj, od.x_pos, od.y_pos, od.width, od.height); else #endif @@ -762,12 +762,12 @@ void ScummEngine::resetRoomObjects() { for (i = 0; i < _numObjectsInRoom; i++) { od = &_objs[findLocalObjectSlot()]; - ptr = obcds.findNext(MKID_BE('OBCD')); + ptr = obcds.findNext(MKTAG('O','B','C','D')); if (ptr == NULL) error("Room %d missing object code block(s)", _roomResource); od->OBCDoffset = ptr - rootptr; - cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), ptr); + cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), ptr); if (_game.version >= 7) od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id)); @@ -779,7 +779,7 @@ void ScummEngine::resetRoomObjects() { if (_dumpScripts) { char buf[32]; sprintf(buf, "roomobj-%d-", _roomResource); - ptr = findResource(MKID_BE('VERB'), ptr); + ptr = findResource(MKTAG('V','E','R','B'), ptr); dumpResource(buf, od->obj_nr, ptr); } @@ -788,7 +788,7 @@ void ScummEngine::resetRoomObjects() { searchptr = room; ResourceIterator obims(room, false); for (i = 0; i < _numObjectsInRoom; i++) { - ptr = obims.findNext(MKID_BE('OBIM')); + ptr = obims.findNext(MKTAG('O','B','I','M')); if (ptr == NULL) error("Room %d missing image blocks(s)", _roomResource); @@ -870,7 +870,7 @@ void ScummEngine_v4::resetRoomObjects() { for (i = 0; i < _numObjectsInRoom; i++) { od = &_objs[findLocalObjectSlot()]; - ptr = obcds.findNext(MKID_BE('OBCD')); + ptr = obcds.findNext(MKTAG('O','B','C','D')); if (ptr == NULL) error("Room %d missing object code block(s)", _roomResource); @@ -887,7 +887,7 @@ void ScummEngine_v4::resetRoomObjects() { for (i = 0; i < _numObjectsInRoom; i++) { // In the PC Engine version of Loom, there aren't image blocks // for all objects. - ptr = obims.findNext(MKID_BE('OBIM')); + ptr = obims.findNext(MKTAG('O','B','I','M')); if (ptr == NULL) break; @@ -991,11 +991,11 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte * searchptr = room; } - cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), searchptr + od->OBCDoffset); + cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), searchptr + od->OBCDoffset); if (cdhd == NULL) error("Room %d missing CDHD blocks(s)", _roomResource); if (od->OBIMoffset) - imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), room + od->OBIMoffset); + imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), room + od->OBIMoffset); od->flags = Gdi::dbAllowMaskOr; @@ -1194,7 +1194,7 @@ const byte *ScummEngine::getObjOrActorName(int obj) { return (objptr + offset); } - return findResourceData(MKID_BE('OBNA'), objptr); + return findResourceData(MKTAG('O','B','N','A'), objptr); } void ScummEngine::setObjectName(int obj) { @@ -1278,7 +1278,7 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) { if (od.fl_object_index) { ptr = getResourceAddress(rtFlObject, od.fl_object_index); - ptr = findResource(MKID_BE('OBIM'), ptr); + ptr = findResource(MKTAG('O','B','I','M'), ptr); } else { ptr = getResourceAddress(rtRoom, _roomResource); if (ptr) @@ -1288,23 +1288,23 @@ const byte *ScummEngine::getOBIMFromObjectData(const ObjectData &od) { } static const uint32 IMxx_tags[] = { - MKID_BE('IM00'), - MKID_BE('IM01'), - MKID_BE('IM02'), - MKID_BE('IM03'), - MKID_BE('IM04'), - MKID_BE('IM05'), - MKID_BE('IM06'), - MKID_BE('IM07'), - MKID_BE('IM08'), - MKID_BE('IM09'), - MKID_BE('IM0A'), - MKID_BE('IM0B'), - MKID_BE('IM0C'), - MKID_BE('IM0D'), - MKID_BE('IM0E'), - MKID_BE('IM0F'), - MKID_BE('IM10') + MKTAG('I','M','0','0'), + MKTAG('I','M','0','1'), + MKTAG('I','M','0','2'), + MKTAG('I','M','0','3'), + MKTAG('I','M','0','4'), + MKTAG('I','M','0','5'), + MKTAG('I','M','0','6'), + MKTAG('I','M','0','7'), + MKTAG('I','M','0','8'), + MKTAG('I','M','0','9'), + MKTAG('I','M','0','A'), + MKTAG('I','M','0','B'), + MKTAG('I','M','0','C'), + MKTAG('I','M','0','D'), + MKTAG('I','M','0','E'), + MKTAG('I','M','0','F'), + MKTAG('I','M','1','0') }; const byte *ScummEngine::getObjectImage(const byte *ptr, int state) { @@ -1317,15 +1317,15 @@ const byte *ScummEngine::getObjectImage(const byte *ptr, int state) { // The OBIM contains an IMAG, which in turn contains a WRAP, which contains // an OFFS chunk and multiple BOMP/SMAP chunks. To find the right BOMP/SMAP, // we use the offsets in the OFFS chunk, - ptr = findResource(MKID_BE('IMAG'), ptr); + ptr = findResource(MKTAG('I','M','A','G'), ptr); if (!ptr) return 0; - ptr = findResource(MKID_BE('WRAP'), ptr); + ptr = findResource(MKTAG('W','R','A','P'), ptr); if (!ptr) return 0; - ptr = findResource(MKID_BE('OFFS'), ptr); + ptr = findResource(MKTAG('O','F','F','S'), ptr); if (!ptr) return 0; @@ -1348,7 +1348,7 @@ int ScummEngine::getObjectImageCount(int object) { return 0; ptr = getOBIMFromObjectData(_objs[objnum]); - imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), ptr); + imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), ptr); if (!imhd) return 0; @@ -1365,7 +1365,7 @@ int ScummEngine::getObjectImageCount(int object) { int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) { // In V8, IMHD has no obj_id, but rather a name string. We map the name // back to an object id using a table derived from the DOBJ resource. - const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim); + const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim); ObjectNameId *found = (ObjectNameId *)bsearch(imhd->v8.name, _objectIDMap, _objectIDMapSize, sizeof(ObjectNameId), (int (*)(const void*, const void*))strcmp); assert(found); @@ -1373,7 +1373,7 @@ int ScummEngine_v8::getObjectIdFromOBIM(const byte *obim) { } int ScummEngine_v7::getObjectIdFromOBIM(const byte *obim) { - const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim); + const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim); return READ_LE_UINT16(&imhd->v7.obj_id); } #endif @@ -1382,7 +1382,7 @@ int ScummEngine::getObjectIdFromOBIM(const byte *obim) { if (_game.features & GF_SMALL_HEADER) return READ_LE_UINT16(obim + 6); - const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim); + const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim); return READ_LE_UINT16(&imhd->old.obj_id); } @@ -1400,7 +1400,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, if (findWhat & foCodeHeader) { fo->obcd = obcdptr = getOBCDFromObject(id); assert(obcdptr); - fo->cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr); + fo->cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr); } if (findWhat & foImageHeader) { fo->obim = obimptr = getOBIMFromObjectData(_objs[id2]); @@ -1416,7 +1416,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, if (_game.features & GF_OLD_BUNDLE) { numobj = roomptr[20]; } else { - const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr); + const RoomHeader *roomhdr = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr); if (_game.version == 8) numobj = READ_LE_UINT32(&(roomhdr->v8.numObjects)); @@ -1467,10 +1467,10 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, assert(searchptr); ResourceIterator obcds(searchptr, (_game.features & GF_SMALL_HEADER) != 0); for (i = 0; i < numobj; i++) { - obcdptr = obcds.findNext(MKID_BE('OBCD')); + obcdptr = obcds.findNext(MKTAG('O','B','C','D')); if (obcdptr == NULL) error("findObjectInRoom: Not enough code blocks in room %d", room); - cdhd = (const CodeHeader *)findResourceData(MKID_BE('CDHD'), obcdptr); + cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), obcdptr); if (_game.features & GF_SMALL_HEADER) id2 = READ_LE_UINT16(obcdptr + 6); @@ -1495,7 +1495,7 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, if (findWhat & foImageHeader) { ResourceIterator obims(roomptr, (_game.features & GF_SMALL_HEADER) != 0); for (i = 0; i < numobj; i++) { - obimptr = obims.findNext(MKID_BE('OBIM')); + obimptr = obims.findNext(MKTAG('O','B','I','M')); if (obimptr == NULL) error("findObjectInRoom: Not enough image blocks in room %d", room); obim_id = getObjectIdFromOBIM(obimptr); @@ -1699,7 +1699,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) { if (!img) img = getObjectImage(ptr, 1); // Backward compatibility with samnmax blast objects assert(img); - bomp = findResourceData(MKID_BE('BOMP'), img); + bomp = findResourceData(MKTAG('B','O','M','P'), img); } if (!bomp) @@ -1843,7 +1843,7 @@ void ScummEngine::loadFlObject(uint object, uint room) { char buf[32]; const byte *ptr = foir.obcd; sprintf(buf, "roomobj-%d-", room); - ptr = findResource(MKID_BE('VERB'), ptr); + ptr = findResource(MKTAG('V','E','R','B'), ptr); dumpResource(buf, object, ptr); } @@ -1869,7 +1869,7 @@ void ScummEngine::loadFlObject(uint object, uint room) { assert(flob); // Copy object code + object image to floating object - WRITE_UINT32(flob, MKID_BE('FLOB')); + WRITE_UINT32(flob, MKTAG('F','L','O','B')); WRITE_BE_UINT32(flob + 4, flob_size); memcpy(flob + 8, foir.obcd, obcd_size); memcpy(flob + 8 + obcd_size, foir.obim, obim_size); diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index 18784151b7..e81212fec8 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -1029,7 +1029,7 @@ void ScummEngine::setCurrentPalette(int palindex) { void ScummEngine::setRoomPalette(int palindex, int room) { const byte *roomptr = getResourceAddress(rtRoom, room); assert(roomptr); - const byte *pals = findResource(MKID_BE('PALS'), roomptr); + const byte *pals = findResource(MKTAG('P','A','L','S'), roomptr); assert(pals); const byte *rgbs = findPalInPals(pals, palindex); assert(rgbs); @@ -1040,11 +1040,11 @@ const byte *ScummEngine::findPalInPals(const byte *pal, int idx) { const byte *offs; uint32 size; - pal = findResource(MKID_BE('WRAP'), pal); + pal = findResource(MKTAG('W','R','A','P'), pal); if (pal == NULL) return NULL; - offs = findResourceData(MKID_BE('OFFS'), pal); + offs = findResourceData(MKTAG('O','F','F','S'), pal); if (offs == NULL) return NULL; diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp index 06f97fd671..8922ff1730 100644 --- a/engines/scumm/player_towns.cpp +++ b/engines/scumm/player_towns.cpp @@ -622,7 +622,7 @@ int Player_Towns_v2::getSoundStatus(int sound) const { void Player_Towns_v2::startSound(int sound) { uint8 *ptr = _vm->getResourceAddress(rtSound, sound); - if (READ_BE_UINT32(ptr) == MKID_BE('TOWS')) { + if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) { _soundOverride[sound].type = 7; uint8 velo = _soundOverride[sound].velo ? _soundOverride[sound].velo - 1: (ptr[10] + ptr[11] + 1) >> 1; uint8 pan = _soundOverride[sound].pan ? _soundOverride[sound].pan - 1 : 64; @@ -630,7 +630,7 @@ void Player_Towns_v2::startSound(int sound) { _soundOverride[sound].velo = _soundOverride[sound].pan = 0; playPcmTrack(sound, ptr + 8, velo, pan, ptr[52], pri); - } else if (READ_BE_UINT32(ptr) == MKID_BE('SBL ')) { + } else if (READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) { _soundOverride[sound].type = 5; playVocTrack(ptr + 27); @@ -680,7 +680,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) { case 258: if (_soundOverride[args[1]].type == 0) { ptr = _vm->getResourceAddress(rtSound, args[1]); - if (READ_BE_UINT32(ptr) == MKID_BE('TOWS')) + if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) _soundOverride[args[1]].type = 7; } if (_soundOverride[args[1]].type == 7) { @@ -692,7 +692,7 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) { case 259: if (_soundOverride[args[1]].type == 0) { ptr = _vm->getResourceAddress(rtSound, args[1]); - if (READ_BE_UINT32(ptr) == MKID_BE('TOWS')) + if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) _soundOverride[args[1]].type = 7; } if (_soundOverride[args[1]].type == 7) { diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index 5bc643a5d1..c872a83d14 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -259,26 +259,26 @@ void ScummEngine::readIndexFile() { if (_fileHandle->eos() || _fileHandle->err()) break; switch (blocktype) { - case MKID_BE('DOBJ'): + case MKTAG('D','O','B','J'): _numGlobalObjects = _fileHandle->readUint16LE(); itemsize -= 2; break; - case MKID_BE('DROO'): + case MKTAG('D','R','O','O'): _numRooms = _fileHandle->readUint16LE(); itemsize -= 2; break; - case MKID_BE('DSCR'): + case MKTAG('D','S','C','R'): _numScripts = _fileHandle->readUint16LE(); itemsize -= 2; break; - case MKID_BE('DCOS'): + case MKTAG('D','C','O','S'): _numCostumes = _fileHandle->readUint16LE(); itemsize -= 2; break; - case MKID_BE('DSOU'): + case MKTAG('D','S','O','U'): _numSounds = _fileHandle->readUint16LE(); itemsize -= 2; break; @@ -351,7 +351,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) { int num; char *ptr; switch (blocktype) { - case MKID_BE('ANAM'): // Used by: The Dig, FT + case MKTAG('A','N','A','M'): // Used by: The Dig, FT debug(9, "found ANAM block, reading audio names"); num = _fileHandle->readUint16LE(); ptr = (char*)malloc(num * 9); @@ -359,7 +359,7 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) { _imuseDigital->setAudioNames(num, ptr); break; - case MKID_BE('DRSC'): // Used by: COMI + case MKTAG('D','R','S','C'): // Used by: COMI readResTypeList(rtRoomScripts); break; @@ -372,37 +372,37 @@ void ScummEngine_v7::readIndexBlock(uint32 blocktype, uint32 itemsize) { void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) { int i; switch (blocktype) { - case MKID_BE('DIRI'): + case MKTAG('D','I','R','I'): readResTypeList(rtRoomImage); break; - case MKID_BE('DIRM'): + case MKTAG('D','I','R','M'): readResTypeList(rtImage); break; - case MKID_BE('DIRT'): + case MKTAG('D','I','R','T'): readResTypeList(rtTalkie); break; - case MKID_BE('DLFL'): + case MKTAG('D','L','F','L'): i = _fileHandle->readUint16LE(); _fileHandle->seek(-2, SEEK_CUR); _heV7RoomOffsets = (byte *)calloc(2 + (i * 4), 1); _fileHandle->read(_heV7RoomOffsets, (2 + (i * 4)) ); break; - case MKID_BE('DISK'): + case MKTAG('D','I','S','K'): i = _fileHandle->readUint16LE(); _heV7DiskOffsets = (byte *)calloc(i, 1); _fileHandle->read(_heV7DiskOffsets, i); break; - case MKID_BE('SVER'): + case MKTAG('S','V','E','R'): // Index version number _fileHandle->seek(itemsize - 8, SEEK_CUR); break; - case MKID_BE('INIB'): + case MKTAG('I','N','I','B'): _fileHandle->seek(itemsize - 8, SEEK_CUR); debug(2, "INIB index block not yet handled, skipping"); break; @@ -415,17 +415,17 @@ void ScummEngine_v70he::readIndexBlock(uint32 blocktype, uint32 itemsize) { void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) { int i; switch (blocktype) { - case MKID_BE('DCHR'): - case MKID_BE('DIRF'): + case MKTAG('D','C','H','R'): + case MKTAG('D','I','R','F'): readResTypeList(rtCharset); break; - case MKID_BE('DOBJ'): + case MKTAG('D','O','B','J'): debug(9, "found DOBJ block, reading object table"); readGlobalObjects(); break; - case MKID_BE('RNAM'): + case MKTAG('R','N','A','M'): // Names of rooms. Maybe we should put them into a table, for use by the debugger? if (_game.heversion >= 80) { for (int room; (room = _fileHandle->readUint16LE()); ) { @@ -449,32 +449,32 @@ void ScummEngine::readIndexBlock(uint32 blocktype, uint32 itemsize) { } break; - case MKID_BE('DROO'): - case MKID_BE('DIRR'): + case MKTAG('D','R','O','O'): + case MKTAG('D','I','R','R'): readResTypeList(rtRoom); break; - case MKID_BE('DSCR'): - case MKID_BE('DIRS'): + case MKTAG('D','S','C','R'): + case MKTAG('D','I','R','S'): readResTypeList(rtScript); break; - case MKID_BE('DCOS'): - case MKID_BE('DIRC'): + case MKTAG('D','C','O','S'): + case MKTAG('D','I','R','C'): readResTypeList(rtCostume); break; - case MKID_BE('MAXS'): + case MKTAG('M','A','X','S'): readMAXS(itemsize); allocateArrays(); break; - case MKID_BE('DIRN'): - case MKID_BE('DSOU'): + case MKTAG('D','I','R','N'): + case MKTAG('D','S','O','U'): readResTypeList(rtSound); break; - case MKID_BE('AARY'): + case MKTAG('A','A','R','Y'): readArrayFromIndexFile(); break; @@ -1287,14 +1287,14 @@ void ScummEngine::allocateArrays() { _arraySlot = (byte *)calloc(_numArray, 1); } - _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKID_BE('AKOS') : MKID_BE('COST'), + _res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKTAG('A','K','O','S') : MKTAG('C','O','S','T'), _numCostumes, "costume", 1); - _res->allocResTypeData(rtRoom, MKID_BE('ROOM'), _numRooms, "room", 1); - _res->allocResTypeData(rtRoomImage, MKID_BE('RMIM'), _numRooms, "room image", 1); - _res->allocResTypeData(rtRoomScripts, MKID_BE('RMSC'), _numRooms, "room script", 1); - _res->allocResTypeData(rtSound, MKID_BE('SOUN'), _numSounds, "sound", 2); - _res->allocResTypeData(rtScript, MKID_BE('SCRP'), _numScripts, "script", 1); - _res->allocResTypeData(rtCharset, MKID_BE('CHAR'), _numCharsets, "charset", 1); + _res->allocResTypeData(rtRoom, MKTAG('R','O','O','M'), _numRooms, "room", 1); + _res->allocResTypeData(rtRoomImage, MKTAG('R','M','I','M'), _numRooms, "room image", 1); + _res->allocResTypeData(rtRoomScripts, MKTAG('R','M','S','C'), _numRooms, "room script", 1); + _res->allocResTypeData(rtSound, MKTAG('S','O','U','N'), _numSounds, "sound", 2); + _res->allocResTypeData(rtScript, MKTAG('S','C','R','P'), _numScripts, "script", 1); + _res->allocResTypeData(rtCharset, MKTAG('C','H','A','R'), _numCharsets, "charset", 1); _res->allocResTypeData(rtObjectName, 0, _numNewNames, "new name", 0); _res->allocResTypeData(rtInventory, 0, _numInventory, "inventory", 0); _res->allocResTypeData(rtTemp, 0, 10, "temp", 0); @@ -1304,8 +1304,8 @@ void ScummEngine::allocateArrays() { _res->allocResTypeData(rtString, 0, _numArray, "array", 0); _res->allocResTypeData(rtFlObject, 0, _numFlObject, "flobject", 0); _res->allocResTypeData(rtMatrix, 0, 10, "boxes", 0); - _res->allocResTypeData(rtImage, MKID_BE('AWIZ'), _numImages, "images", 1); - _res->allocResTypeData(rtTalkie, MKID_BE('TLKE'), _numTalkies, "talkie", 1); + _res->allocResTypeData(rtImage, MKTAG('A','W','I','Z'), _numImages, "images", 1); + _res->allocResTypeData(rtTalkie, MKTAG('T','L','K','E'), _numTalkies, "talkie", 1); } void ScummEngine_v70he::allocateArrays() { @@ -1464,35 +1464,35 @@ const byte *findResourceSmall(uint32 tag, const byte *searchin) { uint16 newTag2Old(uint32 newTag) { switch (newTag) { - case (MKID_BE('RMHD')): + case (MKTAG('R','M','H','D')): return (0x4448); // HD - case (MKID_BE('IM00')): + case (MKTAG('I','M','0','0')): return (0x4D42); // BM - case (MKID_BE('EXCD')): + case (MKTAG('E','X','C','D')): return (0x5845); // EX - case (MKID_BE('ENCD')): + case (MKTAG('E','N','C','D')): return (0x4E45); // EN - case (MKID_BE('SCAL')): + case (MKTAG('S','C','A','L')): return (0x4153); // SA - case (MKID_BE('LSCR')): + case (MKTAG('L','S','C','R')): return (0x534C); // LS - case (MKID_BE('OBCD')): + case (MKTAG('O','B','C','D')): return (0x434F); // OC - case (MKID_BE('OBIM')): + case (MKTAG('O','B','I','M')): return (0x494F); // OI - case (MKID_BE('SMAP')): + case (MKTAG('S','M','A','P')): return (0x4D42); // BM - case (MKID_BE('CLUT')): + case (MKTAG('C','L','U','T')): return (0x4150); // PA - case (MKID_BE('BOXD')): + case (MKTAG('B','O','X','D')): return (0x5842); // BX - case (MKID_BE('CYCL')): + case (MKTAG('C','Y','C','L')): return (0x4343); // CC - case (MKID_BE('EPAL')): + case (MKTAG('E','P','A','L')): return (0x5053); // SP - case (MKID_BE('TILE')): + case (MKTAG('T','I','L','E')): return (0x4C54); // TL - case (MKID_BE('ZP00')): + case (MKTAG('Z','P','0','0')): return (0x505A); // ZP default: return (0); diff --git a/engines/scumm/room.cpp b/engines/scumm/room.cpp index 58b6cdb105..06fa0f2c39 100644 --- a/engines/scumm/room.cpp +++ b/engines/scumm/room.cpp @@ -264,7 +264,7 @@ void ScummEngine::setupRoomSubBlocks() { // // Determine the room dimensions (width/height) // - rmhd = (const RoomHeader *)findResourceData(MKID_BE('RMHD'), roomptr); + rmhd = (const RoomHeader *)findResourceData(MKTAG('R','M','H','D'), roomptr); if (_game.version == 8) { _roomWidth = READ_LE_UINT32(&(rmhd->v8.width)); @@ -286,18 +286,18 @@ void ScummEngine::setupRoomSubBlocks() { if (_game.version == 8) { _IM00_offs = getObjectImage(roomptr, 1) - roomptr; } else if (_game.features & GF_SMALL_HEADER) { - _IM00_offs = findResourceData(MKID_BE('IM00'), roomptr) - roomptr; + _IM00_offs = findResourceData(MKTAG('I','M','0','0'), roomptr) - roomptr; } else if (_game.heversion >= 70) { byte *roomImagePtr = getResourceAddress(rtRoomImage, _roomResource); - _IM00_offs = findResource(MKID_BE('IM00'), roomImagePtr) - roomImagePtr; + _IM00_offs = findResource(MKTAG('I','M','0','0'), roomImagePtr) - roomImagePtr; } else { - _IM00_offs = findResource(MKID_BE('IM00'), findResource(MKID_BE('RMIM'), roomptr)) - roomptr; + _IM00_offs = findResource(MKTAG('I','M','0','0'), findResource(MKTAG('R','M','I','M'), roomptr)) - roomptr; } // // Look for an exit script // - ptr = findResourceData(MKID_BE('EXCD'), roomResPtr); + ptr = findResourceData(MKTAG('E','X','C','D'), roomResPtr); if (ptr) _EXCD_offs = ptr - roomResPtr; if (_dumpScripts && _EXCD_offs) @@ -306,7 +306,7 @@ void ScummEngine::setupRoomSubBlocks() { // // Look for an entry script // - ptr = findResourceData(MKID_BE('ENCD'), roomResPtr); + ptr = findResourceData(MKTAG('E','N','C','D'), roomResPtr); if (ptr) _ENCD_offs = ptr - roomResPtr; if (_dumpScripts && _ENCD_offs) @@ -326,7 +326,7 @@ void ScummEngine::setupRoomSubBlocks() { if (_game.features & GF_SMALL_HEADER) { ResourceIterator localScriptIterator(searchptr, true); - while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) { + while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) { int id = 0; ptr += _resourceHeaderSize; /* skip tag & size */ id = ptr[0]; @@ -341,7 +341,7 @@ void ScummEngine::setupRoomSubBlocks() { } } else if (_game.heversion >= 90) { ResourceIterator localScriptIterator2(searchptr, false); - while ((ptr = localScriptIterator2.findNext(MKID_BE('LSC2'))) != NULL) { + while ((ptr = localScriptIterator2.findNext(MKTAG('L','S','C','2'))) != NULL) { int id = 0; ptr += _resourceHeaderSize; /* skip tag & size */ @@ -359,7 +359,7 @@ void ScummEngine::setupRoomSubBlocks() { } ResourceIterator localScriptIterator(searchptr, false); - while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) { + while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) { int id = 0; ptr += _resourceHeaderSize; /* skip tag & size */ @@ -376,7 +376,7 @@ void ScummEngine::setupRoomSubBlocks() { } else { ResourceIterator localScriptIterator(searchptr, false); - while ((ptr = localScriptIterator.findNext(MKID_BE('LSCR'))) != NULL) { + while ((ptr = localScriptIterator.findNext(MKTAG('L','S','C','R'))) != NULL) { int id = 0; ptr += _resourceHeaderSize; /* skip tag & size */ @@ -403,18 +403,18 @@ void ScummEngine::setupRoomSubBlocks() { } // Locate the EGA palette (currently unused). - ptr = findResourceData(MKID_BE('EPAL'), roomptr); + ptr = findResourceData(MKTAG('E','P','A','L'), roomptr); if (ptr) _EPAL_offs = ptr - roomptr; // Locate the standard room palette (for V3-V5 games). - ptr = findResourceData(MKID_BE('CLUT'), roomptr); + ptr = findResourceData(MKTAG('C','L','U','T'), roomptr); if (ptr) _CLUT_offs = ptr - roomptr; // Locate the standard room palettes (for V6+ games). if (_game.version >= 6) { - ptr = findResource(MKID_BE('PALS'), roomptr); + ptr = findResource(MKTAG('P','A','L','S'), roomptr); if (ptr) { _PALS_offs = ptr - roomptr; } @@ -425,7 +425,7 @@ void ScummEngine::setupRoomSubBlocks() { if (_game.version == 8) trans = (byte)READ_LE_UINT32(&(rmhd->v8.transparency)); else { - ptr = findResourceData(MKID_BE('TRNS'), roomptr); + ptr = findResourceData(MKTAG('T','R','N','S'), roomptr); if (ptr) trans = ptr[0]; else @@ -434,7 +434,7 @@ void ScummEngine::setupRoomSubBlocks() { // Actor Palette in HE 70 games if (_game.heversion == 70) { - ptr = findResourceData(MKID_BE('REMP'), roomptr); + ptr = findResourceData(MKTAG('R','E','M','P'), roomptr); if (ptr) { for (i = 0; i < 256; i++) _HEV7ActorPalette[i] = *ptr++; @@ -485,7 +485,7 @@ void ScummEngine::resetRoomSubBlocks() { _res->nukeResource(rtMatrix, 1); _res->nukeResource(rtMatrix, 2); if (_game.features & GF_SMALL_HEADER) { - ptr = findResourceData(MKID_BE('BOXD'), roomptr); + ptr = findResourceData(MKTAG('B','O','X','D'), roomptr); if (ptr) { byte numOfBoxes = *ptr; int size; @@ -506,21 +506,21 @@ void ScummEngine::resetRoomSubBlocks() { } } else { - ptr = findResourceData(MKID_BE('BOXD'), roomptr); + ptr = findResourceData(MKTAG('B','O','X','D'), roomptr); if (ptr) { int size = getResourceDataSize(ptr); _res->createResource(rtMatrix, 2, size); roomptr = getResourceAddress(rtRoom, _roomResource); - ptr = findResourceData(MKID_BE('BOXD'), roomptr); + ptr = findResourceData(MKTAG('B','O','X','D'), roomptr); memcpy(getResourceAddress(rtMatrix, 2), ptr, size); } - ptr = findResourceData(MKID_BE('BOXM'), roomptr); + ptr = findResourceData(MKTAG('B','O','X','M'), roomptr); if (ptr) { int size = getResourceDataSize(ptr); _res->createResource(rtMatrix, 1, size); roomptr = getResourceAddress(rtRoom, _roomResource); - ptr = findResourceData(MKID_BE('BOXM'), roomptr); + ptr = findResourceData(MKTAG('B','O','X','M'), roomptr); memcpy(getResourceAddress(rtMatrix, 1), ptr, size); } } @@ -531,7 +531,7 @@ void ScummEngine::resetRoomSubBlocks() { for (i = 1; i < _res->num[rtScaleTable]; i++) _res->nukeResource(rtScaleTable, i); - ptr = findResourceData(MKID_BE('SCAL'), roomptr); + ptr = findResourceData(MKTAG('S','C','A','L'), roomptr); if (ptr) { int s1, s2, y1, y2; if (_game.version == 8) { @@ -558,7 +558,7 @@ void ScummEngine::resetRoomSubBlocks() { // Color cycling // HE 7.0 games load resources but don't use them. if (_game.version >= 4 && _game.heversion <= 62) { - ptr = findResourceData(MKID_BE('CYCL'), roomptr); + ptr = findResourceData(MKTAG('C','Y','C','L'), roomptr); if (ptr) { initCycl(ptr); } @@ -567,7 +567,7 @@ void ScummEngine::resetRoomSubBlocks() { #ifdef ENABLE_HE // Polygons in HE 80+ games if (_game.heversion >= 80) { - ptr = findResourceData(MKID_BE('POLD'), roomptr); + ptr = findResourceData(MKTAG('P','O','L','D'), roomptr); if (ptr) { ((ScummEngine_v71he *)this)->_wiz->polygonLoad(ptr); } diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index fb34255683..3bfe51a77b 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -154,7 +154,7 @@ void ScummEngine::requestLoad(int slot) { } static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) { - hdr.type = MKID_BE('SCVM'); + hdr.type = MKTAG('S','C','V','M'); hdr.size = 0; hdr.ver = CURRENT_VER; @@ -308,7 +308,7 @@ static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &h hdr.size = in->readUint32LE(); hdr.ver = in->readUint32LE(); in->read(hdr.name, sizeof(hdr.name)); - return !in->err() && hdr.type == MKID_BE('SCVM'); + return !in->err() && hdr.type == MKTAG('S','C','V','M'); } bool ScummEngine::loadState(int slot, bool compat) { @@ -746,7 +746,7 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos SaveInfoSection section; section.type = file->readUint32BE(); - if (section.type != MKID_BE('INFO')) { + if (section.type != MKTAG('I','N','F','O')) { return false; } @@ -793,7 +793,7 @@ bool ScummEngine::loadInfos(Common::SeekableReadStream *file, SaveStateMetaInfos void ScummEngine::saveInfos(Common::WriteStream* file) { SaveInfoSection section; - section.type = MKID_BE('INFO'); + section.type = MKTAG('I','N','F','O'); section.version = INFOSECTION_VERSION; section.size = SaveInfoSectionSize; diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index c6c1f5f58f..9e02f126cd 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -174,7 +174,7 @@ int ScummEngine::getVerbEntrypoint(int obj, int entry) { else if (_game.features & GF_SMALL_HEADER) verbptr = objptr + 19; else - verbptr = findResource(MKID_BE('VERB'), objptr); + verbptr = findResource(MKTAG('V','E','R','B'), objptr); assert(verbptr); @@ -921,7 +921,7 @@ void ScummEngine::runExitScript() { // be limiting ourselves to strictly reading the size from the header? if (_game.id == GID_INDY3 && !(_game.features & GF_OLD_BUNDLE)) { byte *roomptr = getResourceAddress(rtRoom, _roomResource); - const byte *excd = findResourceData(MKID_BE('EXCD'), roomptr) - _resourceHeaderSize; + const byte *excd = findResourceData(MKTAG('E','X','C','D'), roomptr) - _resourceHeaderSize; if (!excd || (getResourceDataSize(excd) < 1)) { debug(2, "Exit-%d is empty", _roomResource); return; diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index abe397ba7e..b2df1d0baa 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -3014,7 +3014,7 @@ void ScummEngine_v6::o6_setBoxSet() { ResourceIterator boxds(room, false); for (i = 0; i < arg; i++) - boxd = boxds.findNext(MKID_BE('BOXD')); + boxd = boxds.findNext(MKTAG('B','O','X','D')); if (!boxd) error("ScummEngine_v6::o6_setBoxSet: Can't find dboxes for set %d", arg); @@ -3027,7 +3027,7 @@ void ScummEngine_v6::o6_setBoxSet() { ResourceIterator boxms(room, false); for (i = 0; i < arg; i++) - boxm = boxms.findNext(MKID_BE('BOXM')); + boxm = boxms.findNext(MKTAG('B','O','X','M')); if (!boxm) error("ScummEngine_v6::o6_setBoxSet: Can't find mboxes for set %d", arg); diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 7b98c86506..5aea36ef66 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1577,7 +1577,7 @@ void ScummEngine_v3::resetScumm() { // Load tile set and palette for the distaff byte *roomptr = getResourceAddress(rtRoom, 90); assert(roomptr); - const byte *palPtr = findResourceData(MKID_BE('CLUT'), roomptr); + const byte *palPtr = findResourceData(MKTAG('C','L','U','T'), roomptr); assert(palPtr - 4); setPCEPaletteFromPtr(palPtr); _gdi->_distaff = true; diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp index a838fdba56..32fa99a870 100644 --- a/engines/scumm/smush/imuse_channel.cpp +++ b/engines/scumm/smush/imuse_channel.cpp @@ -29,6 +29,7 @@ #include "scumm/scumm.h" // For DEBUG_SMUSH #include "scumm/util.h" #include "scumm/smush/channel.h" +#include "scumm/imuse_digi/dimuse_codecs.h" // for decode12BitsSample namespace Scumm { @@ -64,7 +65,7 @@ bool ImuseChannel::appendData(Common::SeekableReadStream &b, int32 size) { assert(size > 8); uint32 imus_type = b.readUint32BE(); /*uint32 imus_size =*/ b.readUint32BE(); - if (imus_type != MKID_BE('iMUS')) + if (imus_type != MKTAG('i','M','U','S')) error("Invalid Chunk for imuse_channel"); size -= 8; _tbufferSize = size; @@ -115,7 +116,7 @@ bool ImuseChannel::handleMap(byte *data) { size -= 8; switch (subType) { - case MKID_BE('FRMT'): + case MKTAG('F','R','M','T'): if (subSize != 20) error("invalid size for FRMT Chunk"); //uint32 imuse_start = READ_BE_UINT32(data); @@ -125,14 +126,14 @@ bool ImuseChannel::handleMap(byte *data) { _channels = READ_BE_UINT32(data+16); assert(_channels == 1 || _channels == 2); break; - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): // Ignore this break; - case MKID_BE('REGN'): + case MKTAG('R','E','G','N'): if (subSize != 8) error("invalid size for REGN Chunk"); break; - case MKID_BE('STOP'): + case MKTAG('S','T','O','P'): if (subSize != 4) error("invalid size for STOP Chunk"); break; @@ -171,28 +172,10 @@ void ImuseChannel::decode() { } } - // FIXME: Code duplication! See decode12BitsSample() in imuse_digi/dimuse_codecs.cpp - - int loop_size = _sbufferSize / 3; - int new_size = loop_size * 4; - byte *keep, *decoded; - uint32 value; - keep = decoded = (byte *)malloc(new_size); - assert(keep); - unsigned char * source = _sbuffer; - - while (loop_size--) { - byte v1 = *source++; - byte v2 = *source++; - byte v3 = *source++; - value = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; - WRITE_BE_UINT16(decoded, value); decoded += 2; - value = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; - WRITE_BE_UINT16(decoded, value); decoded += 2; - } + byte *keep; + _sbufferSize = BundleCodecs::decode12BitsSample(_sbuffer, &keep, _sbufferSize); free(_sbuffer); _sbuffer = (byte *)keep; - _sbufferSize = new_size; } bool ImuseChannel::handleSubTags(int32 &offset) { @@ -201,13 +184,13 @@ bool ImuseChannel::handleSubTags(int32 &offset) { uint32 size = READ_BE_UINT32(_tbuffer + offset + 4); uint32 available_size = _tbufferSize - offset; switch (type) { - case MKID_BE('MAP '): + case MKTAG('M','A','P',' '): _inData = false; if (available_size >= (size + 8)) { handleMap((byte *)_tbuffer + offset); } break; - case MKID_BE('DATA'): + case MKTAG('D','A','T','A'): _inData = true; _dataSize = size; offset += 8; diff --git a/engines/scumm/smush/saud_channel.cpp b/engines/scumm/smush/saud_channel.cpp index 94df70633f..04ed955224 100644 --- a/engines/scumm/smush/saud_channel.cpp +++ b/engines/scumm/smush/saud_channel.cpp @@ -50,7 +50,7 @@ bool SaudChannel::handleSubTags(int32 &offset) { uint32 available_size = _tbufferSize - offset; switch (type) { - case MKID_BE('STRK'): + case MKTAG('S','T','R','K'): _inData = false; if (available_size >= (size + 8)) { int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4); @@ -60,14 +60,14 @@ bool SaudChannel::handleSubTags(int32 &offset) { } else return false; break; - case MKID_BE('SMRK'): + case MKTAG('S','M','R','K'): _inData = false; if (available_size >= (size + 8)) _markReached = true; else return false; break; - case MKID_BE('SHDR'): + case MKTAG('S','H','D','R'): _inData = false; if (available_size >= (size + 8)) { int32 subSize = READ_BE_UINT32((byte *)_tbuffer + offset + 4); @@ -76,7 +76,7 @@ bool SaudChannel::handleSubTags(int32 &offset) { } else return false; break; - case MKID_BE('SDAT'): + case MKTAG('S','D','A','T'): _inData = true; _dataSize = size; offset += 8; @@ -123,7 +123,7 @@ bool SaudChannel::appendData(Common::SeekableReadStream &b, int32 size) { assert(size > 8); uint32 saud_type = b.readUint32BE(); /*uint32 saud_size =*/ b.readUint32BE(); - if (saud_type != MKID_BE('SAUD')) + if (saud_type != MKTAG('S','A','U','D')) error("Invalid Chunk for SaudChannel : %X", saud_type); size -= 8; _dataSize = -2; diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp index fe2b9d99ff..0e4f588593 100644 --- a/engines/scumm/smush/smush_player.cpp +++ b/engines/scumm/smush/smush_player.cpp @@ -190,7 +190,7 @@ static StringResource *getStrings(ScummEngine *vm, const char *file, bool is_enc theFile.read(filebuffer, length); filebuffer[length] = 0; - if (is_encoded && READ_BE_UINT32(filebuffer) == MKID_BE('ETRS')) { + if (is_encoded && READ_BE_UINT32(filebuffer) == MKTAG('E','T','R','S')) { assert(length > ETRS_HEADER_LENGTH); length -= ETRS_HEADER_LENGTH; for (int i = 0; i < length; ++i) { @@ -507,7 +507,7 @@ void SmushPlayer::handleTextResource(uint32 subType, int32 subSize, Common::Seek const char *str; char *string = NULL, *string2 = NULL; - if (subType == MKID_BE('TEXT')) { + if (subType == MKTAG('T','E','X','T')) { string = (char *)malloc(subSize - 16); str = string; b.read(string, subSize - 16); @@ -845,40 +845,40 @@ void SmushPlayer::handleFrame(int32 frameSize, Common::SeekableReadStream &b) { const int32 subSize = b.readUint32BE(); const int32 subOffset = b.pos(); switch (subType) { - case MKID_BE('NPAL'): + case MKTAG('N','P','A','L'): handleNewPalette(subSize, b); break; - case MKID_BE('FOBJ'): + case MKTAG('F','O','B','J'): handleFrameObject(subSize, b); break; #ifdef USE_ZLIB - case MKID_BE('ZFOB'): + case MKTAG('Z','F','O','B'): handleZlibFrameObject(subSize, b); break; #endif - case MKID_BE('PSAD'): + case MKTAG('P','S','A','D'): if (!_compressedFileMode) handleSoundFrame(subSize, b); break; - case MKID_BE('TRES'): + case MKTAG('T','R','E','S'): handleTextResource(subType, subSize, b); break; - case MKID_BE('XPAL'): + case MKTAG('X','P','A','L'): handleDeltaPalette(subSize, b); break; - case MKID_BE('IACT'): + case MKTAG('I','A','C','T'): handleIACT(subSize, b); break; - case MKID_BE('STOR'): + case MKTAG('S','T','O','R'): handleStore(subSize, b); break; - case MKID_BE('FTCH'): + case MKTAG('F','T','C','H'): handleFetch(subSize, b); break; - case MKID_BE('SKIP'): + case MKTAG('S','K','I','P'): _vm->_insane->procSKIP(subSize, b); break; - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): handleTextResource(subType, subSize, b); break; default: @@ -990,7 +990,7 @@ void SmushPlayer::parseNextFrame() { const uint32 subType = _base->readUint32BE(); const int32 subSize = _base->readUint32BE(); const int32 subOffset = _base->pos(); - assert(subType == MKID_BE('AHDR')); + assert(subType == MKTAG('A','H','D','R')); handleAnimHeader(subSize, *_base); _base->seek(subOffset + subSize, SEEK_SET); @@ -1029,10 +1029,10 @@ void SmushPlayer::parseNextFrame() { debug(3, "Chunk: %s at %x", tag2str(subType), subOffset); switch (subType) { - case MKID_BE('AHDR'): // FT INSANE may seek file to the beginning + case MKTAG('A','H','D','R'): // FT INSANE may seek file to the beginning handleAnimHeader(subSize, *_base); break; - case MKID_BE('FRME'): + case MKTAG('F','R','M','E'): handleFrame(subSize, *_base); break; default: diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 0051319151..54f35c1969 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -206,7 +206,7 @@ void Sound::playSound(int soundID) { // Support for SFX in Monkey Island 1, Mac version // This is rather hackish right now, but works OK. SFX are not sounding // 100% correct, though, not sure right now what is causing this. - else if (READ_BE_UINT32(ptr) == MKID_BE('Mac1')) { + else if (READ_BE_UINT32(ptr) == MKTAG('M','a','c','1')) { // Read info from the header size = READ_BE_UINT32(ptr+0x60); rate = READ_BE_UINT16(ptr+0x64); @@ -245,7 +245,7 @@ void Sound::playSound(int soundID) { _mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID); } // Support for sampled sound effects in Monkey Island 1 and 2 - else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SBL ')) { + else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) { debugC(DEBUG_SOUND, "Using SBL sound effect"); // SBL resources essentially contain VOC sound data. @@ -316,7 +316,7 @@ void Sound::playSound(int soundID) { stream = Audio::makeRawStream(sound, size, rate, Audio::FLAG_UNSIGNED); _mixer->playStream(Audio::Mixer::kSFXSoundType, NULL, stream, soundID); } - else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKID_BE('SOUN')) { + else if (_vm->_game.platform != Common::kPlatformFMTowns && READ_BE_UINT32(ptr) == MKTAG('S','O','U','N')) { if (_vm->_game.version != 3) ptr += 2; @@ -415,7 +415,7 @@ void Sound::playSound(int soundID) { // Rather it seems that starting a new music is supposed to // automatically stop the old song. if (_vm->_imuse) { - if (READ_BE_UINT32(ptr) != MKID_BE('ASFX')) + if (READ_BE_UINT32(ptr) != MKTAG('A','S','F','X')) _vm->_imuse->stopAllSounds(); } } @@ -1090,15 +1090,15 @@ int ScummEngine::readSoundResource(int idx) { debugC(DEBUG_RESOURCE, " basetag: %s, total_size=%d", tag2str(basetag), total_size); switch (basetag) { - case MKID_BE('MIDI'): - case MKID_BE('iMUS'): + case MKTAG('M','I','D','I'): + case MKTAG('i','M','U','S'): if (_musicType != MDT_PCSPK && _musicType != MDT_PCJR) { _fileHandle->seek(-8, SEEK_CUR); _fileHandle->read(_res->createResource(rtSound, idx, total_size + 8), total_size + 8); return 1; } break; - case MKID_BE('SOU '): + case MKTAG('S','O','U',' '): best_pri = -1; while (pos < total_size) { tag = _fileHandle->readUint32BE(); @@ -1108,32 +1108,32 @@ int ScummEngine::readSoundResource(int idx) { pri = -1; switch (tag) { - case MKID_BE('TOWS'): + case MKTAG('T','O','W','S'): pri = 16; break; - case MKID_BE('SBL '): + case MKTAG('S','B','L',' '): pri = 15; break; - case MKID_BE('ADL '): + case MKTAG('A','D','L',' '): pri = 1; if (_musicType == MDT_ADLIB) pri = 10; break; - case MKID_BE('AMI '): + case MKTAG('A','M','I',' '): pri = 3; break; - case MKID_BE('ROL '): + case MKTAG('R','O','L',' '): pri = 3; if (_native_mt32) pri = 5; break; - case MKID_BE('GMD '): + case MKTAG('G','M','D',' '): pri = 4; break; - case MKID_BE('MAC '): // Occurs in Mac MI2, FOA + case MKTAG('M','A','C',' '): // Occurs in Mac MI2, FOA pri = 2; break; - case MKID_BE('SPK '): + case MKTAG('S','P','K',' '): pri = -1; // if (_musicType == MDT_PCSPK || _musicType == MDT_PCJR) // pri = 11; @@ -1163,7 +1163,7 @@ int ScummEngine::readSoundResource(int idx) { return 1; } break; - case MKID_BE('Mac0'): + case MKTAG('M','a','c','0'): _fileHandle->seek(-12, SEEK_CUR); total_size = _fileHandle->readUint32BE() - 8; ptr = (byte *)calloc(total_size, 1); @@ -1173,11 +1173,11 @@ int ScummEngine::readSoundResource(int idx) { free(ptr); return 1; - case MKID_BE('Mac1'): - case MKID_BE('RIFF'): - case MKID_BE('TALK'): - case MKID_BE('DIGI'): - case MKID_BE('Crea'): + case MKTAG('M','a','c','1'): + case MKTAG('R','I','F','F'): + case MKTAG('T','A','L','K'): + case MKTAG('D','I','G','I'): + case MKTAG('C','r','e','a'): case 0x460e200d: // WORKAROUND bug # 1311447 _fileHandle->seek(-12, SEEK_CUR); total_size = _fileHandle->readUint32BE(); @@ -1186,7 +1186,7 @@ int ScummEngine::readSoundResource(int idx) { //dumpResource("sound-", idx, ptr); return 1; - case MKID_BE('HSHD'): + case MKTAG('H','S','H','D'): // HE sound type without SOUN header _fileHandle->seek(-16, SEEK_CUR); total_size = max_total_size + 8; @@ -1195,7 +1195,7 @@ int ScummEngine::readSoundResource(int idx) { //dumpResource("sound-", idx, ptr); return 1; - case MKID_BE('FMUS'): { + case MKTAG('F','M','U','S'): { // Used in 3DO version of puttputt joins the parade and probably others // Specifies a separate file to be used for music from what I gather. int tmpsize; @@ -1406,20 +1406,20 @@ static byte *writeVLQ(byte *ptr, int value) { static byte Mac0ToGMInstrument(uint32 type, int &transpose) { transpose = 0; switch (type) { - case MKID_BE('MARI'): return 12; - case MKID_BE('PLUC'): return 45; - case MKID_BE('HARM'): return 22; - case MKID_BE('PIPE'): return 19; - case MKID_BE('TROM'): transpose = -12; return 57; - case MKID_BE('STRI'): return 48; - case MKID_BE('HORN'): return 60; - case MKID_BE('VIBE'): return 11; - case MKID_BE('SHAK'): return 77; - case MKID_BE('PANP'): return 75; - case MKID_BE('WHIS'): return 76; - case MKID_BE('ORGA'): return 17; - case MKID_BE('BONG'): return 115; - case MKID_BE('BASS'): transpose = -24; return 35; + case MKTAG('M','A','R','I'): return 12; + case MKTAG('P','L','U','C'): return 45; + case MKTAG('H','A','R','M'): return 22; + case MKTAG('P','I','P','E'): return 19; + case MKTAG('T','R','O','M'): transpose = -12; return 57; + case MKTAG('S','T','R','I'): return 48; + case MKTAG('H','O','R','N'): return 60; + case MKTAG('V','I','B','E'): return 11; + case MKTAG('S','H','A','K'): return 77; + case MKTAG('P','A','N','P'): return 75; + case MKTAG('W','H','I','S'): return 76; + case MKTAG('O','R','G','A'): return 17; + case MKTAG('B','O','N','G'): return 115; + case MKTAG('B','A','S','S'): transpose = -24; return 35; default: error("Unknown Mac0 instrument %s found", tag2str(type)); } @@ -1504,13 +1504,13 @@ static void convertMac0Resource(ResourceManager *res, int idx, byte *src_ptr, in // Parse the three channels for (i = 0; i < 3; i++) { - assert(READ_BE_UINT32(src_ptr) == MKID_BE('Chan')); + assert(READ_BE_UINT32(src_ptr) == MKTAG('C','h','a','n')); len = READ_BE_UINT32(src_ptr + 4); track_len[i] = len - 24; track_instr[i] = Mac0ToGMInstrument(READ_BE_UINT32(src_ptr + 8), track_transpose[i]); track_data[i] = src_ptr + 12; src_ptr += len; - looped = (READ_BE_UINT32(src_ptr - 8) == MKID_BE('Loop')); + looped = (READ_BE_UINT32(src_ptr - 8) == MKTAG('L','o','o','p')); // For each note event, we need up to 6 bytes for the // Note On (3 VLQ, 3 event), and 6 bytes for the Note diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index e8f75dd901..6d5eb3fad7 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -1499,7 +1499,7 @@ void ScummEngine::drawVerbBitmap(int verb, int x, int y) { } imptr = getObjectImage(obim, 1); } else { - const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKID_BE('IMHD'), obim); + const ImageHeader *imhd = (const ImageHeader *)findResourceData(MKTAG('I','M','H','D'), obim); if (_game.version >= 7) { imgw = READ_LE_UINT16(&imhd->v7.width) / 8; imgh = READ_LE_UINT16(&imhd->v7.height) / 8; diff --git a/engines/sword1/control.h b/engines/sword1/control.h index a6ccb09a04..2e5bfc7197 100644 --- a/engines/sword1/control.h +++ b/engines/sword1/control.h @@ -44,7 +44,7 @@ class Mouse; class Music; class Sound; -#define SAVEGAME_HEADER MKID_BE('BS_1') +#define SAVEGAME_HEADER MKTAG('B','S','_','1') #define SAVEGAME_VERSION 2 #define MAX_BUTTONS 16 diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp index 24fd5b502f..1906fcb7fd 100644 --- a/engines/sword1/screen.cpp +++ b/engines/sword1/screen.cpp @@ -899,7 +899,7 @@ uint8* Screen::psxShrinkedBackgroundToIndexed(uint8 *psxBackground, uint32 bakXr uint8 *fullres_buffer = (uint8 *)malloc(bakXres * (yresInTiles + 1) * 32); memset(fullres_buffer, 0, bakXres * (yresInTiles + 1) * 32); - bool isCompressed = (READ_LE_UINT32(psxBackground) == MKID_BE('COMP')); + bool isCompressed = (READ_LE_UINT32(psxBackground) == MKTAG('C','O','M','P')); totTiles -= xresInTiles; psxBackground += 4; //We skip the id tag diff --git a/engines/tinsel/adpcm.cpp b/engines/tinsel/adpcm.cpp new file mode 100644 index 0000000000..ec51d150dc --- /dev/null +++ b/engines/tinsel/adpcm.cpp @@ -0,0 +1,168 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tinsel/adpcm.h" + +namespace Tinsel { + +static const double TinselFilterTable[4][2] = { + {0, 0 }, + {0.9375, 0}, + {1.796875, -0.8125}, + {1.53125, -0.859375} +}; + +void Tinsel_ADPCMStream::readBufferTinselHeader() { + uint8 start = _stream->readByte(); + uint8 filterVal = (start & 0xC0) >> 6; + + if ((start & 0x20) != 0) { + //Lower 6 bit are negative + + // Negate + start = ~(start | 0xC0) + 1; + + _status.predictor = 1 << start; + } else { + // Lower 6 bit are positive + + // Truncate + start &= 0x1F; + + _status.predictor = ((double) 1.0) / (1 << start); + } + + _status.K0 = TinselFilterTable[filterVal][0]; + _status.K1 = TinselFilterTable[filterVal][1]; +} + +int16 Tinsel_ADPCMStream::decodeTinsel(int16 code, double eVal) { + double sample; + + sample = (double) code; + sample *= eVal * _status.predictor; + sample += (_status.d0 * _status.K0) + (_status.d1 * _status.K1); + + _status.d1 = _status.d0; + _status.d0 = sample; + + return (int16) CLIP<double>(sample, -32768.0, 32767.0); +} + +int Tinsel4_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) { + int samples; + uint16 data; + const double eVal = 1.142822265; + + samples = 0; + + assert(numSamples % 2 == 0); + + while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) { + if (_blockPos[0] == _blockAlign) { + readBufferTinselHeader(); + _blockPos[0] = 0; + } + + for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2, _blockPos[0]++) { + // Read 1 byte = 8 bits = two 4 bit blocks + data = _stream->readByte(); + buffer[samples] = decodeTinsel((data << 8) & 0xF000, eVal); + buffer[samples+1] = decodeTinsel((data << 12) & 0xF000, eVal); + } + } + + return samples; +} + +int Tinsel6_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) { + int samples; + const double eVal = 1.032226562; + + samples = 0; + + while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) { + if (_blockPos[0] == _blockAlign) { + readBufferTinselHeader(); + _blockPos[0] = 0; + _chunkPos = 0; + } + + for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _chunkPos = (_chunkPos + 1) % 4) { + + switch (_chunkPos) { + case 0: + _chunkData = _stream->readByte(); + buffer[samples] = decodeTinsel((_chunkData << 8) & 0xFC00, eVal); + break; + case 1: + _chunkData = (_chunkData << 8) | (_stream->readByte()); + buffer[samples] = decodeTinsel((_chunkData << 6) & 0xFC00, eVal); + _blockPos[0]++; + break; + case 2: + _chunkData = (_chunkData << 8) | (_stream->readByte()); + buffer[samples] = decodeTinsel((_chunkData << 4) & 0xFC00, eVal); + _blockPos[0]++; + break; + case 3: + _chunkData = (_chunkData << 8); + buffer[samples] = decodeTinsel((_chunkData << 2) & 0xFC00, eVal); + _blockPos[0]++; + break; + } + + } + + } + + return samples; +} + +int Tinsel8_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) { + int samples; + byte data; + const double eVal = 1.007843258; + + samples = 0; + + while (samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) { + if (_blockPos[0] == _blockAlign) { + readBufferTinselHeader(); + _blockPos[0] = 0; + } + + for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples++, _blockPos[0]++) { + // Read 1 byte = 8 bits = one 8 bit block + data = _stream->readByte(); + buffer[samples] = decodeTinsel(data << 8, eVal); + } + } + + return samples; +} + + +} // End of namespace Tinsel diff --git a/engines/tinsel/adpcm.h b/engines/tinsel/adpcm.h new file mode 100644 index 0000000000..79d537eef6 --- /dev/null +++ b/engines/tinsel/adpcm.h @@ -0,0 +1,105 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TINSEL_ADPCM_H +#define TINSEL_ADPCM_H + +#include "audio/decoders/adpcm_intern.h" + +namespace Tinsel { + +class Tinsel_ADPCMStream : public Audio::ADPCMStream { +protected: + struct { + // Tinsel + double predictor; + double K0, K1; + double d0, d1; + } _status; + + void reset() { + ADPCMStream::reset(); + memset(&_status, 0, sizeof(_status)); + } + + int16 decodeTinsel(int16, double); + void readBufferTinselHeader(); + +public: + Tinsel_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign) + : ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { + + if (blockAlign == 0) + error("Tinsel_ADPCMStream(): blockAlign isn't specified"); + + if (channels != 1) + error("Tinsel_ADPCMStream(): Tinsel ADPCM only supports mono"); + + memset(&_status, 0, sizeof(_status)); + } + +}; + +class Tinsel4_ADPCMStream : public Tinsel_ADPCMStream { +public: + Tinsel4_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign) + : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {} + + virtual int readBuffer(int16 *buffer, const int numSamples); +}; + +class Tinsel6_ADPCMStream : public Tinsel_ADPCMStream { +protected: + uint8 _chunkPos; + uint16 _chunkData; + + void reset() { + ADPCMStream::reset(); + _chunkPos = 0; + _chunkData = 0; + } + +public: + Tinsel6_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign) + : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) { + _chunkPos = 0; + _chunkData = 0; + } + + virtual int readBuffer(int16 *buffer, const int numSamples); +}; + +class Tinsel8_ADPCMStream : public Tinsel_ADPCMStream { +public: + Tinsel8_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign) + : Tinsel_ADPCMStream(stream, disposeAfterUse, size, rate, channels, blockAlign) {} + + virtual int readBuffer(int16 *buffer, const int numSamples); +}; + + +} // End of namespace Tinsel + +#endif diff --git a/engines/tinsel/background.cpp b/engines/tinsel/background.cpp index 560216aadb..f895ecd2da 100644 --- a/engines/tinsel/background.cpp +++ b/engines/tinsel/background.cpp @@ -39,9 +39,6 @@ namespace Tinsel { // current background const BACKGND *pCurBgnd = NULL; -// FIXME: Not yet used -static bool bEntireRedraw; - /** * Called to initialise a background. * @param pBgnd Pointer to data struct for current background @@ -257,9 +254,4 @@ void DrawBackgnd() { ResetClipRect(); } -void ForceEntireRedraw() { - bEntireRedraw = true; -} - - } // End of namespace Tinsel diff --git a/engines/tinsel/background.h b/engines/tinsel/background.h index 81b490488e..d0b27e6e40 100644 --- a/engines/tinsel/background.h +++ b/engines/tinsel/background.h @@ -110,8 +110,6 @@ OBJECT *GetBgObject(); SCNHANDLE BgPal(); -void ForceEntireRedraw(); - int BgWidth(); int BgHeight(); diff --git a/engines/tinsel/bmv.cpp b/engines/tinsel/bmv.cpp index 3f56288aca..b5b84ceaee 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -1025,7 +1025,6 @@ bool BMVPlayer::DoSoundFrame() { void BMVPlayer::CopyMovieToScreen() { // Not if not up and running yet! if (!screenBuffer || (currentFrame == 0)) { - ForceEntireRedraw(); DrawBackgnd(); return; } @@ -1046,21 +1045,6 @@ void BMVPlayer::CopyMovieToScreen() { } /** - * LookAtBuffers - */ -void BMVPlayer::LookAtBuffers() { - // FIXME: What's the point of this function??? - // Maybe to ensure the relevant data is loaded into cache by the CPU? - static int junk; // FIXME: Avoid non-const global vars - int i; - - if (bigBuffer) { - for (i = 0; i < NUM_SLOTS; i++) - junk += bigBuffer[i*SLOT_SIZE]; - } -} - -/** * Handles playback of any active movie. Called from the foreground 24 times a second. */ void BMVPlayer::FettleBMV() { @@ -1078,8 +1062,6 @@ void BMVPlayer::FettleBMV() { return; } - LookAtBuffers(); - if (!stream.isOpen()) { int i; diff --git a/engines/tinsel/bmv.h b/engines/tinsel/bmv.h index 2644504cab..99a43e0740 100644 --- a/engines/tinsel/bmv.h +++ b/engines/tinsel/bmv.h @@ -151,7 +151,6 @@ private: bool MaintainBuffer(); bool DoBMVFrame(); bool DoSoundFrame(); - void LookAtBuffers(); }; diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp index 6e30caf006..ab606f3159 100644 --- a/engines/tinsel/drives.cpp +++ b/engines/tinsel/drives.cpp @@ -38,7 +38,6 @@ namespace Tinsel { // FIXME: Avoid non-const global vars char currentCD = '1'; -static uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 }; static bool bChangingCD = false; static char nextCD = '\0'; @@ -75,6 +74,8 @@ int GetCurrentCD() { return (currentCD - '1' + 1); } +static const uint32 cdFlags[] = { fCd1, fCd2, fCd3, fCd4, fCd5, fCd6, fCd7, fCd8 }; + void SetCD(int flags) { if (flags & cdFlags[currentCD - '1']) return; diff --git a/engines/tinsel/dw.h b/engines/tinsel/dw.h index 8bd7ca1a4e..aed4c50408 100644 --- a/engines/tinsel/dw.h +++ b/engines/tinsel/dw.h @@ -42,8 +42,6 @@ typedef int HPOLYGON; #define LF_CHAR '\x0a' // line feed // file names -#define SAMPLE_FILE "english.smp" // all samples -#define SAMPLE_INDEX "english.idx" // sample index filename #define MIDI_FILE "midi.dat" // all MIDI sequences #define INDEX_FILENAME "index" // name of index file #define PSX_INDEX_FILENAME "index.dat" // name of index file in psx version diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index a48fd2ca1f..f2db42bede 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -65,8 +65,6 @@ enum { fLoaded = 0x20000000L ///< set when file data has been loaded }; #define FSIZE_MASK 0x00FFFFFFL ///< mask to isolate the filesize -#define MALLOC_MASK 0xFF000000L ///< mask to isolate the memory allocation flags -//#define HANDLEMASK 0xFF800000L ///< get handle of address //----------------- LOCAL GLOBAL DATA -------------------- @@ -80,7 +78,6 @@ static uint numHandles = 0; static uint32 cdPlayHandle = (uint32)-1; -static int cdPlayFileNum, cdPlaySceneNum; static SCNHANDLE cdBaseHandle = 0, cdTopHandle = 0; static Common::File *cdGraphStream = 0; @@ -235,7 +232,7 @@ void LoadCDGraphData(MEMHANDLE *pH) { // clear the loading flag // pH->filesize &= ~fLoading; - if (bytes != ((cdTopHandle-cdBaseHandle) & OFFSETMASK)) + if (bytes != ((cdTopHandle - cdBaseHandle) & OFFSETMASK)) // file is corrupt error(FILE_READ_ERROR, "CD play file"); } @@ -248,7 +245,7 @@ void LoadCDGraphData(MEMHANDLE *pH) { * @param next Handle of end of range + 1 */ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) { - if (cdPlayFileNum == cdPlaySceneNum && start == cdBaseHandle) + if (start == cdBaseHandle) return; OpenCDGraphFile(); @@ -264,7 +261,6 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) { } void SetCdPlaySceneDetails(int fileNum, const char *fileName) { - cdPlaySceneNum = fileNum; strcpy(szCdPlayFile, fileName); } diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk index 2778cec3df..2ab94b830a 100644 --- a/engines/tinsel/module.mk +++ b/engines/tinsel/module.mk @@ -2,6 +2,7 @@ MODULE := engines/tinsel MODULE_OBJS := \ actors.o \ + adpcm.o \ anim.o \ background.o \ bg.o \ diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index ea5d88ce1c..12bcff829b 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -38,6 +38,7 @@ #include "common/file.h" #include "common/memstream.h" +#include "tinsel/adpcm.h" #include "tinsel/config.h" #include "tinsel/sound.h" #include "tinsel/music.h" @@ -65,10 +66,6 @@ struct SOUND_BUFFER { // FIXME: Avoid non-const global vars -// get set when music driver is installed -//static MDI_DRIVER *mDriver; -//static HSEQUENCE mSeqHandle; - // MIDI buffer static SOUND_BUFFER midiBuffer = { 0, 0 }; @@ -152,8 +149,6 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) { // the index and length of the last tune loaded static uint32 dwLastMidiIndex = 0; // FIXME: Avoid non-const global vars - //static uint32 dwLastSeqLen; - uint32 dwSeqLen = 0; // length of the sequence // Support for external music from the music enhancement project @@ -471,7 +466,6 @@ PCMMusicPlayer::PCMMusicPlayer() { _silenceSamples = 0; _curChunk = 0; - _fileName = 0; _state = S_IDLE; _mState = S_IDLE; _scriptNum = -1; @@ -494,15 +488,13 @@ PCMMusicPlayer::PCMMusicPlayer() { PCMMusicPlayer::~PCMMusicPlayer() { _vm->_mixer->stopHandle(_handle); - - delete[] _fileName; } void PCMMusicPlayer::startPlay(int id) { - if (!_fileName) + if (_filename.empty()) return; - debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _fileName, id); + debugC(DEBUG_DETAILED, kTinselDebugMusic, "Playing PCM music %s, index %d", _filename.c_str(), id); Common::StackLock slock(_mutex); @@ -617,8 +609,7 @@ void PCMMusicPlayer::setMusicSceneDetails(SCNHANDLE hScript, _hScript = hScript; _hSegment = hSegment; - _fileName = new char[strlen(fileName) + 1]; - strcpy(_fileName, fileName); + _filename = fileName; // Start scene with music not dimmed _dimmed = false; @@ -774,19 +765,19 @@ bool PCMMusicPlayer::getNextChunk() { sampleLength = FROM_LE_32(musicSegments[snum].sampleLength); sampleCLength = (((sampleLength + 63) & ~63)*33)/64; - if (!file.open(_fileName)) - error(CANNOT_FIND_FILE, _fileName); + if (!file.open(_filename)) + error(CANNOT_FIND_FILE, _filename.c_str()); file.seek(sampleOffset); if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset) - error(FILE_IS_CORRUPT, _fileName); + error(FILE_IS_CORRUPT, _filename.c_str()); buffer = (byte *) malloc(sampleCLength); assert(buffer); // read all of the sample if (file.read(buffer, sampleCLength) != sampleCLength) - error(FILE_IS_CORRUPT, _fileName); + error(FILE_IS_CORRUPT, _filename.c_str()); debugC(DEBUG_DETAILED, kTinselDebugMusic, "Creating ADPCM music chunk with size %d, " "offset %d (script %d.%d)", sampleCLength, sampleOffset, @@ -795,8 +786,8 @@ bool PCMMusicPlayer::getNextChunk() { sampleStream = new Common::MemoryReadStream(buffer, sampleCLength, DisposeAfterUse::YES); delete _curChunk; - _curChunk = makeADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength, - Audio::kADPCMTinsel8, 22050, 1, 32); + _curChunk = new Tinsel8_ADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength, + 22050, 1, 32); _state = S_MID; return true; diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h index af089caf24..9003e60078 100644 --- a/engines/tinsel/music.h +++ b/engines/tinsel/music.h @@ -148,7 +148,7 @@ protected: int32 _scriptIndex; SCNHANDLE _hScript; SCNHANDLE _hSegment; - char *_fileName; + Common::String _filename; uint8 _volume; diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp index c965666e84..3182593a88 100644 --- a/engines/tinsel/saveload.cpp +++ b/engines/tinsel/saveload.cpp @@ -77,9 +77,6 @@ SRSTATE SRstate = SR_IDLE; // in DOS_DW.C extern void syncSCdata(Common::Serializer &s); -// in DOS_MAIN.C -//char HardDriveLetter(); - // in PCODE.C extern void syncGlobInfo(Common::Serializer &s); @@ -283,32 +280,6 @@ static void syncSavedData(Common::Serializer &s, SAVED_DATA &sd) { } } - -/** - * Called when saving a game to a new file. - * Generates a new, unique, filename. - */ -static char *NewName() { - static char result[FNAMELEN]; // FIXME: Avoid non-const global vars - int i; - int ano = 1; // Allocated number - - while (1) { - Common::String fname = _vm->getSavegameFilename(ano); - strcpy(result, fname.c_str()); - - for (i = 0; i < numSfiles; i++) - if (!strcmp(savedFiles[i].name, result)) - break; - - if (i == numSfiles) - break; - ano++; - } - - return result; -} - /** * Compare two TimeDate structs to see which one was earlier. * Returns 0 if they are equal, a negative value if a is lower / first, and @@ -498,19 +469,37 @@ static bool DoRestore() { */ static void DoSave() { Common::OutSaveFile *f; - const char *fname; + char tmpName[FNAMELEN]; // Next getList() must do its stuff again NeedLoad = true; - if (SaveSceneName == NULL) - SaveSceneName = NewName(); + if (SaveSceneName == NULL) { + // Generate a new unique save name + int i; + int ano = 1; // Allocated number + + while (1) { + Common::String fname = _vm->getSavegameFilename(ano); + strcpy(tmpName, fname.c_str()); + + for (i = 0; i < numSfiles; i++) + if (!strcmp(savedFiles[i].name, tmpName)) + break; + + if (i == numSfiles) + break; + ano++; + } + + SaveSceneName = tmpName; + } + + if (SaveSceneDesc[0] == 0) SaveSceneDesc = "unnamed"; - fname = SaveSceneName; - - f = _vm->getSaveFileMan()->openForSaving(fname); + f = _vm->getSaveFileMan()->openForSaving(SaveSceneName); Common::Serializer s(0, f); if (f == NULL) @@ -537,12 +526,14 @@ static void DoSave() { f->finalize(); delete f; + SaveSceneName = NULL; // Invalidate save name return; save_failure: if (f) { delete f; - _vm->getSaveFileMan()->removeSavefile(fname); + _vm->getSaveFileMan()->removeSavefile(SaveSceneName); + SaveSceneName = NULL; // Invalidate save name } GUI::MessageDialog dialog("Failed to save game state to file."); dialog.runModal(); diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp index 8f0f4771e3..67e0ea9ffd 100644 --- a/engines/tinsel/scene.cpp +++ b/engines/tinsel/scene.cpp @@ -112,15 +112,11 @@ struct ENTRANCE_STRUC { static bool ShowPosition = false; // Set when showpos() has been called #endif -SCNHANDLE newestScene = 0; - int sceneCtr = 0; static int initialMyEscape; static SCNHANDLE SceneHandle = 0; // Current scene handle - stored in case of Save_Scene() -static bool bWatchingOut = false; - SCENE_STRUC tempStruc; struct TP_INIT { @@ -180,9 +176,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) { _ctx->myEscape); CORO_INVOKE_1(Interpret, _ctx->pic); - if (_ctx->pInit->event == CLOSEDOWN || _ctx->pInit->event == LEAVE_T2) - bWatchingOut = false; - CORO_END_CODE; } @@ -193,9 +186,6 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) { void SendSceneTinselProcess(TINSEL_EVENT event) { SCENE_STRUC *ss; - if (event == CLOSEDOWN || event == LEAVE_T2) - bWatchingOut = true; - if (SceneHandle != (SCNHANDLE)NULL) { ss = (SCENE_STRUC *) FindChunk(SceneHandle, CHUNK_SCENE); @@ -206,11 +196,8 @@ void SendSceneTinselProcess(TINSEL_EVENT event) { init.hTinselCode = ss->hSceneScript; g_scheduler->createProcess(PID_TCODE, SceneTinselProcess, &init, sizeof(init)); - } else if (event == CLOSEDOWN) - bWatchingOut = false; + } } - else if (event == CLOSEDOWN) - bWatchingOut = false; } @@ -249,9 +236,6 @@ static void LoadScene(SCNHANDLE scene, int entry) { assert(ss != NULL); if (TinselV2) { - // Handle to scene description - newestScene = FROM_LE_32(ss->hSceneDesc); - // Music stuff char *cptr = (char *)FindChunk(scene, CHUNK_MUSIC_FILENAME); assert(cptr); diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index 5fc2820986..1fcdb4dcf9 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -26,6 +26,7 @@ #include "tinsel/sound.h" +#include "tinsel/adpcm.h" #include "tinsel/dw.h" #include "tinsel/config.h" #include "tinsel/music.h" @@ -319,7 +320,7 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p #endif break; default: - sampleStream = Audio::makeADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); + sampleStream = new Tinsel6_ADPCMStream(compressedStream, DisposeAfterUse::YES, sampleLen, 22050, 1, 24); break; } @@ -530,17 +531,17 @@ void SoundManager::openSampleFiles() { // Detect format of soundfile by looking at 1st sample-index switch (TO_BE_32(_sampleIndex[0])) { - case MKID_BE('MP3 '): + case MKTAG('M','P','3',' '): debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data"); _soundMode = kMP3Mode; break; - case MKID_BE('OGG '): + case MKTAG('O','G','G',' '): debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data"); _soundMode = kVorbisMode; break; - case MKID_BE('FLAC'): + case MKTAG('F','L','A','C'): debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data"); _soundMode = kFLACMode; break; diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 1b3173719f..e1396f9715 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -218,14 +218,17 @@ void KeyboardProcess(CORO_PARAM, const void *) { continue; #endif + case Common::KEYCODE_1: case Common::KEYCODE_F1: // Options dialog ProcessKeyEvent(PLR_MENU); continue; + case Common::KEYCODE_5: case Common::KEYCODE_F5: // Save game ProcessKeyEvent(PLR_SAVE); continue; + case Common::KEYCODE_7: case Common::KEYCODE_F7: // Load game ProcessKeyEvent(PLR_LOAD); diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp index d76a63c1ae..c2e0bf7b20 100644 --- a/engines/toon/audio.cpp +++ b/engines/toon/audio.cpp @@ -26,24 +26,10 @@ #include "toon/audio.h" #include "common/memstream.h" #include "common/substream.h" +#include "audio/decoders/adpcm_intern.h" namespace Toon { -static int ADPCM_index[8] = { - -1, -1, -1, -1, 2 , 4 , 6 , 8 -}; -static int ADPCM_table[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 -}; - AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { for (int32 i = 0; i < 16; i++) _channels[i] = NULL; @@ -372,7 +358,7 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize int32 v31 = v30 & 0x8; int32 v32 = v30 & 0x7; - int32 v33 = ADPCM_table[v19]; + int32 v33 = Audio::Ima_ADPCMStream::_imaTable[v19]; int32 v34 = v33 >> 3; if (v32 & 4) v34 += v33; @@ -383,12 +369,8 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize if (v32 & 1) v34 += v33 >> 2; - v19 += ADPCM_index[v32]; - if (v19 < 0) - v19 = 0; - - if (v19 > 88) - v19 = 88; + v19 += Audio::ADPCMStream::_stepAdjustTable[v32]; + v19 = CLIP<int32>(v19, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1); if (v31) v18 -= v34; diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp index ec2344d659..0573e92fef 100644 --- a/engines/toon/hotspot.cpp +++ b/engines/toon/hotspot.cpp @@ -127,7 +127,7 @@ bool Hotspots::LoadRif(Common::String rifName, Common::String additionalRifName) decoder.unpackM1(rifData, size, _items); if (rifsize2) { RncDecoder decoder2; - decoder2.unpackM1(rifData2 , size, _items + (rifsize >> 9)); + decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9)); for (int32 i = 0; i < (rifsize2 >> 9); i++) { HotspotData *hot = _items + (rifsize >> 9) + i; hot->setData(0, hot->getX1() + 1280); diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp index 376b1db621..0242ace7e3 100644 --- a/engines/toon/script.cpp +++ b/engines/toon/script.cpp @@ -70,7 +70,7 @@ EMCInterpreter::~EMCInterpreter() { bool EMCInterpreter::callback(Common::IFFChunk &chunk) { switch (chunk._type) { - case MKID_BE('TEXT'): + case MKTAG('T','E','X','T'): delete[] _scriptData->text; _scriptData->text = new byte[chunk._size]; assert(_scriptData->text); @@ -78,7 +78,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) { error("Couldn't read TEXT chunk from file '%s'", _filename); break; - case MKID_BE('ORDR'): + case MKTAG('O','R','D','R'): delete[] _scriptData->ordr; _scriptData->ordr = new uint16[chunk._size >> 1]; assert(_scriptData->ordr); @@ -89,7 +89,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) { _scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]); break; - case MKID_BE('DATA'): + case MKTAG('D','A','T','A'): delete[] _scriptData->data; _scriptData->data = new uint16[chunk._size >> 1]; assert(_scriptData->data); diff --git a/engines/toon/script.h b/engines/toon/script.h index 2a74f9084f..b6d28e1171 100644 --- a/engines/toon/script.h +++ b/engines/toon/script.h @@ -87,9 +87,9 @@ public: // Both lead to some problems in our IFF parser, either reading after the end // of file or producing a "Chunk overread" error message. To work around this // we need to adjust the size field properly. - if (_formType == MKID_BE('EMC2')) + if (_formType == MKTAG('E','M','C','2')) _formChunk.size -= 8; - else if (_formType == MKID_BE('AVFS')) + else if (_formType == MKTAG('A','V','F','S')) _formChunk.size += 4; } }; diff --git a/engines/toon/tools.cpp b/engines/toon/tools.cpp index bad796158a..da6e0f712e 100644 --- a/engines/toon/tools.cpp +++ b/engines/toon/tools.cpp @@ -373,8 +373,21 @@ int32 RncDecoder::unpackM1(const void *input, uint16 inputSize, void *output) { _dstPtr += inputLength; _srcPtr += inputLength; _inputByteLeft -= inputLength; - uint16 a = READ_LE_UINT16(_srcPtr); - uint16 b = READ_LE_UINT16(_srcPtr + 2); + uint16 a; + if (_inputByteLeft <= 0) + a = 0; + else if (_inputByteLeft == 1) + a = *_srcPtr; + else + a = READ_LE_UINT16(_srcPtr); + + uint16 b; + if (_inputByteLeft <= 2) + b = 0; + else if(_inputByteLeft == 3) + b = *(_srcPtr + 2); + else + b = READ_LE_UINT16(_srcPtr + 2); _bitBuffl &= ((1 << _bitCount) - 1); _bitBuffl |= (a << _bitCount); diff --git a/engines/toon/tools.h b/engines/toon/tools.h index b716d4813a..1434ca26c7 100644 --- a/engines/toon/tools.h +++ b/engines/toon/tools.h @@ -63,7 +63,7 @@ protected: const uint8 *_srcPtr; uint8 *_dstPtr; - uint16 _inputByteLeft; + int16 _inputByteLeft; public: RncDecoder(); diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp new file mode 100644 index 0000000000..fd1dfe9e9d --- /dev/null +++ b/engines/tsage/converse.cpp @@ -0,0 +1,948 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/str-array.h" + +#include "tsage/tsage.h" +#include "tsage/globals.h" +#include "tsage/staticres.h" + +namespace tSage { + +#define STRIP_WORD_DELAY 30 + + +SequenceManager::SequenceManager() : Action() { + Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL); + _sequenceData.clear(); + _field24 = 0; + _sequenceOffset = 0; + _resNum = 0; + _field26 = 0; + _objectIndex = 0; + _keepActive = false; + setup(); +} + +void SequenceManager::setup() { + _sequenceOffset = 0; + _objectIndex = 0; + _sceneObject = _objectList[0]; +} + +void SequenceManager::synchronise(Serialiser &s) { + s.syncAsSint32LE(_resNum); + s.syncAsSint32LE(_sequenceOffset); + s.syncAsByte(_keepActive); + s.syncAsSint32LE(_field24); + s.syncAsSint32LE(_field26); + + s.syncAsSint32LE(_objectIndex); + SYNC_POINTER(_sceneObject); + for (int i = 0; i < 6; ++i) + SYNC_POINTER(_objectList[i]); + + int seqSize = _sequenceData.size(); + s.syncAsUint32LE(seqSize); + if (s.isLoading()) + _sequenceData.resize(seqSize); + if (seqSize > 0) + s.syncBytes(&_sequenceData[0], seqSize); +} + +void SequenceManager::remove() { + if ((!_sequenceData.empty()) && !_keepActive) { + _sequenceData.clear(); + } + + if (_globals->_sceneObjects->contains(&_sceneText)) + _sceneText.remove(); + + Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL); + Action::remove(); +} + +void SequenceManager::signal() { + if (_globals->_sceneObjects->contains(&_sceneText)) + _sceneText.hide(); + + bool continueFlag = true; + while (continueFlag) { + if (_sequenceOffset >=_sequenceData.size()) { + // Reached the end of the sequence + if (!_keepActive) + remove(); + break; + } + + uint16 idx = static_cast<uint16>(getNextValue() - 32000); + if (idx > 34) + continue; + + int16 v1, v2, v3; + switch (idx) { + case 0: + // Stop sequence + continueFlag = false; + break; + case 1: + _sceneObject->animate(ANIM_MODE_1, NULL); + break; + case 2: + _sceneObject->animate(ANIM_MODE_2, NULL); + break; + case 3: + _sceneObject->animate(ANIM_MODE_3); + break; + case 4: + v1 = getNextValue(); + v2 = getNextValue(); + _sceneObject->animate(ANIM_MODE_8, v1, v2 ? this : NULL); + break; + case 5: + v1 = getNextValue(); + v2 = getNextValue(); + _sceneObject->animate(ANIM_MODE_7, v1, v2 ? this : NULL); + break; + case 6: + v2 = getNextValue(); + _sceneObject->animate(ANIM_MODE_5, v2 ? this : NULL); + break; + case 7: + v2 = getNextValue(); + _sceneObject->animate(ANIM_MODE_6, v2 ? this : NULL); + break; + case 8: + v1 = getNextValue(); + v3 = getNextValue(); + v2 = getNextValue(); + _sceneObject->animate(ANIM_MODE_4, v1, v3, v2 ? this : NULL); + break; + case 9: + v1 = getNextValue(); + v3 = getNextValue(); + v2 = getNextValue(); + _globals->_sceneManager._scene->_sceneBounds.moveTo(v3, v2); + _globals->_sceneManager._scene->loadScene(v1); + break; + case 10: { + int resNum= getNextValue(); + int lineNum = getNextValue(); + int colour = getNextValue(); + int xp = getNextValue(); + int yp = getNextValue(); + int width = getNextValue(); + setMessage(resNum, lineNum, colour, Common::Point(xp, yp), width); + break; + } + case 11: + v1 = getNextValue(); + v2 = getNextValue(); + setAction(globalManager(), v2 ? this : NULL, v1, _objectList[0], _objectList[1], _objectList[2], _objectList[3], NULL); + break; + case 12: + v1 = getNextValue(); + setDelay(v1); + break; + case 13: { + v1 = getNextValue(); + v3 = getNextValue(); + v2 = getNextValue(); + NpcMover *mover = new NpcMover(); + Common::Point destPos(v1, v3); + _sceneObject->addMover(mover, &destPos, v2 ? this : NULL); + break; + } + case 14: + v1 = getNextValue(); + _sceneObject->_numFrames = v1; + break; + case 15: + v1 = getNextValue(); + _sceneObject->_field7A = v1; + break; + case 16: + v1 = getNextValue(); + v2 = getNextValue(); + _sceneObject->_moveDiff = Common::Point(v1, v2); + break; + case 17: + _sceneObject->hide(); + break; + case 18: + _sceneObject->show(); + break; + case 19: + v1 = getNextValue(); + _sceneObject->setVisage(v1); + break; + case 20: + v1 = getNextValue(); + _sceneObject->setStrip(v1); + break; + case 21: + v1 = getNextValue(); + _sceneObject->setFrame(v1); + break; + case 22: + v1 = getNextValue(); + _sceneObject->setPriority2(v1); + break; + case 23: + v1 = getNextValue(); + _sceneObject->changeZoom(v1); + break; + case 24: + v1 = getNextValue(); + v2 = getNextValue(); + v3 = getNextValue(); + _sceneObject->setPosition(Common::Point(v1, v2), v3); + break; + case 25: { + int yStart = getNextValue(); + int minPercent = getNextValue(); + int yEnd = getNextValue(); + int maxPercent = getNextValue(); + _globals->_sceneManager._scene->setZoomPercents(yStart, minPercent, yEnd, maxPercent); + break; + } + case 26: + v1 = getNextValue(); + v2 = getNextValue(); + _soundHandler.startSound(v1, v2 ? this : NULL, 127); + break; + case 27: { + v1 = getNextValue(); + v3 = getNextValue(); + v2 = getNextValue(); + PlayerMover *mover = new PlayerMover(); + Common::Point destPos(v1, v3); + _sceneObject->addMover(mover, &destPos, v2 ? this : NULL); + break; + } + case 28: + _objectIndex = getNextValue(); + _sceneObject = _objectList[_objectIndex]; + assert(_sceneObject); + break; + case 29: + _sceneObject->animate(ANIM_MODE_NONE); + break; + case 30: + v1 = getNextValue(); + _globals->_scrollFollower = (v1 == -1) ? NULL : _objectList[v1]; + break; + case 31: + _sceneObject->setObjectWrapper(new SceneObjectWrapper()); + break; + case 32: + _sceneObject->setObjectWrapper(NULL); + break; + case 33: + v1 = getNextValue(); + if (_keepActive) + setDelay(1); + else { + _sceneText.remove(); + _globals->_sceneManager._scene->_stripManager.start(v1, this); + } + break; + case 34: { + v1 = getNextValue(); + v2 = getNextValue(); + int objIndex1 = getNextValue(); + int objIndex2 = getNextValue(); + int objIndex3 = getNextValue(); + int objIndex4 = getNextValue(); + int objIndex5 = getNextValue(); + + setAction(globalManager(), v2 ? this : NULL, v1, _objectList[objIndex1], _objectList[objIndex2], + _objectList[objIndex3], _objectList[objIndex4], _objectList[objIndex5]); + break; + } + default: + error("SequenceManager::signal - Unknown action %d at offset %xh", idx, _sequenceOffset - 2); + break; + } + } +} + +void SequenceManager::process(Event &event) { + if (((event.eventType == EVENT_BUTTON_DOWN) || (event.eventType == EVENT_KEYPRESS)) && + !event.handled && _globals->_sceneObjects->contains(&_sceneText)) { + // Remove the text item + _sceneText.remove(); + } else { + Action::process(event); + } +} + + +void SequenceManager::attached(EventHandler *newOwner, EventHandler *fmt, va_list va) { + // Get the sequence number to use + _resNum = va_arg(va, int); + + byte *seqData = _vm->_dataManager->getResource(RES_SEQUENCE, _resNum, 0); + uint seqSize = _vm->_memoryManager.getSize(seqData); + + _sequenceData.resize(seqSize); + Common::copy(seqData, seqData + seqSize, &_sequenceData[0]); + + DEALLOCATE(seqData); + + Common::set_to(&_objectList[0], &_objectList[6], (SceneObject *)NULL); + for (int idx = 0; idx < 6; ++idx) { + _objectList[idx] = va_arg(va, SceneObject *); + if (!_objectList[idx]) + break; + } + + setup(); + // TODO: This is not particulary nice, since dummy is uninitialized. + // Since the default Action implementation does not access the va_list + // parameter it should be fine though. Still it would be nice to find + // a better solution to this. + va_list dummy; + Action::attached(newOwner, fmt, dummy); +} + +/** + * Returns the next Id in the sequence + */ +uint16 SequenceManager::getNextValue() { + uint16 result = READ_LE_UINT16(&_sequenceData[0] + _sequenceOffset); + _sequenceOffset += 2; + return result; +} + +void SequenceManager::setMessage(int resNum, int lineNum, int colour, const Common::Point &pt, int width) { + _sceneText._colour1 = colour; + _sceneText._colour2 = 0; + _sceneText._colour3 = 0; + _sceneText._fontNumber = 2; + _sceneText._width = width; + + // Get the display message + Common::String msg = _vm->_dataManager->getMessage(resNum, lineNum); + + // Get the needed rect, and move it to the desired position + Rect textRect; + _globals->gfxManager().getStringBounds(msg.c_str(), textRect, width); + Rect sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + sceneBounds.collapse(4, 2); + textRect.moveTo(pt); + textRect.contain(sceneBounds); + + // Set the text message + _sceneText.setup(msg); + _sceneText.setPosition(Common::Point(textRect.left, textRect.top)); + _sceneText.setPriority2(255); + _sceneText.show(); + + // Set the delay based on the number of words + int numWords = 0; + const char *msgP = msg.c_str(); + while (*msgP) { + if (*msgP++ == ' ') + ++numWords; + } + + setDelay(numWords * 18 + 120); +} + +SequenceManager *SequenceManager::globalManager() { + return &_globals->_sequenceManager; +} + +/*--------------------------------------------------------------------------*/ + +ConversationChoiceDialog::ConversationChoiceDialog() { + _stdColour = 23; + _highlightColour = _globals->_scenePalette._colours.background; + _fontNumber = 1; +} + +int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) { + _gfxManager._font.setFontNumber(_fontNumber); + + _bounds = Rect(20, 0, 20, 0); + _choiceList.clear(); + + // Set up the list of choices + int yp = 0; + for (uint idx = 0; idx < choiceList.size(); ++idx) { + Rect tempRect; + _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, 265); + tempRect.moveTo(25, yp + 10); + + _choiceList.push_back(ChoiceEntry(choiceList[idx], tempRect)); + yp += tempRect.height() + 5; + _bounds.extend(tempRect); + } + _selectedIndex = _choiceList.size(); + + // Set the position for the dialog + _bounds.bottom -= 10; + yp = 180 - _bounds.height(); + _bounds.translate(0, yp); + _bounds.right = _bounds.left + 280; + + // Draw the dialog + draw(); + _globals->_events.showCursor(); + + // Event handling loop + Event event; + while (!_vm->getEventManager()->shouldQuit()) { + while (!_globals->_events.getEvent(event, EVENT_KEYPRESS | EVENT_BUTTON_DOWN | EVENT_MOUSE_MOVE) && + !_vm->getEventManager()->shouldQuit()) + ; + if (_vm->getEventManager()->shouldQuit()) + break; + + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode >= Common::KEYCODE_1) && + (event.kbd.keycode <= (Common::KEYCODE_0 + (int)_choiceList.size()))) { + // Selected an option by number + _selectedIndex = event.kbd.keycode - Common::KEYCODE_1; + break; + } else if ((_selectedIndex != _choiceList.size()) && ((event.eventType == EVENT_BUTTON_DOWN) || + (event.eventType == EVENT_BUTTON_UP))) { + // Item selected + break; + } else { + // Check if any item is highlighted + event.mousePos.x -= _gfxManager._bounds.left; + event.mousePos.y -= _gfxManager._bounds.top; + + uint idx = 0; + while ((idx < _choiceList.size()) && !_choiceList[idx]._bounds.contains(event.mousePos.x, event.mousePos.y)) + ++idx; + + if (idx != _selectedIndex) { + if (_selectedIndex != _choiceList.size()) { + // De-highlight previously selected item + _gfxManager._font._colours.foreground = _stdColour; + _gfxManager._font.writeLines(_choiceList[_selectedIndex]._msg.c_str(), + _choiceList[_selectedIndex]._bounds, ALIGN_LEFT); + } + + _selectedIndex = idx; + + if (_selectedIndex != _choiceList.size()) { + // Highlight the new item + _gfxManager._font._colours.foreground = _highlightColour; + _gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT); + } + + } + } + } + + // Remove the dialog + remove(); + + return _selectedIndex; +} + +void ConversationChoiceDialog::draw() { + // Make a backup copy of the area the dialog will occupy + Rect tempRect = _bounds; + tempRect.collapse(-10, -10); + _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), tempRect); + + // Fill in the contents of the entire dialog + _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + drawFrame(); + + _gfxManager._bounds = tempRect; + _gfxManager._font._colours.foreground = _stdColour; + _gfxManager.activate(); + + // Loop through writing the conversation choices + for (uint idx = 0; idx < _choiceList.size(); ++idx) { + Common::String strNum = Common::String::format("%d", idx + 1); + + // Write the choice number + _gfxManager._font.setPosition(13, _choiceList[idx]._bounds.top); + _gfxManager._font.writeString(strNum.c_str()); + + _gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT); + } + + _gfxManager.deactivate(); +} + +/*--------------------------------------------------------------------------*/ + +void Obj44::load(const byte *dataP) { + _id = READ_LE_UINT16(dataP); + for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx) + _field2[idx] = READ_LE_UINT16(dataP + 2 + idx * 2); + + const byte *listP = dataP + 0x10; + for (int idx = 0; idx < OBJ44_LIST_SIZE; ++idx, listP += 10) { + _list[idx]._id = READ_LE_UINT16(listP); + _list[idx]._scriptOffset = READ_LE_UINT16(listP + 2); + } + + _speakerOffset = READ_LE_UINT16(dataP + 0x42); +} + +void Obj44::synchronise(Serialiser &s) { + s.syncAsSint32LE(_id); + for (int i = 0; i < OBJ44_LIST_SIZE; ++i) + s.syncAsSint32LE(_field2[i]); + for (int i = 0; i < OBJ44_LIST_SIZE; ++i) + _list[OBJ44_LIST_SIZE].synchronise(s); + s.syncAsUint32LE(_speakerOffset); +} + +/*--------------------------------------------------------------------------*/ + +StripManager::StripManager() { + _callbackObject = NULL; + _activeSpeaker = NULL; + reset(); +} + +StripManager::~StripManager() { +} + +void StripManager::start(int stripNum, EventHandler *owner, StripCallback *callback) { + reset(); + + _stripNum = stripNum; + _callbackObject = callback; + _sceneNumber = _globals->_sceneManager._sceneNumber; + _sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + _script.clear(); + + assert(owner); + owner->setAction(this, owner); +} + +void StripManager::reset() { + _actionIndex = 0; + _delayFrames = 0; + _owner = NULL; + _fmt = NULL; + _field2E6 = false; + _stripNum = -1; + _obj44Index = 0; + _field2E8 = 0; + _field20 = 0; + _activeSpeaker = NULL; + _textShown = false; + _callbackObject = NULL; + + _obj44List.clear(); + if (!_script.empty()) { + _script.clear(); + } +} + +void StripManager::load() { + // Get the script + byte *script = _vm->_dataManager->getResource(RES_STRIP, _stripNum, 2); + uint scriptSize = _vm->_memoryManager.getSize(script); + + _script.resize(scriptSize); + Common::copy(script, script + scriptSize, &_script[0]); + + DEALLOCATE(script); + + // Get the object list + byte *obj44List = _vm->_dataManager->getResource(RES_STRIP, _stripNum, 1); + int dataSize = _vm->_memoryManager.getSize(obj44List); + assert((dataSize % 0x44) == 0); + + byte *dataP = obj44List; + for (int idx = 0; idx < (dataSize / 0x44); ++idx, dataP += 0x44) { + Obj44 obj; + obj.load(dataP); + _obj44List.push_back(obj); + } + + DEALLOCATE(obj44List); +} + +void StripManager::synchronise(Serialiser &s) { + s.syncAsSint32LE(_stripNum); + s.syncAsSint32LE(_obj44Index); + s.syncAsSint32LE(_field20); + s.syncAsSint32LE(_sceneNumber); + _sceneBounds.synchronise(s); + SYNC_POINTER(_activeSpeaker); + s.syncAsByte(_textShown); + s.syncAsByte(_field2E6); + s.syncAsSint32LE(_field2E8); + + // Synchronise the item list + int arrSize = _obj44List.size(); + s.syncAsUint16LE(arrSize); + if (s.isLoading()) + _obj44List.resize(arrSize); + for (int i = 0; i < arrSize; ++i) + _obj44List[i].synchronise(s); + + // Synhcronise script data + int scriptSize = _script.size(); + s.syncAsUint16LE(scriptSize); + if (s.isLoading()) + _script.resize(scriptSize); + if (scriptSize > 0) + s.syncBytes(&_script[0], scriptSize); + + // Add speaker list + arrSize = _speakerList.size(); + s.syncAsUint16LE(arrSize); + if (s.isLoading()) + _speakerList.resize(arrSize); + for (int i = 0; i < arrSize; ++i) + SYNC_POINTER(_speakerList[i]); + + SYNC_POINTER(_callbackObject); +} + +void StripManager::remove() { + if (_textShown) { + if (_activeSpeaker) + _activeSpeaker->removeText(); + _textShown = false; + } + + if (_activeSpeaker) + _activeSpeaker->remove(); + + if (_sceneNumber != _globals->_sceneManager._scene->_sceneNumber) { + _globals->_sceneManager._scene->_sceneBounds = _sceneBounds; + _globals->_sceneManager._scene->loadScene(_sceneNumber); + } + + Action::remove(); +} + +void StripManager::signal() { + if (_textShown) { + _activeSpeaker->removeText(); + _textShown = false; + } + + if (_obj44Index < 0) { + EventHandler *owner = _fmt; + int stripNum = ABS(_obj44Index); + remove(); + + start(stripNum, owner); + return; + } else if (_obj44Index == 10000) { + // Reached end of strip + remove(); + return; + } + + // Run strip + + if (_obj44List.size() == 0) + // Load the data for the strip + load(); + + Obj44 &obj44 = _obj44List[_obj44Index]; + _field2E8 = obj44._id; + Common::StringArray choiceList; + + // Build up a list of script entries + int idx; + for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) { + if (!obj44._list[idx]._id) + break; + + // Get the next one + choiceList.push_back((const char *)&_script[0] + obj44._list[idx]._scriptOffset); + } + + int strIndex = 0; + if (choiceList.size() > 1) + // Get the user to select a conversation option + strIndex = _choiceDialog.execute(choiceList); + + if ((choiceList.size() != 1) && !_field2E6) + _delayFrames = 1; + else { + Speaker *speakerP = getSpeaker((const char *)&_script[0] + obj44._speakerOffset); + if (!speakerP) + error("Speaker not found. Screenplay: %s %d", (const char *)&_script[0] + obj44._speakerOffset, _stripNum); + + if (speakerP != _activeSpeaker) { + if (_activeSpeaker) + _activeSpeaker->remove(); + _activeSpeaker = speakerP; + + if ((_activeSpeaker->_newSceneNumber == -1) && (_globals->_sceneManager._scene->_sceneNumber != _sceneNumber)) { + _globals->_sceneManager._scene->_sceneBounds = _sceneBounds; + _globals->_sceneManager._scene->loadScene(_sceneNumber); + } + + _activeSpeaker->proc12(this); + } + + if (_callbackObject) { + for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) { + if (!obj44._field2[idx]) + break; + + _callbackObject->stripCallback(obj44._field2[idx]); + } + } + + _textShown = true; + _activeSpeaker->setText(choiceList[strIndex]); + } + + _obj44Index = getNewIndex(obj44._list[strIndex]._id); + if (_obj44Index == 10001) { + MessageDialog::show("Strip Failure: Node not found", OK_BTN_STRING); + _obj44Index = 0; + } +} + +void StripManager::process(Event &event) { + Action::process(event); + if (event.handled) + return; + + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) { + if (_obj44Index != 10000) { + int currIndex = _obj44Index; + while (!_obj44List[_obj44Index + 1]._id) { + _obj44Index = getNewIndex(_obj44List[_obj44Index]._id); + if ((_obj44Index < 0) || (_obj44Index == 10000)) + break; + currIndex = _obj44Index; + } + + _field2E8 = _obj44List[currIndex]._id; + } + + // Signal the end of the strip + _delayFrames = 0; + event.handled = true; + signal(); + } else if (event.eventType & (EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) { + // Move to next sequence in the strip + _delayFrames = 0; + event.handled = true; + signal(); + } +} + +void StripManager::addSpeaker(Speaker *speaker) { + assert(_speakerList.size() < 100); + _speakerList.push_back(speaker); +} + +Speaker *StripManager::getSpeaker(const char *speakerName) { + for (uint idx = 0; idx < _speakerList.size(); ++idx) { + if (!strcmp(_speakerList[idx]->_speakerName.c_str(), speakerName)) + return _speakerList[idx]; + } + + return NULL; +} + +int StripManager::getNewIndex(int id) { + if (id == 10000) + return id; + + for (uint idx = 0; idx < _obj44List.size(); ++idx) { + if (_obj44List[idx]._id == id) { + return (id == 0) ? 10001 : idx; + } + } + + return 10001; +} + +/*--------------------------------------------------------------------------*/ + +Speaker::Speaker() : EventHandler() { + _newSceneNumber = -1; + _hideObjects = true; + _field18 = 0; + _textWidth = 140; + _textPos = Common::Point(10, 20); + _fontNumber = 2; + _textMode = ALIGN_LEFT; + _colour1 = _colour2 = _colour3 = _globals->_scenePalette._colours.foreground; + _action = NULL; + _speakerName = "SPEAKER"; +} + +void Speaker::synchronise(Serialiser &s) { + _fieldA.synchronise(s); + SYNC_POINTER(_field18); + s.syncString(_speakerName); + s.syncAsSint32LE(_newSceneNumber); + s.syncAsSint32LE(_oldSceneNumber); + _sceneBounds.synchronise(s); + s.syncAsSint32LE(_textWidth); + s.syncAsSint16LE(_textPos.x); s.syncAsSint16LE(_textPos.y); + s.syncAsSint32LE(_fontNumber); + SYNC_ENUM(_textMode, TextAlign); + s.syncAsSint16LE(_colour1); + s.syncAsSint16LE(_colour2); + s.syncAsSint16LE(_colour3); + s.syncAsByte(_hideObjects); +} + +void Speaker::remove() { + if (_hideObjects) + SceneObjectList::deactivate(); +} + +void Speaker::proc12(Action *action) { + _action = action; + if (_newSceneNumber != -1) { + _oldSceneNumber = _globals->_sceneManager._sceneNumber; + _sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + _globals->_sceneManager._scene->loadScene(_newSceneNumber); + } + + if (_hideObjects) + // Activate the object list for display + _objectList.activate(); + + // Draw the speaker objects without any fading + FadeMode fadeMode = _globals->_sceneManager._fadeMode; + _globals->_sceneManager._fadeMode = FADEMODE_IMMEDIATE; + _globals->_sceneObjects->draw(); + _globals->_sceneManager._fadeMode = fadeMode; +} + +void Speaker::setText(const Common::String &msg) { + _globals->_sceneObjects->draw(); + + _sceneText._colour1 = _colour1; + _sceneText._colour2 = _colour2; + _sceneText._colour3 = _colour3; + _sceneText._width = _textWidth; + _sceneText._fontNumber = _fontNumber; + _sceneText._textMode = _textMode; + _sceneText.setup(msg); + _sceneText.setPosition(_textPos); + _sceneText.setPriority2(256); + + // Count the number of words (by spaces) in the string + const char *msgP = msg.c_str(); + int spaceCount = 0; + while (*msgP) { + if (*msgP++ == ' ') + ++spaceCount; + } + + int numFrames = spaceCount * STRIP_WORD_DELAY + 120; + if (_action) + _action->setDelay(numFrames); +} + +void Speaker::removeText() { + _sceneText.remove(); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerGameText::SpeakerGameText() : Speaker() { + _speakerName = "GAMETEXT"; + _textPos = Common::Point(40, 40); + _textMode = ALIGN_CENTRE; + _colour1 = 7; + _textWidth = 230; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +ScreenSpeaker::ScreenSpeaker() : Speaker() { + _npc = NULL; + _textMode = ALIGN_CENTRE; +} + +void ScreenSpeaker::setText(const Common::String &msg) { + GfxManager gfxMan; + gfxMan.activate(); + gfxMan._font.setFontNumber(_fontNumber); + Rect textRect; + + _globals->gfxManager().getStringBounds(msg.c_str(), textRect, _textWidth); + if (_npc) { + textRect.centre(_npc->_position.x, _npc->_bounds.top - (textRect.height() / 2 + 10)); + } else { + textRect.centre(_globals->_sceneManager._scene->_sceneBounds.left + + (_globals->_sceneManager._scene->_sceneBounds.width() / 2), + _globals->_sceneManager._scene->_sceneBounds.top); + } + + Rect rect2 = _globals->_sceneManager._scene->_sceneBounds; + rect2.collapse(10, 6); + textRect.contain(rect2); + + _textPos.x = textRect.left; + _textPos.y = textRect.top; + Speaker::setText(msg); + + gfxMan.deactivate(); +} + +/*--------------------------------------------------------------------------*/ + +void SpeakerAction::signal() { + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(60) + 60); + break; + case 1: + static_cast<SceneObject *>(_owner)->setFrame(1); + static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_5, this, NULL); + break; + case 2: + setDelay(_globals->_randomSource.getRandomNumber(10)); + _actionIndex = 0; + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void AnimatedSpeaker::removeText() { + Speaker::removeText(); + _object1.remove(); + _object2.remove(); + + _objectList.draw(); +} + +} // end of namespace tSage diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h new file mode 100644 index 0000000000..4d6e51a6b8 --- /dev/null +++ b/engines/tsage/converse.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_CONVERSE_H +#define TSAGE_CONVERSE_H + +#include "tsage/core.h" +#include "tsage/dialogs.h" + +namespace tSage { + +class StripCallback : public Action { +public: + virtual void stripCallback(int v) = 0; +}; + +class SequenceManager : public Action { +private: + void setup(); + uint16 getNextValue(); + void setMessage(int resNum, int lineNum, int colour, const Common::Point &pt, int width); + SequenceManager *globalManager(); +public: + SceneText _sceneText; + int _resNum; + uint _sequenceOffset; + bool _keepActive; + int _field24; + int _field26; + Common::Array<byte> _sequenceData; + int _objectIndex; + SceneObject *_sceneObject; + SceneObject *_objectList[6]; + SoundHandler _soundHandler; +public: + SequenceManager(); + + virtual Common::String getClassName() { return "SequenceManager"; } + virtual void synchronise(Serialiser &s); + virtual void remove(); + virtual void signal(); + virtual void process(Event &event); + virtual void attached(EventHandler *newOwner, EventHandler *fmt, va_list va); +}; + + +class Speaker : public EventHandler { +public: + Rect _fieldA; + Action *_field18; + Common::String _speakerName; + int _newSceneNumber; + int _oldSceneNumber; + SceneObjectList _objectList; + Rect _sceneBounds; + SceneText _sceneText; + int _textWidth; + Common::Point _textPos; + int _fontNumber; + TextAlign _textMode; + int _colour1, _colour2, _colour3; + bool _hideObjects; +public: + Speaker(); + + virtual Common::String getClassName() { return "Speaker"; } + virtual void synchronise(Serialiser &s); + virtual void remove(); + virtual void proc12(Action *action); + virtual void setText(const Common::String &msg); + virtual void removeText(); + + void setTextPos(const Common::Point &pt) { _textPos = pt; } +}; + +class SpeakerGameText : public Speaker { +public: + SpeakerGameText(); + + virtual Common::String getClassName() { return "SpeakerGameText"; } +}; + +class ScreenSpeaker : public Speaker { +public: + SceneItem *_npc; +public: + ScreenSpeaker(); + + virtual Common::String getClassName() { return "ScreenSpeaker"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerAction : public Action { +public: + virtual void signal(); + + virtual Common::String getClassName() { return "SpeakerAction"; } +}; + +class AnimatedSpeaker : public Speaker { +public: + SceneObject _object1; + SceneObject _object2; + SpeakerAction _speakerAction; +public: + virtual Common::String getClassName() { return "AnimatedSpeaker"; } + virtual void removeText(); +}; + +class ChoiceEntry { +public: + Common::String _msg; + Rect _bounds; + + ChoiceEntry() {} + ChoiceEntry(const Common::String &msg, const Rect &bounds) { + _msg = msg; + _bounds = bounds; + } +}; + +class ConversationChoiceDialog : public ModalDialog { +public: + int _stdColour; + int _highlightColour; + int _fontNumber; + int _savedFgColour; + int _savedFontNumber; + Common::Array<ChoiceEntry> _choiceList; + uint _selectedIndex; +public: + ConversationChoiceDialog(); + + void setColours(int stdColour, int highlightColour) { + _stdColour = stdColour; + _highlightColour = highlightColour; + } + void setFontNumber(int fontNum) { _fontNumber = fontNum; } + int execute(const Common::StringArray &choiceList); + + virtual void draw(); +}; + +class Obj0A : public Serialisable { +public: + int _id; + uint _scriptOffset; + + virtual void synchronise(Serialiser &s) { + s.syncAsSint32LE(_id); + s.syncAsUint32LE(_scriptOffset); + } +}; + +#define OBJ44_LIST_SIZE 5 + +class Obj44 : public Serialisable { +public: + int _id; + int _field2[OBJ44_LIST_SIZE]; + Obj0A _list[OBJ44_LIST_SIZE]; + uint _speakerOffset; +public: + void load(const byte *dataP); + virtual void synchronise(Serialiser &s); +}; + +class StripManager : public Action { +private: + void reset(); + void load(); + Speaker *getSpeaker(const char *speakerName); + int getNewIndex(int newId); +public: + int _stripNum; + int _obj44Index; + int _field20; + int _sceneNumber; + Rect _sceneBounds; + ConversationChoiceDialog _choiceDialog; + Common::Array<Speaker *> _speakerList; + StripCallback *_callbackObject; + Speaker *_activeSpeaker; + bool _textShown; + bool _field2E6; + int _field2E8; + Common::Array<Obj44> _obj44List; + Common::Array<byte> _script; +public: + StripManager(); + virtual ~StripManager(); + + virtual void synchronise(Serialiser &s); + virtual void remove(); + virtual void signal(); + virtual void process(Event &event); + + void start(int stripNum, EventHandler *owner, StripCallback *callback = NULL); + void setCallback(StripCallback *callback) { _callbackObject = callback; } + void setColours(int stdColour, int highlightColour) { _choiceDialog.setColours(stdColour, highlightColour); } + void setFontNumber(int fontNum) { _choiceDialog.setFontNumber(fontNum); } + void addSpeaker(Speaker *speaker); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp new file mode 100644 index 0000000000..81088b4eaa --- /dev/null +++ b/engines/tsage/core.cpp @@ -0,0 +1,3735 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/system.h" +#include "common/config-manager.h" +#include "common/translation.h" +#include "engines/engine.h" +#include "gui/saveload.h" +#include "tsage/tsage.h" +#include "tsage/core.h" +#include "tsage/dialogs.h" +#include "tsage/events.h" +#include "tsage/scenes.h" +#include "tsage/staticres.h" +#include "tsage/globals.h" + +namespace tSage { + +// The engine uses ScumMVM screen buffering, so all logic is hardcoded to use pane buffer 0 +#define CURRENT_PANENUM 0 + +/*--------------------------------------------------------------------------*/ + +InvObject::InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description) : + _sceneNumber(sceneNumber), _rlbNum(rlbNum), _cursorNum(cursorNum), _cursorId(cursorId), + _description(description) { + _displayResNum = 3; + _iconResNum = 5; + + // Decode the image for the inventory item to get it's display bounds + uint size; + byte *imgData = _vm->_dataManager->getSubResource(_displayResNum, _rlbNum, _cursorNum, &size); + GfxSurface s = surfaceFromRes(imgData); + _bounds = s.getBounds(); + + DEALLOCATE(imgData); +} + +void InvObject::setCursor() { + _globals->_events._currentCursor = _cursorId; + + if (_iconResNum != -1) { + GfxSurface s = surfaceFromRes(_iconResNum, _rlbNum, _cursorNum); + + Graphics::Surface src = s.lockSurface(); + _globals->_events.setCursor(src, s._transColour, s._centroid, _cursorId); + } +} + +/*--------------------------------------------------------------------------*/ + +InvObjectList::InvObjectList() : + _stunner(2280, 1, 2, OBJECT_STUNNER, "This is your stunner."), + _scanner(1, 1, 3, OBJECT_SCANNER, "A combination scanner comm unit."), + _stasisBox(5200, 1, 4, OBJECT_STASIS_BOX, "A stasis box."), + _infoDisk(40, 1, 1, OBJECT_INFODISK, "The infodisk you took from the assassin."), + _stasisNegator(0, 2, 2, OBJECT_STASIS_NEGATOR, "The stasis field negator."), + _keyDevice(4250, 1, 6, OBJECT_KEY_DEVICE, "A magnetic key device."), + _medkit(2280, 1, 7, OBJECT_MEDKIT, "Your medkit."), + _ladder(4100, 1, 8, OBJECT_LADDER, "The chief's ladder."), + _rope(4150, 1, 9, OBJECT_ROPE, "The chief's rope."), + _key(7700, 1, 11, OBJECT_KEY, "A key."), + _translator(7700, 1, 13, OBJECT_TRANSLATOR, "The dolphin translator box."), + _ale(2150, 1, 10, OBJECT_ALE, "A bottle of ale."), + _paper(7700, 1, 12, OBJECT_PAPER, "A slip of paper with the numbers 2,4, and 3 written on it."), + _waldos(0, 1, 14, OBJECT_WALDOS, "A pair of waldos from the ruined probe."), + _stasisBox2(8100, 1, 4, OBJECT_STASIS_BOX2, "A stasis box."), + _ring(8100, 2, 5, OBJECT_RING, "This is a signet ring sent to you by Louis Wu."), + _cloak(9850, 2, 6, OBJECT_CLOAK, "A fine silk cloak."), + _tunic(9450, 2, 7, OBJECT_TUNIC, "The patriarch's soiled tunic."), + _candle(9500, 2, 8, OBJECT_CANDLE, "A tallow candle."), + _straw(9400, 2, 9, OBJECT_STRAW, "Clean, dry straw."), + _scimitar(9850, 1, 18, OBJECT_SCIMITAR, "A scimitar from the Patriarch's closet."), + _sword(9850, 1, 17, OBJECT_SWORD, "A short sword from the Patriarch's closet."), + _helmet(9500, 2, 4, OBJECT_HELMET, "Some type of helmet."), + _items(4300, 2, 10, OBJECT_ITEMS, "Two interesting items from the Tnuctipun vessel."), + _concentrator(4300, 2, 11, OBJECT_CONCENTRATOR, "The Tnuctipun anti-matter concentrator contained in a stasis field."), + _nullifier(5200, 2, 12, OBJECT_NULLIFIER, "A purported neural wave nullifier."), + _peg(4045, 2, 16, OBJECT_PEG, "A peg with a symbol."), + _vial(5100, 2, 17, OBJECT_VIAL, "A vial of the bat creatures anti-pheromone drug."), + _jacket(9850, 3, 1, OBJECT_JACKET, "A natty padded jacket."), + _tunic2(9850, 3, 2, OBJECT_TUNIC2, "A very hairy tunic."), + _bone(5300, 3, 5, OBJECT_BONE, "A very sharp bone."), + _jar(7700, 3, 4, OBJECT_JAR, "An jar filled with a green substance."), + _emptyJar(7700, 3, 3, OBJECT_EMPTY_JAR, "An empty jar.") { + + // Add the items to the list + _itemList.push_back(&_stunner); + _itemList.push_back(&_scanner); + _itemList.push_back(&_stasisBox); + _itemList.push_back(&_infoDisk); + _itemList.push_back(&_stasisNegator); + _itemList.push_back(&_keyDevice); + _itemList.push_back(&_medkit); + _itemList.push_back(&_ladder); + _itemList.push_back(&_rope); + _itemList.push_back(&_key); + _itemList.push_back(&_translator); + _itemList.push_back(&_ale); + _itemList.push_back(&_paper); + _itemList.push_back(&_waldos); + _itemList.push_back(&_stasisBox2); + _itemList.push_back(&_ring); + _itemList.push_back(&_cloak); + _itemList.push_back(&_tunic); + _itemList.push_back(&_candle); + _itemList.push_back(&_straw); + _itemList.push_back(&_scimitar); + _itemList.push_back(&_sword); + _itemList.push_back(&_helmet); + _itemList.push_back(&_items); + _itemList.push_back(&_concentrator); + _itemList.push_back(&_nullifier); + _itemList.push_back(&_peg); + _itemList.push_back(&_vial); + _itemList.push_back(&_jacket); + _itemList.push_back(&_tunic2); + _itemList.push_back(&_bone); + _itemList.push_back(&_jar); + _itemList.push_back(&_emptyJar); + + _selectedItem = NULL; +} + +void InvObjectList::synchronise(Serialiser &s) { + SavedObject::synchronise(s); + SYNC_POINTER(_selectedItem); +} + +/*--------------------------------------------------------------------------*/ + +void EventHandler::dispatch() { + if (_action) _action->dispatch(); +} + +void EventHandler::setAction(Action *action, EventHandler *fmt, ...) { + if (_action) { + _action->_fmt = NULL; + _action->remove(); + } + + _action = action; + if (action) { + va_list va; + va_start(va, fmt); + _action->attached(this, fmt, va); + va_end(va); + } +} + +/*--------------------------------------------------------------------------*/ + +Action::Action() { + _actionIndex = 0; + _owner = NULL; + _fmt = NULL; +} + +void Action::synchronise(Serialiser &s) { + EventHandler::synchronise(s); + if (s.isLoading()) + remove(); + + SYNC_POINTER(_owner); + s.syncAsSint32LE(_actionIndex); + s.syncAsSint32LE(_delayFrames); + s.syncAsUint32LE(_startFrame); + s.syncAsSint16LE(_field16); + SYNC_POINTER(_fmt); +} + +void Action::remove() { + if (_action) + _action->remove(); + + if (_owner) { + _owner->_action = NULL; + _owner = NULL; + } else { + _globals->_sceneManager.removeAction(this); + } + + _field16 = 0; + if (_fmt) + _fmt->signal(); +} + +void Action::process(Event &event) { + if (_action) + _action->process(event); +} + +void Action::dispatch() { + if (_action) + _action->dispatch(); + + if (_delayFrames) { + uint32 frameNumber = _globals->_events.getFrameNumber(); + + if (frameNumber >= _startFrame) { + _delayFrames -= frameNumber - _startFrame; + _startFrame = frameNumber; + if (_delayFrames <= 0) { + _delayFrames = 0; + signal(); + } + } + } +} + +void Action::attached(EventHandler *newOwner, EventHandler *fmt, va_list va) { + _actionIndex = 0; + _delayFrames = 0; + _startFrame = _globals->_events.getFrameNumber(); + _owner = newOwner; + _fmt = fmt; + _field16 = 1; + signal(); +} + +void Action::setDelay(int numFrames) { + _delayFrames = numFrames; + _startFrame = _globals->_events.getFrameNumber(); +} + +/*--------------------------------------------------------------------------*/ + +ObjectMover::~ObjectMover() { + if (_sceneObject->_mover == this) + _sceneObject->_mover = NULL; +} + +void ObjectMover::synchronise(Serialiser &s) { + EventHandler::synchronise(s); + + s.syncAsSint16LE(_destPosition.x); s.syncAsSint16LE(_destPosition.y); + s.syncAsSint16LE(_moveDelta.x); s.syncAsSint16LE(_moveDelta.y); + s.syncAsSint16LE(_moveSign.x); s.syncAsSint16LE(_moveSign.y); + s.syncAsSint32LE(_minorDiff); + s.syncAsSint32LE(_majorDiff); + s.syncAsSint32LE(_field1A); + SYNC_POINTER(_action); + SYNC_POINTER(_sceneObject); +} + +void ObjectMover::remove() { + if (_sceneObject->_mover == this) + _sceneObject->_mover = NULL; + + delete this; +} + +void ObjectMover::dispatch() { + Common::Point currPos = _sceneObject->_position; + int yDiff = _sceneObject->_yDiff; + + if (dontMove()) + return; + + _sceneObject->_regionIndex = 0; + if (_moveDelta.x >= _moveDelta.y) { + int xAmount = _moveSign.x * _sceneObject->_moveDiff.x * _sceneObject->_percent / 100; + if (!xAmount) + xAmount = _moveSign.x; + currPos.x += xAmount; + + int yAmount = ABS(_destPosition.y - currPos.y); + int yChange = _majorDiff / ABS(xAmount); + int ySign; + + if (!yChange) + ySign = _moveSign.y; + else { + int v = yAmount / yChange; + _field1A += yAmount % yChange; + if (_field1A >= yChange) { + ++v; + _field1A -= yChange; + } + + ySign = _moveSign.y * v; + } + + currPos.y += ySign; + _majorDiff -= ABS(xAmount); + + } else { + int yAmount = _moveSign.y * _sceneObject->_moveDiff.y * _sceneObject->_percent / 100; + if (!yAmount) + yAmount = _moveSign.y; + currPos.y += yAmount; + + int xAmount = ABS(_destPosition.x - currPos.x); + int xChange = _majorDiff / ABS(yAmount); + int xSign; + + if (!xChange) + xSign = _moveSign.x; + else { + int v = xAmount / xChange; + _field1A += xAmount % xChange; + if (_field1A >= xChange) { + ++v; + _field1A -= xChange; + } + + xSign = _moveSign.x * v; + } + + currPos.x += xSign; + _majorDiff -= ABS(yAmount); + } + + _sceneObject->_regionIndex = _sceneObject->checkRegion(currPos); + if (!_sceneObject->_regionIndex) { + _sceneObject->setPosition(currPos, yDiff); + _sceneObject->getHorizBounds(); + + if (dontMove()) { + _sceneObject->_position = _destPosition; + endMove(); + } + } else { + endMove(); + } +} + +void ObjectMover::setup(const Common::Point &destPos) { + _sceneObject->calcAngle(destPos); + + if ((_sceneObject->_objectWrapper) && !(_sceneObject->_flags & OBJFLAG_SUPPRESS_DISPATCH)) + _sceneObject->_objectWrapper->dispatch(); + + // Get the difference + int diffX = destPos.x - _sceneObject->_position.x; + int diffY = destPos.y - _sceneObject->_position.y; + int xSign = (diffX < 0) ? -1 : (diffX > 0 ? 1 : 0); + int ySign = (diffY < 0) ? -1 : (diffY > 0 ? 1 : 0); + diffX = ABS(diffX); + diffY = ABS(diffY); + + if (diffX < diffY) { + _minorDiff = diffX / 2; + _majorDiff = diffY; + } else { + _minorDiff = diffY / 2; + _majorDiff = diffX; + } + + // Set the destination position + _destPosition = destPos; + _moveDelta = Common::Point(diffX, diffY); + _moveSign = Common::Point(xSign, ySign); + _field1A = 0; + + if (!diffX && !diffY) + // Object is already at the correct destination + endMove(); +} + +bool ObjectMover::dontMove() const { + return (_majorDiff <= 0); +} + +void ObjectMover::endMove() { + EventHandler *actionP = _action; + remove(); + + if (actionP) + actionP->signal(); +} + +/*--------------------------------------------------------------------------*/ + +ObjectMover2::ObjectMover2() : ObjectMover() { + _destObject = NULL; +} + +void ObjectMover2::synchronise(Serialiser &s) { + ObjectMover::synchronise(s); + + SYNC_POINTER(_destObject); + s.syncAsSint32LE(_minArea); + s.syncAsSint32LE(_maxArea); +} + +void ObjectMover2::dispatch() { + int area = _sceneObject->getSpliceArea(_destObject); + if (area > _maxArea) { + // Setup again for the new destination + setup(_destObject->_position); + ObjectMover::dispatch(); + } else if (area >= _minArea) { + // Keep dispatching + ObjectMover::dispatch(); + } else { + // Within minimum, so end move + endMove(); + } +} + +void ObjectMover2::startMove(SceneObject *sceneObj, va_list va) { + // Set up fields + _sceneObject = sceneObj; + + _minArea = va_arg(va, int); + _maxArea = va_arg(va, int); + _destObject = va_arg(va, SceneObject *); + + setup(_destObject->_position); +} + +void ObjectMover2::endMove() { + _sceneObject->_regionIndex = 0x40; +} + +/*--------------------------------------------------------------------------*/ + +void ObjectMover3::dispatch() { + int area = _sceneObject->getSpliceArea(_destObject); + if (area <= _minArea) { + endMove(); + } else { + setup(_destObject->_position); + ObjectMover::dispatch(); + } +} + +void ObjectMover3::startMove(SceneObject *sceneObj, va_list va) { + _sceneObject = sceneObj; + _destObject = va_arg(va, SceneObject *); + _minArea = va_arg(va, int); + _action = va_arg(va, Action *); + + setup(_destObject->_position); +} + +void ObjectMover3::endMove() { + ObjectMover::endMove(); +} + +/*--------------------------------------------------------------------------*/ + +void NpcMover::startMove(SceneObject *sceneObj, va_list va) { + _sceneObject = sceneObj; + + Common::Point *destPos = va_arg(va, Common::Point *); + _action = va_arg(va, Action *); + + setup(*destPos); +} + +/*--------------------------------------------------------------------------*/ + +void PlayerMover::synchronise(Serialiser &s) { + NpcMover::synchronise(s); + + s.syncAsSint16LE(_finalDest.x); s.syncAsSint16LE(_finalDest.y); + s.syncAsSint32LE(_routeIndex); + + for (int i = 0; i < MAX_ROUTE_SIZE; ++i) { + s.syncAsSint16LE(_routeList[i].x); s.syncAsSint16LE(_routeList[i].y); + } +} + +void PlayerMover::startMove(SceneObject *sceneObj, va_list va) { + _sceneObject = sceneObj; + Common::Point *pt = va_arg(va, Common::Point *); + _finalDest = *pt; + _action = va_arg(va, Action *); + + setDest(_finalDest); +} + +void PlayerMover::endMove() { + while (++_routeIndex != 0) { + if ((_routeList[_routeIndex].x == ROUTE_END_VAL) || + (_routeList[_routeIndex].y == ROUTE_END_VAL) || + (_sceneObject->_regionIndex)) { + // Movement route is completely finished + ObjectMover::endMove(); + return; + } + + if ((_routeList[_routeIndex].x != _sceneObject->_position.x) || + (_routeList[_routeIndex].y != _sceneObject->_position.y)) + break; + } + + // Set up the new interim destination along the route + _globals->_walkRegions._routeEnds.moveSrc = _globals->_walkRegions._routeEnds.moveDest; + _globals->_walkRegions._routeEnds.moveDest = _routeList[_routeIndex]; + setup(_routeList[_routeIndex]); + dispatch(); +} + +void PlayerMover::setDest(const Common::Point &destPos) { + _routeList[0] = _sceneObject->_position; + + if (_globals->_walkRegions._resNum == -1) { + // Scene has no walk regions defined, so player can walk anywhere directly + _routeList[0] = destPos; + _routeList[1] = Common::Point(ROUTE_END_VAL, ROUTE_END_VAL); + } else { + // Figure out a path to the destination (or as close as possible to it) + pathfind(_routeList, _sceneObject->_position, destPos, _globals->_walkRegions._routeEnds); + } + + _routeIndex = 0; + _globals->_walkRegions._routeEnds.moveSrc = _sceneObject->_position; + _globals->_walkRegions._routeEnds.moveDest = _routeList[0]; + setup(_routeList[0]); +} + +#define REGION_LIST_SIZE 20 + +void PlayerMover::pathfind(Common::Point *routeList, Common::Point srcPos, Common::Point destPos, RouteEnds routeEnds) { + Common::List<int> regionIndexes; + RouteEnds tempRouteEnds; + int routeRegions[REGION_LIST_SIZE]; + Common::Point objPos; + + // Get the region the source is in + int srcRegion = _globals->_walkRegions.indexOf(srcPos); + if (srcRegion == -1) { + srcRegion = findClosestRegion(srcPos, regionIndexes); + } + + // Main loop for building up the path + routeRegions[0] = 0; + while (!routeRegions[0]) { + // Check the destination region + int destRegion = _globals->_walkRegions.indexOf(destPos, ®ionIndexes); + + if ((srcRegion == -1) && (destRegion == -1)) { + // Both source and destination are outside walkable areas + } else if (srcRegion == -1) { + // Source is outside walkable areas + tempRouteEnds = routeEnds; + objPos = _sceneObject->_position; + + Common::Point newPos; + findLinePoint(&tempRouteEnds, &objPos, 1, &newPos); + int srcId = _globals->_walkRegions.indexOf(newPos); + + if (srcId == -1) { + tempRouteEnds.moveDest = tempRouteEnds.moveSrc; + tempRouteEnds.moveSrc = routeEnds.moveDest; + + findLinePoint(&tempRouteEnds, &objPos, 1, &newPos); + srcRegion = _globals->_walkRegions.indexOf(newPos); + + if (srcRegion == -1) + srcRegion = checkMover(srcPos, destPos); + } + + } else if (destRegion == -1) { + // Destination is outside walkable areas + destRegion = findClosestRegion(destPos, regionIndexes); + if (destRegion == -1) { + // No further route found, so end it + *routeList++ = srcPos; + break; + } else { + _finalDest = destPos; + } + } + + if (srcRegion == destRegion) { + *routeList++ = (srcRegion == -1) ? srcPos : destPos; + break; + } + + int var6; + proc1(routeRegions, srcRegion, destRegion, var6); + + if (!routeRegions[0]) { + regionIndexes.push_back(destRegion); + continue; + } + + _globals->_walkRegions._field18[0]._pt1 = srcPos; + _globals->_walkRegions._field18[0]._pt2 = srcPos; + _globals->_walkRegions._field18[1]._pt1 = destPos; + _globals->_walkRegions._field18[1]._pt2 = destPos; + + int tempList[REGION_LIST_SIZE]; + tempList[0] = 0; + int endIndex = 0; + int idx = 1; + + do { + int breakEntry = routeRegions[idx]; + int breakEntry2 = routeRegions[idx + 1]; + + int listIndex = 0; + while (_globals->_walkRegions._idxList[_globals->_walkRegions[breakEntry]._idxListIndex + listIndex] != + breakEntry2) + ++listIndex; + + tempList[idx] = _globals->_walkRegions._idxList2[_globals->_walkRegions[breakEntry]._idxList2Index + + listIndex]; + + ++endIndex; + } while (routeRegions[++idx] != destRegion); + + tempList[idx] = 1; + idx = 0; + for (int listIndex = 1; listIndex <= endIndex; ++listIndex) { + int var10 = tempList[listIndex]; + int var12 = tempList[listIndex + 1]; + + if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt1, + _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2) && + sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var12]._pt2, + _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2)) + continue; + + Common::Point tempPt; + if (sub_F8E5(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[1]._pt1, + _globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var10]._pt2, &tempPt)) { + // Add point to the route list + _globals->_walkRegions._field18[0]._pt1 = tempPt; + *routeList++ = tempPt; + } else { + int v16 = + (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt1) << 1) + + (findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[1]._pt1) << 1) + + findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt1) + + findDistance(_globals->_walkRegions._field18[var10]._pt1, _globals->_walkRegions._field18[var12]._pt2); + + int v1A = + (findDistance(_globals->_walkRegions._field18[0]._pt1, _globals->_walkRegions._field18[var10]._pt2) << 1) + + (findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[1]._pt2) << 1) + + findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt1) + + findDistance(_globals->_walkRegions._field18[var10]._pt2, _globals->_walkRegions._field18[var12]._pt2); + + if (v16 < v1A) { + checkMovement2(_globals->_walkRegions._field18[var10]._pt1, + _globals->_walkRegions._field18[var10]._pt2, 1, objPos); + } else { + checkMovement2(_globals->_walkRegions._field18[var10]._pt2, + _globals->_walkRegions._field18[var10]._pt1, 1, objPos); + } + + _globals->_walkRegions._field18[0]._pt1 = objPos; + *routeList++ = objPos; + } + } + + // Add in the route entry + *routeList++ = _globals->_walkRegions._field18[1]._pt1; + } + + // Mark the end of the path + *routeList = Common::Point(ROUTE_END_VAL, ROUTE_END_VAL); +} + +int PlayerMover::regionIndexOf(const Common::Point &pt) { + for (uint idx = 0; idx < _globals->_walkRegions._regionList.size(); ++idx) { + if (_globals->_walkRegions._regionList[idx].contains(pt)) + return idx + 1; + } + + return 0; +} + +int PlayerMover::findClosestRegion(Common::Point &pt, const Common::List<int> &indexList) { + int newY = pt.y; + int result = 0; + + for (int idx = 1; idx < SCREEN_WIDTH; ++idx, newY += idx) { + int newX = pt.x + idx; + result = regionIndexOf(newX, pt.y); + + if ((result == 0) || contains(indexList, result)) { + newY = pt.y + idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newX -= idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newX -= idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newY -= idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newY -= idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newX += idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + newX += idx; + result = regionIndexOf(newX, newY); + + if ((result == 0) || contains(indexList, result)) { + continue; + } + } + } + } + } + } + } + } + + // Found an index + pt.x = newX; + pt.y = newY; + return result; + } + + return (result == 0) ? -1 : result; +} + +Common::Point *PlayerMover::findLinePoint(RouteEnds *routeEnds, Common::Point *objPos, int length, Common::Point *outPos) { + int xp = objPos->x + (((routeEnds->moveDest.y - routeEnds->moveSrc.y) * 9) / 8); + int yp = objPos->y - (((routeEnds->moveDest.x - routeEnds->moveSrc.x) * 8) / 9); + + int xDiff = xp - objPos->x; + int yDiff = yp - objPos->y; + int xDirection = (xDiff == 0) ? 0 : ((xDiff < 0) ? 1 : -1); + int yDirection = (yDiff == 0) ? 0 : ((yDiff < 0) ? 1 : -1); + xDiff = ABS(xDiff); + yDiff = ABS(yDiff); + int majorChange = MAX(xDiff, yDiff) / 2; + + int outX = objPos->x; + int outY = objPos->y; + + while (length-- > 0) { + if (xDiff < yDiff) { + outY += yDirection; + majorChange += xDiff; + if (majorChange > yDiff) { + majorChange -= yDiff; + outX += xDirection; + } + } else { + outX += xDirection; + majorChange += yDiff; + if (majorChange > xDiff) { + majorChange -= xDiff; + outY += yDirection; + } + } + } + + outPos->x = outX; + outPos->y = outY; + return outPos; +} + +int PlayerMover::checkMover(Common::Point &srcPos, const Common::Point &destPos) { + int regionIndex = 0; + Common::Point objPos = _sceneObject->_position; + uint32 regionBitList = _sceneObject->_regionBitList; + _sceneObject->_regionBitList = 0; + + _sceneObject->_position.x = srcPos.x; + _sceneObject->_position.y = srcPos.y; + _sceneObject->_mover = NULL; + + NpcMover *mover = new NpcMover(); + _sceneObject->addMover(mover, &destPos, NULL); + + // Handle automatic movement of the player until a walkable region is reached, + // or the end point of the movement is + do { + _sceneObject->_mover->dispatch(); + + // Scan walk regions for point + for (uint idx = 0; idx < _globals->_walkRegions._regionList.size(); ++idx) { + if (_globals->_walkRegions[idx].contains(_sceneObject->_position)) { + regionIndex = idx + 1; + srcPos = _sceneObject->_position; + break; + } + } + } while ((regionIndex == 0) && (_sceneObject->_mover) && !_vm->shouldQuit()); + + _sceneObject->_position = objPos; + _sceneObject->_regionBitList = regionBitList; + + if (_sceneObject->_mover) + _sceneObject->_mover->remove(); + + _sceneObject->_mover = this; + return regionIndex; +} + +void PlayerMover::checkMovement2(const Common::Point &srcPos, const Common::Point &destPos, int numSteps, Common::Point &ptOut) { + Common::Point objPos = _sceneObject->_position; + _sceneObject->_position = srcPos; + uint32 regionBitList = _sceneObject->_regionBitList; + _sceneObject->_position = srcPos; + _sceneObject->_mover = NULL; + + NpcMover *mover = new NpcMover(); + _sceneObject->addMover(mover, &destPos, NULL); + + while ((numSteps > 0) && ((_sceneObject->_position.x != destPos.x) || (_sceneObject->_position.y != destPos.y))) { + _sceneObject->_mover->dispatch(); + --numSteps; + } + + ptOut = _sceneObject->_position; + _sceneObject->_position = objPos; + _sceneObject->_regionBitList = regionBitList; + + if (_sceneObject->_mover) + _sceneObject->_mover->remove(); + + _sceneObject->_mover = this; +} + +int PlayerMover::proc1(int *routeList, int srcRegion, int destRegion, int &v) { + int tempList[REGION_LIST_SIZE + 1]; + v = 0; + for (int idx = 0; idx <= *routeList; ++idx) + tempList[idx] = routeList[idx]; + + if (*routeList == REGION_LIST_SIZE) + // Sequence too long + return 32000; + + int regionIndex; + for (regionIndex = 1; regionIndex <= *tempList; ++regionIndex) { + if (routeList[regionIndex] == srcRegion) + // Current path returns to original source region, so don't allow it + return 32000; + } + + WalkRegion &srcWalkRegion = _globals->_walkRegions[srcRegion]; + int distance; + if (!routeList[0]) { + // No route + distance = 0; + } else { + WalkRegion ®ion = _globals->_walkRegions[routeList[*routeList]]; + distance = findDistance(srcWalkRegion._pt, region._pt); + } + + tempList[++*tempList] = srcRegion; + int newIndex = *tempList; + + if (srcRegion == destRegion) { + v = 1; + for (int idx = newIndex; idx <= *tempList; ++idx) { + routeList[idx] = tempList[idx]; + ++*routeList; + } + return distance; + } else { + int foundIndex = 0; + int idx = 0; + int currDest; + while ((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + idx]) != 0) { + if (currDest == destRegion) { + foundIndex = idx; + break; + } + + ++idx; + } + + int resultOffset = 31990; + while (((currDest = _globals->_walkRegions._idxList[srcWalkRegion._idxListIndex + foundIndex]) != 0) && (v == 0)) { + int newDistance = proc1(tempList, currDest, destRegion, v); + + if ((newDistance <= resultOffset) || v) { + routeList[0] = newIndex - 1; + + for (int i = newIndex; i <= tempList[0]; ++i) { + routeList[i] = tempList[i]; + ++routeList[0]; + } + + resultOffset = newDistance; + } + + tempList[0] = newIndex; + ++foundIndex; + } + + v = 0; + return resultOffset + distance; + } +} + +int PlayerMover::findDistance(const Common::Point &pt1, const Common::Point &pt2) { + int diff = ABS(pt1.x - pt2.x); + double xx = diff * diff; + diff = ABS(pt1.y - pt2.y); + double yy = diff * 8.0 / 7.0; + yy *= yy; + + return (int)sqrt(xx + yy); +} + +bool PlayerMover::sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, + const Common::Point &pt4, Common::Point *ptOut) { + double diff1 = pt2.x - pt1.x; + double diff2 = pt2.y - pt1.y; + double diff3 = pt4.x - pt3.x; + double diff4 = pt4.y - pt3.y; + double var10 = 0.0, var8 = 0.0; + double var18 = 0.0, var20 = 0.0; + + if (diff1 != 0.0) { + var8 = diff2 / diff1; + var18 = pt1.y - (pt1.x * var8); + } + if (diff3 != 0.0) { + var10 = diff4 / diff3; + var20 = pt3.y - (pt3.x * var10); + } + + if (var8 == var10) + return false; + + double var48, var50; + if (diff1 == 0) { + if (diff3 == 0) + return false; + + var48 = pt1.x; + var50 = var10 * var48 + var20; + } else { + var48 = (diff3 == 0) ? pt3.x : (var20 - var18) / (var8 - var10); + var50 = var8 * var48 + var18; + } + + bool var52 = false, var56 = false, var54 = false, var58 = false; + Common::Point tempPt((int)(var48 + 0.5), (int)(var50 + 0.5)); + + if ((tempPt.x >= pt3.x) && (tempPt.x <= pt4.x)) + var56 = true; + else if ((tempPt.x >= pt4.x) && (tempPt.x <= pt3.x)) + var56 = true; + if (var56) { + if ((tempPt.y >= pt3.y) && (tempPt.y <= pt4.y)) + var58 = true; + else if ((tempPt.y >= pt4.y) && (tempPt.y <= pt3.y)) + var58 = true; + } + + if ((tempPt.x >= pt1.x) && (tempPt.x <= pt2.x)) + var52 = true; + else if ((tempPt.x >= pt2.x) && (tempPt.x <= pt1.x)) + var52 = true; + if (var52) { + if ((tempPt.y >= pt1.y) && (tempPt.y <= pt2.y)) + var54 = true; + else if ((tempPt.y >= pt2.y) && (tempPt.y <= pt1.y)) + var54 = true; + } + + if (var52 && var54 && var56 && var58) { + if (ptOut) + *ptOut = tempPt; + return true; + } + + return false; +} + +/*--------------------------------------------------------------------------*/ + +void PlayerMover2::synchronise(Serialiser &s) { + SYNC_POINTER(_destObject); + s.syncAsSint16LE(_field7E); + s.syncAsSint16LE(_minArea); +} + +void PlayerMover2::dispatch() { + int total = _sceneObject->getSpliceArea(_destObject); + + if (total <= _minArea) + endMove(); + else { + setDest(_destObject->_position); + ObjectMover::dispatch(); + } +} + +void PlayerMover2::startMove(SceneObject *sceneObj, va_list va) { + _sceneObject = sceneObj; + _field7E = va_arg(va, int); + _minArea = va_arg(va, int); + _destObject = va_arg(va, SceneObject *); + + PlayerMover::setDest(_destObject->_position); +} + +void PlayerMover2::endMove() { + _sceneObject->_regionIndex = 0x40; +} + +/*--------------------------------------------------------------------------*/ + +PaletteModifier::PaletteModifier() { + _scenePalette = NULL; + _action = NULL; +} + +/*--------------------------------------------------------------------------*/ + +PaletteRotation::PaletteRotation() : PaletteModifier() { + _disabled = false; + _delayFrames = 0; + _delayCtr = 0; + _frameNumber = _globals->_events.getFrameNumber(); +} + +void PaletteRotation::synchronise(Serialiser &s) { + PaletteModifier::synchronise(s); + + s.syncAsByte(_disabled); + s.syncAsSint32LE(_delayFrames); + s.syncAsSint32LE(_delayCtr); + s.syncAsUint32LE(_frameNumber); + s.syncAsSint32LE(_currIndex); + s.syncAsSint32LE(_start); + s.syncAsSint32LE(_end); + s.syncAsSint32LE(_rotationMode); + s.syncAsSint32LE(_duration); + for (int i = 0; i < 256; ++i) { + s.syncAsByte(_palette[i].r); + s.syncAsByte(_palette[i].g); + s.syncAsByte(_palette[i].b); + } +} + +void PaletteRotation::signal() { + if (_delayCtr) { + uint32 frameNumber = _globals->_events.getFrameNumber(); + + if (frameNumber >= _frameNumber) { + _delayCtr = frameNumber - _frameNumber; + _frameNumber = frameNumber; + + if (_delayCtr < 0) + _delayCtr = 0; + } + } + + if (_delayCtr) + return; + _delayCtr = _delayFrames; + if (_disabled) + return; + + bool flag = true; + switch (_rotationMode) { + case -1: + if (--_currIndex < _start) { + flag = decDuration(); + if (flag) + _currIndex = _end - 1; + } + break; + case 1: + if (++_currIndex >= _end) { + flag = decDuration(); + if (flag) + _currIndex = _start; + } + break; + case 2: + if (++_currIndex >= _end) { + flag = decDuration(); + if (flag) { + _currIndex = _end - 2; + _rotationMode = 3; + } + } + break; + case 3: + if (--_currIndex < _start) { + flag = decDuration(); + if (flag) { + _currIndex = _start + 1; + _rotationMode = 2; + } + } + break; + } + + if (flag) { + int count2 = _currIndex - _start; + int count = _end - _currIndex; + g_system->getPaletteManager()->setPalette((const byte *)&_palette[_currIndex], _start, count); + + if (count2) { + g_system->getPaletteManager()->setPalette((const byte *)&_palette[_start], _start + count, count2); + } + } +} + +void PaletteRotation::remove() { + Action *action = _action; + g_system->getPaletteManager()->setPalette((const byte *)&_palette[_start], _start, _end - _start); + + _scenePalette->_listeners.remove(this); + + delete this; + if (action) + action->signal(); +} + +void PaletteRotation::set(ScenePalette *palette, int start, int end, int rotationMode, int duration, Action *action) { + _duration = duration; + _disabled = false; + _action = action; + _scenePalette = palette; + + Common::copy(&palette->_palette[0], &palette->_palette[256], &_palette[0]); + + _start = start; + _end = end + 1; + _rotationMode = rotationMode; + + switch (_rotationMode) { + case -1: + case 3: + _currIndex = _end; + break; + default: + _currIndex = _start; + break; + } +} + +void PaletteRotation::setPalette(ScenePalette *palette, bool disabled) { + _scenePalette = palette; + _disabled = disabled; + _delayFrames = 100; +} + +bool PaletteRotation::decDuration() { + if (_duration) { + if (--_duration == 0) { + remove(); + return false; + } + } + return true; +} + +void PaletteRotation::setDelay(int amount) { + _delayFrames = _delayCtr = amount; +} + +/*--------------------------------------------------------------------------*/ + +void PaletteUnknown::synchronise(Serialiser &s) { + PaletteModifier::synchronise(s); + + s.syncAsSint16LE(_step); + s.syncAsSint16LE(_percent); + s.syncAsSint16LE(_field12); + s.syncAsSint16LE(_field14); + for (int i = 0; i < 256; ++i) { + s.syncAsByte(_palette[i].r); + s.syncAsByte(_palette[i].g); + s.syncAsByte(_palette[i].b); + } +} + +void PaletteUnknown::signal() { + _percent -= _step; + if (_percent > 0) { + _scenePalette->fade((byte *)_palette, true /* 256 */, _percent); + } else { + remove(); + } +} + +void PaletteUnknown::remove() { + if (_scenePalette) { + for (int i = 0; i < 256; i++) + _scenePalette->_palette[i] = _palette[i]; + _scenePalette->refresh(); + _scenePalette->_listeners.remove(this); + delete this; + } + + if (_action) + _action->signal(); +} + +/*--------------------------------------------------------------------------*/ + +ScenePalette::ScenePalette() { + // Set a default gradiant range + for (int idx = 0; idx < 256; ++idx) + _palette[idx].r = _palette[idx].g = _palette[idx].b = idx; + + _field412 = 0; +} + +ScenePalette::ScenePalette(int paletteNum) { + loadPalette(paletteNum); +} + +bool ScenePalette::loadPalette(int paletteNum) { + byte *palData = _vm->_dataManager->getResource(RES_PALETTE, paletteNum, 0, true); + if (!palData) + return false; + + int palStart = READ_LE_UINT16(palData); + int palSize = READ_LE_UINT16(palData + 2); + assert(palSize <= 256); + + RGB8 *destP = &_palette[palStart]; + RGB8 *srcP = (RGB8 *)(palData + 6); + + Common::copy(&srcP[0], &srcP[palSize], destP); + + DEALLOCATE(palData); + return true; +} + +void ScenePalette::refresh() { + // Set indexes for standard colours to closest colour in the palette + _colours.background = indexOf(255, 255, 255); // White background + _colours.foreground = indexOf(0, 0, 0); // Black foreground + _redColour = indexOf(180, 0, 0); // Red-ish + _greenColour = indexOf(0, 180, 0); // Green-ish + _blueColour = indexOf(0, 0, 180); // Blue-ish + _aquaColour = indexOf(0, 180, 180); // Aqua + _purpleColour = indexOf(180, 0, 180); // Purple + _limeColour = indexOf(180, 180, 0); // Lime + + // Refresh the palette + g_system->getPaletteManager()->setPalette((const byte *)&_palette[0], 0, 256); +} + +/** + * Loads a section of the palette into the game palette + */ +void ScenePalette::setPalette(int index, int count) { + g_system->getPaletteManager()->setPalette((const byte *)&_palette[index], index, count); +} + +/** + * Returns the palette index with the closest matching colour to that specified + * @param r R component + * @param g G component + * @param b B component + * @param threshold Closeness threshold. + * @remarks A threshold may be provided to specify how close the matching colour must be + */ +uint8 ScenePalette::indexOf(uint r, uint g, uint b, int threshold) { + int palIndex = -1; + + for (int i = 0; i < 256; ++i) { + int rDiff = abs(_palette[i].r - (int)r); + int gDiff = abs(_palette[i].g - (int)g); + int bDiff = abs(_palette[i].b - (int)b); + + int idxThreshold = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff; + if (idxThreshold <= threshold) { + threshold = idxThreshold; + palIndex = i; + } + } + + return palIndex; +} + +/** + * Loads the specified range of the palette with the current system palette + * @param start Start index + * @param count Number of palette entries + */ +void ScenePalette::getPalette(int start, int count) { + g_system->getPaletteManager()->grabPalette((byte *)&_palette[start], start, count); +} + +void ScenePalette::signalListeners() { + for (SynchronisedList<PaletteModifier *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { + (*i)->signal(); + } +} + +void ScenePalette::clearListeners() { + SynchronisedList<PaletteModifier *>::iterator i = _listeners.begin(); + while (i != _listeners.end()) { + PaletteModifier *obj = *i; + ++i; + obj->remove(); + } +} + +void ScenePalette::fade(const byte *adjustData, bool fullAdjust, int percent) { + RGB8 tempPalette[256]; + + // Ensure the percent adjustment is within 0 - 100% + percent = CLIP(percent, 0, 100); + + for (int palIndex = 0; palIndex < 256; ++palIndex) { + const byte *srcP = (const byte *)&_palette[palIndex]; + byte *destP = (byte *)&tempPalette[palIndex].r; + + for (int rgbIndex = 0; rgbIndex < 3; ++rgbIndex, ++srcP, ++destP) { + *destP = *srcP - ((*srcP - adjustData[rgbIndex]) * (100 - percent)) / 100; + } + + if (fullAdjust) + adjustData += 3; + } + + // Set the altered pale4tte + g_system->getPaletteManager()->setPalette((const byte *)&tempPalette[0], 0, 256); + g_system->updateScreen(); +} + +PaletteRotation *ScenePalette::addRotation(int start, int end, int rotationMode, int duration, Action *action) { + PaletteRotation *obj = new PaletteRotation(); + + if ((rotationMode == 2) || (rotationMode == 3)) + duration <<= 1; + + obj->set(this, start, end, rotationMode, duration, action); + _listeners.push_back(obj); + return obj; +} + +PaletteUnknown *ScenePalette::addUnkPal(RGB8 *arrBufferRGB, int unkNumb, bool disabled, Action *action) { + PaletteUnknown *paletteUnk = new PaletteUnknown(); + paletteUnk->_action = action; + for (int i = 0; i < 256; i++) { + if (unkNumb <= 1) + paletteUnk->_palette[i] = arrBufferRGB[i]; + else + paletteUnk->_palette[i] = arrBufferRGB[0]; + } +// PaletteRotation::setPalette(this, disabled); + _globals->_scenePalette._listeners.push_back(paletteUnk); + return paletteUnk; +} + + +void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) { + ScenePalette tempPalette; + + if (_globals->_sceneManager._hasPalette) { + if ((fadeMode == FADEMODE_GRADUAL) || (fadeMode == FADEMODE_IMMEDIATE)) { + // Fade out any active palette + tempPalette.getPalette(); + uint32 adjustData = 0; + + for (int percent = 100; percent >= 0; percent -= 5) { + if (fadeMode == FADEMODE_IMMEDIATE) + percent = 0; + tempPalette.fade((byte *)&adjustData, false, percent); + g_system->delayMillis(10); + } + } else { + _globals->_scenePalette.refresh(); + _globals->_sceneManager._hasPalette = false; + } + } + + _globals->_screenSurface.copyFrom(_globals->_sceneManager._scene->_backSurface, + bounds, Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), NULL); + + for (SynchronisedList<PaletteModifier *>::iterator i = tempPalette._listeners.begin(); i != tempPalette._listeners.end(); ++i) + delete *i; + tempPalette._listeners.clear(); +} + +void ScenePalette::synchronise(Serialiser &s) { + for (int i = 0; i < 256; ++i) { + s.syncAsByte(_palette[i].r); + s.syncAsByte(_palette[i].g); + s.syncAsByte(_palette[i].b); + } + s.syncAsSint32LE(_colours.foreground); + s.syncAsSint32LE(_colours.background); + + s.syncAsSint32LE(_field412); + s.syncAsByte(_redColour); + s.syncAsByte(_greenColour); + s.syncAsByte(_blueColour); + s.syncAsByte(_aquaColour); + s.syncAsByte(_purpleColour); + s.syncAsByte(_limeColour); +} + +/*--------------------------------------------------------------------------*/ + +void SceneItem::synchronise(Serialiser &s) { + EventHandler::synchronise(s); + + _bounds.synchronise(s); + s.syncString(_msg); + s.syncAsSint32LE(_fieldE); + s.syncAsSint32LE(_field10); + s.syncAsSint16LE(_position.x); s.syncAsSint32LE(_position.y); + s.syncAsSint16LE(_yDiff); + s.syncAsSint32LE(_sceneRegionId); +} + +void SceneItem::remove() { + _globals->_sceneItems.remove(this); +} + +void SceneItem::doAction(int action) { + const char *msg = NULL; + + switch ((int)action) { + case CURSOR_LOOK: + msg = LOOK_SCENE_HOTSPOT; + break; + case CURSOR_USE: + msg = USE_SCENE_HOTSPOT; + break; + case CURSOR_TALK: + msg = TALK_SCENE_HOTSPOT; + break; + case 0x1000: + msg = SPECIAL_SCENE_HOTSPOT; + break; + default: + msg = DEFAULT_SCENE_HOTSPOT; + break; + } + + GUIErrorMessage(msg); +} + +bool SceneItem::contains(const Common::Point &pt) { + const Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + + if (_sceneRegionId == 0) + return _bounds.contains(pt.x + sceneBounds.left, pt.y + sceneBounds.top); + else + return _globals->_sceneRegions.indexOf(Common::Point(pt.x + sceneBounds.left, + pt.y + sceneBounds.top)) == _sceneRegionId; +} + +void SceneItem::display(int resNum, int lineNum, ...) { + Common::String msg = !resNum ? Common::String() : _vm->_dataManager->getMessage(resNum, lineNum); + + if (_globals->_sceneObjects->contains(&_globals->_sceneText)) { + _globals->_sceneText.remove(); + _globals->_sceneObjects->draw(); + } + + GfxFontBackup font; + Common::Point pos(160, 100); + Rect textRect; + int maxWidth = 120; + bool keepOnscreen = false; + bool centreText = true; + + if (resNum) { + va_list va; + va_start(va, lineNum); + + int mode; + do { + // Get next instruction + mode = va_arg(va, int); + + switch (mode) { + case SET_WIDTH: + // Set width + maxWidth = va_arg(va, int); + _globals->_sceneText._width = maxWidth; + break; + case SET_X: + // Set the X Position + pos.x = va_arg(va, int); + break; + case SET_Y: + // Set the Y Position + pos.y = va_arg(va, int); + break; + case SET_FONT: + // Set the font number + _globals->_sceneText._fontNumber = va_arg(va, int); + _globals->gfxManager()._font.setFontNumber(_globals->_sceneText._fontNumber); + break; + case SET_BG_COLOUR: { + // Set the background colour + int bgColour = va_arg(va, int); + _globals->gfxManager()._font._colours.background = bgColour; + if (!bgColour) + _globals->gfxManager().setFillFlag(false); + break; + } + case SET_FG_COLOUR: + // Set the foreground colour + _globals->_sceneText._colour1 = va_arg(va, int); + _globals->gfxManager()._font._colours.foreground = _globals->_sceneText._colour1; + break; + case SET_KEEP_ONSCREEN: + // Suppresses immediate display + keepOnscreen = va_arg(va, int) != 0; + break; + case SET_EXT_BGCOLOUR: { + // Set secondary bg colour + int v = va_arg(va, int); + _globals->_sceneText._colour2 = v; + _globals->gfxManager()._font._colours2.background = v; + break; + } + case SET_EXT_FGCOLOUR: { + // Set secondary fg colour + int v = va_arg(va, int); + _globals->_sceneText._colour3 = v; + _globals->gfxManager()._font._colours.foreground = v; + break; + } + case SET_POS_MODE: + // Set whether a custom x/y is used + centreText = va_arg(va, int) != 0; + break; + case SET_TEXT_MODE: + // Set the text mode + _globals->_sceneText._textMode = (TextAlign)va_arg(va, int); + break; + default: + break; + } + } while (mode != LIST_END); + + va_end(va); + } + + if (resNum) { + // Get required bounding size + _globals->gfxManager().getStringBounds(msg.c_str(), textRect, maxWidth); + textRect.centre(pos.x, pos.y); + + textRect.contain(_globals->gfxManager()._bounds); + if (centreText) { + _globals->_sceneText._colour1 = _globals->_sceneText._colour2; + _globals->_sceneText._colour2 = 0; + _globals->_sceneText._colour3 = 0; + } + + _globals->_sceneText.setup(msg); + if (centreText) { + _globals->_sceneText.setPosition(Common::Point( + _globals->_sceneManager._scene->_sceneBounds.left + textRect.left, + _globals->_sceneManager._scene->_sceneBounds.top + textRect.top), 0); + } else { + _globals->_sceneText.setPosition(pos, 0); + } + + _globals->_sceneText.setPriority2(255); + _globals->_sceneObjects->draw(); + } + + // Unless the flag is set to keep the message on-screen, show it until a mouse or keypress, then remove it + if (!keepOnscreen && !msg.empty()) { + Event event; + + // Keep event on-screen until a mouse or keypress + while (!_vm->getEventManager()->shouldQuit() && !_globals->_events.getEvent(event, + EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) { + g_system->updateScreen(); + g_system->delayMillis(10); + } + + _globals->_sceneText.remove(); + } +} + +/*--------------------------------------------------------------------------*/ + +void SceneHotspot::doAction(int action) { + switch ((int)action) { + case CURSOR_LOOK: + display(1, 0, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + display(1, 5, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_TALK: + display(1, 15, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_WALK: + break; + default: + display(2, action, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void NamedHotspot::doAction(int action) { + switch (action) { + case CURSOR_WALK: + // Nothing + break; + case CURSOR_LOOK: + if (_lookLineNum == -1) + SceneHotspot::doAction(action); + else + SceneItem::display(_resnum, _lookLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (_useLineNum == -1) + SceneHotspot::doAction(action); + else + SceneItem::display(_resnum, _useLineNum, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void NamedHotspot::setup(const int ys, const int xe, const int ye, const int xs, const int resnum, const int lookLineNum, const int useLineNum) { + setBounds(ys, xe, ye, xs); + _resnum = resnum; + _lookLineNum = lookLineNum; + _useLineNum = useLineNum; + _globals->_sceneItems.addItems(this, NULL); +} + +/*--------------------------------------------------------------------------*/ + +void SceneObjectWrapper::setSceneObject(SceneObject *so) { + _sceneObject = so; + so->_strip = 1; + so->_flags |= OBJFLAG_PANES; +} + +void SceneObjectWrapper::synchronise(Serialiser &s) { + EventHandler::synchronise(s); + SYNC_POINTER(_sceneObject); +} + +void SceneObjectWrapper::remove() { + delete this; +} + +void SceneObjectWrapper::dispatch() { + _visageImages.setVisage(_sceneObject->_visage); + int frameCount = _visageImages.getFrameCount(); + int angle = _sceneObject->_angle; + int strip = _sceneObject->_strip; + + if (frameCount == 4) { + if ((angle > 314) || (angle < 45)) + strip = 4; + if ((angle > 44) && (angle < 135)) + strip = 1; + if ((angle >= 135) && (angle < 225)) + strip = 3; + if ((angle >= 225) && (angle < 315)) + strip = 2; + } else if (frameCount == 8) { + if ((angle > 330) || (angle < 30)) + strip = 4; + if ((angle >= 30) && (angle < 70)) + strip = 7; + if ((angle >= 70) && (angle < 110)) + strip = 1; + if ((angle >= 110) && (angle < 150)) + strip = 5; + if ((angle >= 150) && (angle < 210)) + strip = 3; + if ((angle >= 210) && (angle < 250)) + strip = 6; + if ((angle >= 250) && (angle < 290)) + strip = 2; + if ((angle >= 290) && (angle < 331)) + strip = 8; + } + + if (strip > frameCount) + strip = frameCount; + + _sceneObject->setStrip(strip); +} + +/*--------------------------------------------------------------------------*/ + +SceneObject::SceneObject() : SceneHotspot() { + _endAction = NULL; + _mover = NULL; + _objectWrapper = NULL; + _flags = 0; + _walkStartFrame = 0; + _animateMode = ANIM_MODE_NONE; + _updateStartFrame = 0; + _moveDiff.x = 5; + _moveDiff.y = 3; + _numFrames = 10; + _numFrames = 10; + _field7A = 10; + _regionBitList = 0; + _sceneRegionId = 0; + _percent = 100; + _flags |= OBJFLAG_PANES; + + _frameChange = 0; +} + +SceneObject::SceneObject(const SceneObject &so) : SceneHotspot() { + *this = so; + if (_objectWrapper) + // Create a fresh object wrapper for this object + _objectWrapper = new SceneObjectWrapper(); +} + +SceneObject::~SceneObject() { + delete _mover; + delete _objectWrapper; +} + +int SceneObject::getNewFrame() { + int frameNum = _frame + _frameChange; + + if (_frameChange > 0) { + if (frameNum > getFrameCount()) { + frameNum = 1; + if (_animateMode == ANIM_MODE_1) + ++frameNum; + } + } else if (frameNum < 1) { + frameNum = getFrameCount(); + } + + return frameNum; +} + +int SceneObject::getFrameCount() { + _visageImages.setVisage(_visage, _strip); + return _visageImages.getFrameCount(); +} + +void SceneObject::animEnded() { + _animateMode = ANIM_MODE_NONE; + if (_endAction) + _endAction->signal(); +} + +int SceneObject::changeFrame() { + int frameNum = _frame; + uint32 mouseCtr = _globals->_events.getFrameNumber(); + + if ((_updateStartFrame <= mouseCtr) || (_animateMode == ANIM_MODE_1)) { + if (_numFrames > 0) { + int v = 60 / _numFrames; + _updateStartFrame = mouseCtr + v; + + frameNum = getNewFrame(); + } + } + + return frameNum; +} + +void SceneObject::setPosition(const Common::Point &p, int yDiff) { + _position = p; + _yDiff = yDiff; + _flags |= OBJFLAG_PANES; +} + +void SceneObject::setZoom(int percent) { + assert((percent >= -1) && (percent < 999)); + if (percent != _percent) { + _percent = percent; + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::updateZoom() { + changeZoom(_percent); +} + +void SceneObject::changeZoom(int percent) { + if (percent == -1) + _flags &= ~OBJFLAG_ZOOMED; + else { + _flags |= OBJFLAG_ZOOMED; + setZoom(percent); + } +} + +void SceneObject::setStrip(int stripNum) { + if (stripNum != _strip) { + _strip = stripNum; + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::setStrip2(int stripNum) { + if (stripNum == -1) + _flags &= ~OBJFLAG_SUPPRESS_DISPATCH; + else { + _flags |= OBJFLAG_SUPPRESS_DISPATCH; + setStrip(stripNum); + } +} + +void SceneObject::setFrame(int frameNum) { + if (frameNum != _frame) { + _frame = frameNum; + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::setFrame2(int frameNum) { + if (frameNum != -1) { + _flags |= OBJFLAG_NO_UPDATES; + setFrame(frameNum); + } else { + _flags &= ~OBJFLAG_NO_UPDATES; + } +} + +void SceneObject::setPriority(int priority) { + if (priority != _priority) { + _priority = priority; + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::setPriority2(int priority) { + if (priority == -1) { + _flags &= ~OBJFLAG_FIXED_PRIORITY; + } else { + _flags |= OBJFLAG_FIXED_PRIORITY; + setPriority(priority); + } +} + +void SceneObject::setVisage(int visage) { + if (visage != _visage) { + _visage = visage; + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::setObjectWrapper(SceneObjectWrapper *objWrapper) { + if (_objectWrapper) + _objectWrapper->remove(); + _objectWrapper = objWrapper; + if (objWrapper) + objWrapper->setSceneObject(this); +} + +void SceneObject::addMover(ObjectMover *mover, ...) { + if (_mover) + _mover->remove(); + _mover = mover; + + if (mover) { + // Set up the assigned mover + _walkStartFrame = _globals->_events.getFrameNumber(); + if (_field7A != 0) + _walkStartFrame = 60 / _field7A; + + // Signal the mover that movement is beginning + va_list va; + va_start(va, mover); + mover->startMove(this, va); + va_end(va); + } +} + +void SceneObject::getHorizBounds() { + Rect tempRect; + + GfxSurface frame = getFrame(); + tempRect.resize(frame, _position.x, _position.y - _yDiff, _percent); + + _xs = tempRect.left; + _xe = tempRect.right; +} + +int SceneObject::getRegionIndex() { + return _globals->_sceneRegions.indexOf(_position); +} + +int SceneObject::checkRegion(const Common::Point &pt) { + Rect tempRect; + int regionIndex = 0; + + // Temporarily change the position + Common::Point savedPos = _position; + _position = pt; + + int regIndex = _globals->_sceneRegions.indexOf(pt); + if (_regionBitList & (1 << regIndex)) + regionIndex = regIndex; + + // Restore position + _position = savedPos; + + // Get the object's frame bounds + GfxSurface frame = getFrame(); + tempRect.resize(frame, _position.x, _position.y - _yDiff, _percent); + + int yPos, newY; + if ((_position.y - _yDiff) <= (pt.y - _yDiff)) { + yPos = _position.y - _yDiff; + newY = pt.y; + } else { + yPos = pt.y - _yDiff; + newY = _position.y; + } + newY -= _yDiff; + + SynchronisedList<SceneObject *>::iterator i; + for (i = _globals->_sceneObjects->begin(); (regionIndex == 0) && (i != _globals->_sceneObjects->end()); ++i) { + if ((*i) && ((*i)->_flags & OBJFLAG_CHECK_REGION)) { + int objYDiff = (*i)->_position.y - _yDiff; + if ((objYDiff >= yPos) && (objYDiff <= newY) && + ((*i)->_xs < tempRect.right) && ((*i)->_xe > tempRect.left)) { + // Found index + regionIndex = -1; //****DEBUG*** = *i; + break; + } + } + } + + return regionIndex; +} + +void SceneObject::animate(AnimateMode animMode, ...) { + _animateMode = animMode; + _updateStartFrame = _globals->_events.getFrameNumber(); + if (_numFrames) + _updateStartFrame += 60 / _numFrames; + + va_list va; + va_start(va, animMode); + + switch (_animateMode) { + case ANIM_MODE_NONE: + _endAction = NULL; + break; + + case ANIM_MODE_1: + _frameChange = 1; + _field2E = _position; + _endAction = 0; + break; + + case ANIM_MODE_2: + _frameChange = 1; + _endAction = NULL; + break; + + case ANIM_MODE_3: + _frameChange = -1; + _endAction = NULL; + break; + + case ANIM_MODE_4: + _endFrame = va_arg(va, int); + _frameChange = va_arg(va, int); + _endAction = va_arg(va, Action *); + if (_endFrame == _frame) + setFrame(getNewFrame()); + break; + + case ANIM_MODE_5: + _frameChange = 1; + _endFrame = getFrameCount(); + _endAction = va_arg(va, Action *); + if (_endFrame == _frame) + setFrame(getNewFrame()); + break; + + case ANIM_MODE_6: + _frameChange = -1; + _endAction = va_arg(va, Action *); + _endFrame = 1; + if (_frame == _endFrame) + setFrame(getNewFrame()); + break; + + case ANIM_MODE_7: + _endFrame = va_arg(va, int); + _endAction = va_arg(va, Action *); + _frameChange = 1; + break; + + case ANIM_MODE_8: + _field68 = va_arg(va, int); + _endAction = va_arg(va, Action *); + _frameChange = 1; + _endFrame = getFrameCount(); + if (_frame == _endFrame) + setFrame(getNewFrame()); + break; + } +} + +SceneObject *SceneObject::clone() const { + SceneObject *obj = new SceneObject(*this); + return obj; +} + +void SceneObject::checkAngle(const SceneObject *obj) { + _angle = GfxManager::getAngle(_position, obj->_position); + + if (_objectWrapper) + _objectWrapper->dispatch(); +} + +void SceneObject::hide() { + _flags |= OBJFLAG_HIDE; + if (_flags & OBJFLAG_HIDING) + _flags |= OBJFLAG_PANES; +} + +void SceneObject::show() { + if (_flags & OBJFLAG_HIDE) { + _flags &= ~OBJFLAG_HIDE; + _flags |= OBJFLAG_PANES; + } +} + +int SceneObject::getSpliceArea(const SceneObject *obj) { + int xd = ABS(_position.x - obj->_position.x); + int yd = ABS(_position.y - obj->_position.y); + + return (xd * xd + yd) / 2; +} + +void SceneObject::synchronise(Serialiser &s) { + SceneHotspot::synchronise(s); + + s.syncAsUint32LE(_updateStartFrame); + s.syncAsUint32LE(_walkStartFrame); + s.syncAsSint16LE(_field2E.x); s.syncAsSint16LE(_field2E.y); + s.syncAsSint16LE(_percent); + s.syncAsSint16LE(_priority); + s.syncAsSint16LE(_angle); + s.syncAsUint32LE(_flags); + s.syncAsSint16LE(_xs); + s.syncAsSint16LE(_xe); + _paneRects[0].synchronise(s); + _paneRects[1].synchronise(s); + s.syncAsSint32LE(_visage); + SYNC_POINTER(_objectWrapper); + s.syncAsSint32LE(_strip); + SYNC_ENUM(_animateMode, AnimateMode); + s.syncAsSint32LE(_frame); + s.syncAsSint32LE(_endFrame); + s.syncAsSint32LE(_field68); + s.syncAsSint32LE(_frameChange); + s.syncAsSint32LE(_numFrames); + s.syncAsSint32LE(_regionIndex); + SYNC_POINTER(_mover); + s.syncAsSint16LE(_moveDiff.x); s.syncAsSint16LE(_moveDiff.y); + s.syncAsSint32LE(_field7A); + SYNC_POINTER(_endAction); + s.syncAsUint32LE(_regionBitList); +} + +void SceneObject::postInit(SceneObjectList *OwnerList) { + if (!OwnerList) + OwnerList = _globals->_sceneObjects; + + if (!OwnerList->contains(this)) { + _percent = 100; + _priority = 255; + _flags = 4; + _visage = 0; + _strip = 1; + _frame = 1; + _objectWrapper = NULL; + _animateMode = ANIM_MODE_NONE; + _endAction = 0; + _mover = NULL; + _yDiff = 0; + _moveDiff.x = 5; + _moveDiff.y = 3; + _field7A = 10; + _regionIndex = 0x40; + _numFrames = 10; + _regionBitList = 0; + + OwnerList->push_back(this); + _flags |= OBJFLAG_PANES; + } +} + +void SceneObject::remove() { + SceneItem::remove(); + if (_globals->_sceneObjects->contains(this)) + // For objects in the object list, flag the object for removal in the next drawing, so that + // the drawing code has a chance to restore the area previously covered by the object + _flags |= OBJFLAG_PANES | OBJFLAG_REMOVE | OBJFLAG_HIDE; + else + // Not in the list, so immediately remove the object + removeObject(); +} + +void SceneObject::dispatch() { + uint32 currTime = _globals->_events.getFrameNumber(); + if (_action) + _action->dispatch(); + + if (_mover && (_walkStartFrame <= currTime)) { + if (_field7A) { + int frameInc = 60 / _field7A; + _walkStartFrame = currTime + frameInc; + } + _mover->dispatch(); + } + + if (!(_flags & OBJFLAG_NO_UPDATES)) { + switch (_animateMode) { + case ANIM_MODE_1: + if (isNoMover()) + setFrame(1); + else if ((_field2E.x != _position.x) || (_field2E.y != _position.y)) { + setFrame(changeFrame()); + _field2E = _position; + + } + break; + + case ANIM_MODE_2: + case ANIM_MODE_3: + setFrame(changeFrame()); + + break; + case ANIM_MODE_4: + case ANIM_MODE_5: + case ANIM_MODE_6: + if (_frame == _endFrame) + animEnded(); + else + setFrame(changeFrame()); + break; + + case ANIM_MODE_7: + if (changeFrame() != _frame) { + // Pick a new random frame + int frameNum = 0; + do { + int count = getFrameCount(); + frameNum = _globals->_randomSource.getRandomNumber(count - 1); + } while (frameNum == _frame); + + setFrame(frameNum); + if (_endFrame) { + if (--_endFrame == 0) + animEnded(); + } + } + break; + + case ANIM_MODE_8: + if (_frame == _endFrame) { + if (_frameChange != -1) { + _frameChange = -1; + _endFrame = 1; + + setFrame(changeFrame()); + } else if (!_field68 || (--_field68 > 0)) { + _frameChange = 1; + _endFrame = getFrameCount(); + + setFrame(changeFrame()); + } else { + animEnded(); + } + } else { + setFrame(changeFrame()); + } + + break; + + default: + break; + } + } + + // Handle updating the zoom and/or priority + if (!(_flags & OBJFLAG_ZOOMED)) { + int yp = CLIP((int)_position.y, 0, 255); + setZoom(_globals->_sceneManager._scene->_zoomPercents[yp]); + } + if (!(_flags & OBJFLAG_FIXED_PRIORITY)) { + setPriority(_position.y); + } +} + +void SceneObject::calcAngle(const Common::Point &pt) { + int newAngle = GfxManager::getAngle(_position, pt); + if (newAngle != -1) + _angle = newAngle; +} + +void SceneObject::removeObject() { + _globals->_sceneItems.remove(this); + _globals->_sceneObjects->remove(this); + + if (_visage) { + _vm->_memoryManager.deallocate(_visage); + _visage = 0; + } + + if (_objectWrapper) { + _objectWrapper->remove(); + _objectWrapper = NULL; + } + if (_mover) { + _mover->remove(); + _mover = NULL; + } + if (_flags & 0x800) + destroy(); +} + +GfxSurface SceneObject::getFrame() { + _visageImages.setVisage(_visage, _strip); + return _visageImages.getFrame(_frame); +} + +void SceneObject::reposition() { + GfxSurface frame = getFrame(); + _bounds.resize(frame, _position.x, _position.y - _yDiff, _percent); + _xs = _bounds.left; + _xe = _bounds.right; +} + +/** + * Draws an object into the scene + */ +void SceneObject::draw() { + Rect destRect = _bounds; + destRect.translate(-_globals->_sceneManager._scene->_sceneBounds.left, + -_globals->_sceneManager._scene->_sceneBounds.top); + Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(_priority); + GfxSurface frame = getFrame(); + _globals->gfxManager().copyFrom(frame, destRect, priorityRegion); +} + +/** + * Refreshes the background around the area of a scene object prior to it's being redrawn, + * in case it is moving + */ +void SceneObject::updateScreen() { + Rect srcRect = _paneRects[CURRENT_PANENUM]; + const Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + srcRect.left = (srcRect.left / 4) * 4; + srcRect.right = ((srcRect.right + 3) / 4) * 4; + srcRect.clip(_globals->_sceneManager._scene->_sceneBounds); + + if (srcRect.isValidRect()) { + Rect destRect = srcRect; + destRect.translate(-sceneBounds.left, -sceneBounds.top); + srcRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y); + + _globals->_screenSurface.copyFrom(_globals->_sceneManager._scene->_backSurface, srcRect, destRect); + } +} + +void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority) { + postInit(); + setVisage(visage); + setStrip(stripFrameNum); + setFrame(frameNum); + setPosition(Common::Point(posX, posY), 0); + setPriority2(priority); +} + +/*--------------------------------------------------------------------------*/ + +void SceneObjectList::draw() { + Common::Array<SceneObject *> objList; + int paneNum = 0; + int xAmount = 0, yAmount = 0; + + if (_objList.size() == 0) { + // Alternate draw mode + + if (_globals->_paneRefreshFlag[paneNum] == 1) { + // Load the background + _globals->_sceneManager._scene->refreshBackground(0, 0); + + Rect tempRect = _globals->_sceneManager._scene->_sceneBounds; + tempRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y); + ScenePalette::changeBackground(tempRect, _globals->_sceneManager._fadeMode); + } else { + _globals->_paneRegions[CURRENT_PANENUM].draw(); + } + + _globals->_paneRegions[CURRENT_PANENUM].setRect(0, 0, 0, 0); + _globals->_sceneManager.fadeInIfNecessary(); + + } else { + // If there is a scroll follower, check whether it has moved off-screen + if (_globals->_scrollFollower) { + const Rect &scrollerRect = _globals->_sceneManager._scrollerRect; + Common::Point objPos( + _globals->_scrollFollower->_position.x - _globals->_sceneManager._scene->_sceneBounds.left, + _globals->_scrollFollower->_position.y - _globals->_sceneManager._scene->_sceneBounds.top); + int loadCount = 0; + + if (objPos.x >= scrollerRect.right) { + xAmount = 8; + loadCount = 20; + } + if (objPos.x < scrollerRect.left) { + xAmount = -8; + loadCount = 20; + } + if (objPos.y >= scrollerRect.bottom) { + yAmount = 2; + loadCount = 25; + } + if (objPos.y < scrollerRect.top) { + yAmount = -2; + loadCount = 25; + } + + if (loadCount > 0) + _globals->_sceneManager.setBgOffset(Common::Point(xAmount, yAmount), loadCount); + } + + if (_globals->_sceneManager._sceneLoadCount > 0) { + --_globals->_sceneManager._sceneLoadCount; + _globals->_sceneManager._scene->loadBackground(_globals->_sceneManager._sceneBgOffset.x, + _globals->_sceneManager._sceneBgOffset.y); + } + + // Set up the flag mask + uint32 flagMask = (paneNum == 0) ? OBJFLAG_PANE_0 : OBJFLAG_PANE_1; + + // Initial loop to set up object list and update object position, priority, and flags + for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin(); + i != _globals->_sceneObjects->end(); ++i) { + SceneObject *obj = *i; + objList.push_back(obj); + + if (!(obj->_flags & OBJFLAG_HIDE)) + obj->_flags &= ~OBJFLAG_HIDING; + + // Reposition the bounds of the object to match the desired position + obj->reposition(); + + // Handle updating object priority + if (!(obj->_flags & OBJFLAG_FIXED_PRIORITY)) { + obj->_priority = MIN((int)obj->_position.y - 1, + (int)_globals->_sceneManager._scene->_backgroundBounds.bottom); + } + + if ((_globals->_paneRefreshFlag[paneNum] != 0) || !_globals->_paneRegions[paneNum].empty()) { + obj->_flags |= flagMask; + } + } + + // Check for any intersections, and then sort the object list by priority + checkIntersection(objList, objList.size(), CURRENT_PANENUM); + sortList(objList); + + if (_globals->_paneRefreshFlag[paneNum] == 1) { + // Load the background + _globals->_sceneManager._scene->refreshBackground(0, 0); + } + + _globals->_sceneManager._scene->_sceneBounds.left &= ~3; + _globals->_sceneManager._scene->_sceneBounds.right &= ~3; + _globals->_sceneOffset.x &= ~3; + + if (_globals->_paneRefreshFlag[paneNum] != 0) { + // Change the background + Rect tempRect = _globals->_sceneManager._scene->_sceneBounds; + tempRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y); + ScenePalette::changeBackground(tempRect, _globals->_sceneManager._fadeMode); + } else { + for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) { + SceneObject *obj = objList[objIndex]; + + if ((obj->_flags & flagMask) && obj->_paneRects[paneNum].isValidRect()) + obj->updateScreen(); + } + + _globals->_paneRegions[paneNum].draw(); + } + + _globals->_paneRegions[paneNum].setRect(0, 0, 0, 0); +redraw: + // Main draw loop + for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) { + SceneObject *obj = objList[objIndex]; + + if ((obj->_flags & flagMask) && !(obj->_flags & OBJFLAG_HIDE)) { + obj->_paneRects[paneNum] = obj->_bounds; + obj->draw(); + } + } + + // Update the palette + _globals->_sceneManager.fadeInIfNecessary(); + _globals->_sceneManager._loadMode = 0; + _globals->_paneRefreshFlag[paneNum] = 0; + + // Loop through the object list, removing any objects and refreshing the screen as necessary + for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) { + SceneObject *obj = objList[objIndex]; + + if (obj->_flags & OBJFLAG_HIDE) + obj->_flags |= OBJFLAG_HIDING; + obj->_flags &= ~flagMask; + if (obj->_flags & OBJFLAG_REMOVE) { + obj->_flags |= OBJFLAG_PANES; + + checkIntersection(objList, objIndex, CURRENT_PANENUM); + + obj->updateScreen(); + obj->removeObject(); + + // FIXME: Currently, removing objects causes screen flickers when the removed object intersects + // another drawn object, since the background is briefly redrawn over the object. For now, I'm + // using a forced jump back to redraw objects. In the long term, I should figure out how the + // original game does this properly + objList.remove_at(objIndex); + goto redraw; + } + } + } +} + +void SceneObjectList::checkIntersection(Common::Array<SceneObject *> &ObjList, uint ObjIndex, int PaneNum) { + uint32 flagMask = (PaneNum == 0) ? OBJFLAG_PANE_0 : OBJFLAG_PANE_1; + SceneObject *obj = (ObjIndex == ObjList.size()) ? NULL : ObjList[ObjIndex]; + Rect rect1; + + for (uint idx = 0; idx < ObjList.size(); ++idx) { + SceneObject *currObj = ObjList[idx]; + + if (ObjIndex == ObjList.size()) { + if (currObj->_flags & flagMask) + checkIntersection(ObjList, idx, PaneNum); + } else if (idx != ObjIndex) { + Rect &paneRect = obj->_paneRects[PaneNum]; + Rect objBounds = currObj->_bounds; + if (paneRect.isValidRect()) + objBounds.extend(paneRect); + + Rect objBounds2 = currObj->_bounds; + if (paneRect.isValidRect()) + objBounds2.extend(paneRect); + + objBounds.left &= ~3; + objBounds.right += 3; + objBounds.right &= ~3; + objBounds2.left &= ~3; + objBounds2.right += 3; + objBounds2.right &= ~3; + + if (objBounds.intersects(objBounds2) && !(currObj->_flags & flagMask)) { + currObj->_flags |= flagMask; + checkIntersection(ObjList, idx, PaneNum); + } + } + } +} + +struct SceneObjectLess { + bool operator()(const SceneObject *x, const SceneObject *y) const { + if (y->_priority > x->_priority) + return true; + else if ((y->_priority == x->_priority) && (y->_position.y > x->_position.y)) + return true; + else if ((y->_priority == x->_priority) && (y->_position.y == x->_position.y) && + (y->_yDiff > x->_yDiff)) + return true; + + return false; + } +}; + +void SceneObjectList::sortList(Common::Array<SceneObject *> &ObjList) { + Common::sort(ObjList.begin(), ObjList.end(), SceneObjectLess()); +} + +void SceneObjectList::activate() { + SceneObjectList *objectList = _globals->_sceneObjects; + _globals->_sceneObjects = this; + _globals->_sceneObjects_queue.push_front(this); + + // Flag all the objects as modified + SynchronisedList<SceneObject *>::iterator i; + for (i = begin(); i != end(); ++i) { + (*i)->_flags |= OBJFLAG_PANES; + } + + // Replicate all existing objects on the old object list + for (i = objectList->begin(); i != objectList->end(); ++i) { + SceneObject *sceneObj = (*i)->clone(); + sceneObj->_flags |= OBJFLAG_HIDE | OBJFLAG_REMOVE | OBJFLAG_CLONED; + push_front(sceneObj); + } +} + +void SceneObjectList::deactivate() { + if (_globals->_sceneObjects_queue.size() <= 1) + return; + + SceneObjectList *objectList = *_globals->_sceneObjects_queue.begin(); + _globals->_sceneObjects_queue.pop_front(); + _globals->_sceneObjects = *_globals->_sceneObjects_queue.begin(); + + SynchronisedList<SceneObject *>::iterator i; + for (i = objectList->begin(); i != objectList->end(); ++i) { + if (!((*i)->_flags & OBJFLAG_CLONED)) { + SceneObject *sceneObj = (*i)->clone(); + sceneObj->_flags |= OBJFLAG_HIDE | OBJFLAG_REMOVE | OBJFLAG_CLONED; + _globals->_sceneObjects->push_front(sceneObj); + } + } +} + +void SceneObjectList::synchronise(Serialiser &s) { + _objList.synchronise(s); +} + +/*--------------------------------------------------------------------------*/ + +SceneText::SceneText() : SceneObject() { + _fontNumber = 2; + _width = 160; + _textMode = ALIGN_LEFT; + _colour2 = 0; + _colour3 = 0; +} + +SceneText::~SceneText() { +} + +void SceneText::setup(const Common::String &msg) { + GfxManager gfxMan(_textSurface); + gfxMan.activate(); + Rect textRect; + + gfxMan._font.setFontNumber(_fontNumber); + gfxMan._font._colours.foreground = _colour1; + gfxMan._font._colours2.background = _colour2; + gfxMan._font._colours2.foreground = _colour3; + + gfxMan.getStringBounds(msg.c_str(), textRect, _width); + + // Set up a new blank surface to hold the text + _textSurface.create(textRect.width(), textRect.height()); + _textSurface._transColour = 0xff; + _textSurface.fillRect(textRect, _textSurface._transColour); + + // Write the text to the surface + gfxMan._bounds = textRect; + gfxMan._font.writeLines(msg.c_str(), textRect, _textMode); + + // Do post-init, which adds this SceneText object to the scene + postInit(); + gfxMan.deactivate(); +} + +void SceneText::synchronise(Serialiser &s) { + SceneObject::synchronise(s); + + s.syncAsSint16LE(_fontNumber); + s.syncAsSint16LE(_width); + s.syncAsSint16LE(_colour1); + s.syncAsSint16LE(_colour2); + s.syncAsSint16LE(_colour3); + SYNC_ENUM(_textMode, TextAlign); +} + +/*--------------------------------------------------------------------------*/ + +Visage::Visage() { + _resNum = 0; + _rlbNum = 0; + _data = NULL; +} + +Visage::Visage(const Visage &v) { + _resNum = v._resNum; + _rlbNum = v._rlbNum; + _data = v._data; + if (_data) + _vm->_memoryManager.incLocks(_data); +} + +Visage &Visage::operator=(const Visage &s) { + _resNum = s._resNum; + _rlbNum = s._rlbNum; + _data = s._data; + if (_data) + _vm->_memoryManager.incLocks(_data); + + return *this; +} + +void Visage::setVisage(int resNum, int rlbNum) { + if ((_resNum != resNum) || (_rlbNum != rlbNum)) { + _resNum = resNum; + _rlbNum = rlbNum; + DEALLOCATE(_data); + _data = _vm->_dataManager->getResource(RES_VISAGE, resNum, rlbNum); + assert(_data); + } +} + +Visage::~Visage() { + DEALLOCATE(_data); +} + +GfxSurface Visage::getFrame(int frameNum) { + int numFrames = READ_LE_UINT16(_data); + if (frameNum > numFrames) + frameNum = numFrames; + if (frameNum > 0) + --frameNum; + + int offset = READ_UINT32(_data + 2 + frameNum * 4); + byte *frameData = _data + offset; + + return surfaceFromRes(frameData); +} + +int Visage::getFrameCount() const { + return READ_LE_UINT16(_data); +} + +/*--------------------------------------------------------------------------*/ + +void Player::postInit(SceneObjectList *OwnerList) { + SceneObject::postInit(); + + _canWalk = true; + _uiEnabled = true; + _percent = 100; + _field8C = 10; + _moveDiff.x = 4; + _moveDiff.y = 2; +} + +void Player::disableControl() { + _canWalk = false; + _uiEnabled = false; + _globals->_events.setCursor(CURSOR_NONE); +} + +void Player::enableControl() { + _canWalk = true; + _uiEnabled = true; + _globals->_events.setCursor(CURSOR_WALK); + + switch (_globals->_events.getCursor()) { + case CURSOR_WALK: + case CURSOR_LOOK: + case CURSOR_USE: + case CURSOR_TALK: + _globals->_events.setCursor(_globals->_events.getCursor()); + break; + default: + _globals->_events.setCursor(CURSOR_WALK); + break; + } +} + +void Player::process(Event &event) { + if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN) && + (_globals->_events.getCursor() == CURSOR_WALK) && _globals->_player._canWalk && + (_position != event.mousePos) && _globals->_sceneObjects->contains(this)) { + + PlayerMover *newMover = new PlayerMover(); + Common::Point destPos(event.mousePos.x + _globals->_sceneManager._scene->_sceneBounds.left, + event.mousePos.y + _globals->_sceneManager._scene->_sceneBounds.top); + + addMover(newMover, &destPos, NULL); + event.handled = true; + } +} + +void Player::synchronise(Serialiser &s) { + SceneObject::synchronise(s); + + s.syncAsByte(_canWalk); + s.syncAsByte(_uiEnabled); + s.syncAsSint16LE(_field8C); +} + +/*--------------------------------------------------------------------------*/ + +Region::Region(int resNum, int rlbNum, ResourceType ctlType) { + _regionId = rlbNum; + + byte *regionData = _vm->_dataManager->getResource(ctlType, resNum, rlbNum); + assert(regionData); + + // Set the region bounds + _bounds.top = READ_LE_UINT16(regionData + 6); + _bounds.left = READ_LE_UINT16(regionData + 8); + _bounds.bottom = READ_LE_UINT16(regionData + 10); + _bounds.right = READ_LE_UINT16(regionData + 12); + + // Special handling for small size regions + _regionSize = READ_LE_UINT16(regionData); + if (_regionSize == 14) + // No line slices + return; + + // Set up the line slices + for (int y = 0; y < (_regionSize == 22 ? 1 : _bounds.height()); ++y) { + int slicesCount = READ_LE_UINT16(regionData + 16 + y * 4); + int slicesOffset = READ_LE_UINT16(regionData + 14 + y * 4); + assert(slicesCount < 100); + LineSliceSet sliceSet; + sliceSet.load(slicesCount, regionData + 14 + slicesOffset); + + _ySlices.push_back(sliceSet); + } + + DEALLOCATE(regionData); +} + +/** + * Returns true if the given region contains the specified point + * @param pt Specified position + */ +bool Region::contains(const Common::Point &pt) { + // First check if the point falls inside the overall bounding rectangle + if (!_bounds.contains(pt) || _ySlices.empty()) + return false; + + // Get the correct Y line to use + const LineSliceSet &line = getLineSlices(pt.y); + + // Loop through the horizontal slice list to see if the point falls in one + for (uint idx = 0; idx < line.items.size(); ++idx) { + if ((pt.x >= line.items[idx].xs) && (pt.x < line.items[idx].xe)) + return true; + } + + return false; +} + +/** + * Returns true if the given region is empty + */ +bool Region::empty() const { + return !_bounds.isValidRect() && (_regionSize == 14); +} + +void Region::clear() { + _bounds.set(0, 0, 0, 0); + _regionId = 0; + _regionSize = 0; +} + +void Region::setRect(const Rect &r) { + setRect(r.left, r.top, r.right, r.bottom); +} + +void Region::setRect(int xs, int ys, int xe, int ye) { + bool validRect = (ys < ye) && (xs < xe); + _ySlices.clear(); + + if (!validRect) { + _regionSize = 14; + _bounds.set(0, 0, 0, 0); + } else { + _regionSize = 22; + _bounds.set(xs, ys, xe, ye); + + LineSliceSet sliceSet; + sliceSet.load2(1, xs, xe); + + _ySlices.push_back(sliceSet); + } +} + +const LineSliceSet &Region::getLineSlices(int yp) { + return _ySlices[(_regionSize == 22) ? 0 : yp - _bounds.top]; +} + +LineSliceSet Region::sectPoints(int yp, const LineSliceSet &sliceSet) { + if ((yp < _bounds.top) || (yp >= _bounds.bottom)) + return LineSliceSet(); + + const LineSliceSet &ySet = getLineSlices(yp); + return mergeSlices(sliceSet, ySet); +} + +LineSliceSet Region::mergeSlices(const LineSliceSet &set1, const LineSliceSet &set2) { + LineSliceSet result; + + uint set1Index = 0, set2Index = 0; + + while ((set1Index < set1.items.size()) && (set2Index < set2.items.size())) { + if (set1.items[set1Index].xe <= set2.items[set2Index].xs) { + ++set1Index; + } else if (set2.items[set2Index].xe <= set1.items[set1Index].xs) { + ++set2Index; + } else { + bool set1Flag = set1.items[set1Index].xs >= set2.items[set2Index].xs; + const LineSlice &slice = set1Flag ? set1.items[set1Index] : set2.items[set2Index]; + + result.add(slice.xs, MIN(set1.items[set1Index].xe, set2.items[set2Index].xe)); + if (set1Flag) + ++set1Index; + else + ++set2Index; + } + } + + return result; +} + +/** + * Copies the background covered by the given region to the screen surface + */ +void Region::draw() { + Rect &sceneBounds = _globals->_sceneManager._scene->_sceneBounds; + + for (int yp = sceneBounds.top; yp < sceneBounds.bottom; ++yp) { + // Generate a line slice set + LineSliceSet tempSet; + tempSet.add(sceneBounds.left, sceneBounds.right); + LineSliceSet newSet = sectPoints(yp, tempSet); + + // Loop through the calculated slices + for (uint idx = 0; idx < newSet.items.size(); ++idx) { + Rect rect1(newSet.items[idx].xs, yp, newSet.items[idx].xe, yp + 1); + rect1.left &= ~3; + rect1.right = (rect1.right + 3) & ~3; + + Rect rect2 = rect1; + rect1.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y); + rect2.translate(-sceneBounds.left, -sceneBounds.top); + + _globals->gfxManager().getSurface().copyFrom(_globals->_sceneManager._scene->_backSurface, + rect1, rect2); + } + } +} + +void Region::uniteLine(int yp, LineSliceSet &sliceSet) { + // TODO: More properly implement like the original + + // First expand the bounds as necessary to fit in the row + if (_ySlices.empty()) { + _bounds = Rect(sliceSet.items[0].xs, yp, sliceSet.items[sliceSet.items.size() - 1].xe, yp + 1); + _ySlices.push_back(LineSliceSet()); + } + while (yp < _bounds.top) { + _ySlices.insert_at(0, LineSliceSet()); + --_bounds.top; + } + while (yp >= _bounds.bottom) { + _ySlices.push_back(LineSliceSet()); + ++_bounds.bottom; + } + + // Merge the existing line set into the line + LineSliceSet &destSet = _ySlices[yp - _bounds.top]; + for (uint srcIndex = 0; srcIndex < sliceSet.items.size(); ++srcIndex) { + LineSlice &srcSlice = sliceSet.items[srcIndex]; + + // Check if overlaps existing slices + uint destIndex = 0; + while (destIndex < destSet.items.size()) { + LineSlice &destSlice = destSet.items[destIndex]; + if (((srcSlice.xs >= destSlice.xs) && (srcSlice.xs <= destSlice.xe)) || + ((srcSlice.xe >= destSlice.xs) && (srcSlice.xe <= destSlice.xe)) || + ((srcSlice.xs < destSlice.xs) && (srcSlice.xe > destSlice.xe))) { + // Intersecting, so merge them + destSlice.xs = MIN(srcSlice.xs, destSlice.xs); + destSlice.xe = MAX(srcSlice.xe, destSlice.xe); + break; + } + ++destIndex; + } + if (destIndex == destSet.items.size()) { + // No intersecting region found, so add it to the list + destSet.items.push_back(srcSlice); + } + } + + // Check whether to expand the left/bounds bounds + if (destSet.items[0].xs < _bounds.left) + _bounds.left = destSet.items[0].xs; + if (destSet.items[destSet.items.size() - 1].xe > _bounds.right) + _bounds.right = destSet.items[destSet.items.size() - 1].xe; +} + +void Region::uniteRect(const Rect &rect) { + for (int yp = rect.top; yp < rect.bottom; ++yp) { + LineSliceSet sliceSet; + sliceSet.add(rect.left, rect.right); + uniteLine(yp, sliceSet); + } +} + +/*--------------------------------------------------------------------------*/ + +void SceneRegions::load(int sceneNum) { + clear(); + + byte *regionData = _vm->_dataManager->getResource(RES_CONTROL, sceneNum, 9999, true); + + if (regionData) { + int regionCount = READ_LE_UINT16(regionData); + for (int regionCtr = 0; regionCtr < regionCount; ++regionCtr) { + int rlbNum = READ_LE_UINT16(regionData + regionCtr * 6 + 2); + + push_back(Region(sceneNum, rlbNum)); + } + + DEALLOCATE(regionData); + } +} + +int SceneRegions::indexOf(const Common::Point &pt) { + for (SceneRegions::iterator i = begin(); i != end(); ++i) { + if ((*i).contains(pt)) + return (*i)._regionId; + } + + return 0; +} + +/*--------------------------------------------------------------------------*/ + +SoundHandler::SoundHandler() { + _action = NULL; + _field280 = -1; + if (_globals) + _globals->_sceneListeners.push_back(this); +} + +SoundHandler::~SoundHandler() { + if (_globals) + _globals->_sceneListeners.remove(this); +} + +void SoundHandler::dispatch() { + EventHandler::dispatch(); + int v = _sound.proc12(); + + if (v != -1) { + _field280 = v; + _sound.proc2(-1); + + if (_action) + _action->signal(); + } + + if (_field280 != -1) { + // FIXME: Hardcoded to only flag a sound ended if an action has been set + if (_action) { +// if (!_sound.proc3()) { + _field280 = -1; + if (_action) { + _action->signal(); + _action = NULL; + } + } + } +} + +void SoundHandler::startSound(int soundNum, Action *action, int volume) { + _action = action; + _field280 = 0; + setVolume(volume); + _sound.startSound(soundNum); + + warning("TODO: SoundHandler::startSound"); +} + + +/*--------------------------------------------------------------------------*/ + +void SceneItemList::addItems(SceneItem *first, ...) { + va_list va; + va_start(va, first); + + SceneItem *p = first; + while (p) { + push_back(p); + p = va_arg(va, SceneItem *); + } +} + +/*--------------------------------------------------------------------------*/ + +RegionSupportRec WalkRegion::_processList[PROCESS_LIST_SIZE]; + +void RegionSupportRec::process() { + if (_xDiff < _yDiff) { + _halfDiff += _xDiff; + if (_halfDiff > _yDiff) { + _halfDiff -= _yDiff; + _xp += _xDirection; + } + } else { + do { + _xp += _xDirection; + _halfDiff += _yDiff; + } while (_halfDiff <= _xDiff); + _halfDiff -= _xDiff; + } + --_yDiff2; +} + +/*--------------------------------------------------------------------------*/ + +void WalkRegion::loadRegion(byte *dataP, int size) { + // First clear the region + clear(); + + // Decode the data for the region + int dataCount, regionHeight; + loadProcessList(dataP, size, dataCount, regionHeight); + + int processIndex = 0, idx2 = 0, count; + for (int yp = _processList[0]._yp; yp < regionHeight; ++yp) { + process3(yp, dataCount, processIndex, idx2); + process4(yp, processIndex, idx2, count); + + loadRecords(yp, count, processIndex); + } +} + +void WalkRegion::loadProcessList(byte *dataP, int dataSize, int &dataIndex, int ®ionHeight) { + dataIndex = 0; + int x1 = READ_LE_UINT16(dataP + (dataSize - 1) * 4); + int y1 = READ_LE_UINT16(dataP + (dataSize - 1) * 4 + 2); + regionHeight = y1; + + for (int idx = 0; idx < dataSize; ++idx) { + int xp = READ_LE_UINT16(dataP + idx * 4); + int yp = READ_LE_UINT16(dataP + idx * 4 + 2); + if (yp != y1) { + /* + * Commented out: doesn't seem to be used + int v; + if (idx == (dataSize - 1)) + v = READ_LE_UINT16(dataP + 2); + else + v = process1(idx, dataP, dataSize); + warning("TODO: v not used? - %d", v); + */ + process2(dataIndex, x1, y1, xp, yp); + ++dataIndex; + } + + // Keep regionHeight as the maximum of any y + if (yp > regionHeight) + regionHeight = yp; + + x1 = xp; + y1 = yp; + } +} + +int WalkRegion::process1(int idx, byte *dataP, int dataSize) { + int idx2 = idx + 1; + if (idx2 == dataSize) + idx2 = 0; + + while (READ_LE_UINT16(dataP + idx2 * 4 + 2) == READ_LE_UINT16(dataP + idx * 4 + 2)) { + if (idx2 == (dataSize - 1)) + idx2 = 0; + else + ++idx2; + } + + return READ_LE_UINT16(dataP + idx2 * 4 + 2); +} + +void WalkRegion::process2(int dataIndex, int x1, int y1, int x2, int y2) { + int xDiff = ABS(x2 - x1); + int yDiff = ABS(y2 - y1); + int halfDiff = MAX(xDiff, yDiff) / 2; + int yMax = MIN(y1, y2); + + while (dataIndex && (_processList[dataIndex - 1]._yp > yMax)) { + _processList[dataIndex] = _processList[dataIndex - 1]; + --dataIndex; + } + _processList[dataIndex]._yp = yMax; + + _processList[dataIndex]._xp = (y1 >= y2) ? x2 : x1; + _processList[dataIndex]._xDiff = xDiff; + _processList[dataIndex]._yDiff = yDiff; + _processList[dataIndex]._halfDiff = halfDiff; + + int xTemp = (y1 >= y2) ? x1 - x2 : x2 - x1; + _processList[dataIndex]._xDirection = (xTemp == 0) ? 0 : ((xTemp < 0) ? -1 : 1); + _processList[dataIndex]._yDiff2 = yDiff; +} + +void WalkRegion::process3(int yp, int dataCount, int &idx1, int &idx2) { + while ((idx2 < (dataCount - 1)) && (_processList[idx2 + 1]._yp <= yp)) + ++idx2; + while (!_processList[idx1]._yDiff2) + ++idx1; +} + +void WalkRegion::process4(int yp, int idx1, int idx2, int &count) { + count = 0; + for (int idx = idx1; idx <= idx2; ++idx) { + if (_processList[idx]._yDiff2 > 0) + ++count; + process5(idx, idx1); + } +} + +void WalkRegion::process5(int idx1, int idx2) { + while ((idx1 > idx2) && (_processList[idx1 - 1]._xp > _processList[idx1]._xp)) { + SWAP(_processList[idx1], _processList[idx1 - 1]); + --idx1; + } +} + +void WalkRegion::loadRecords(int yp, int size, int processIndex) { + LineSliceSet sliceSet; + int sliceCount = size / 2; + + for (int idx = 0; idx < sliceCount; ++idx, ++processIndex) { + while (!_processList[processIndex]._yDiff2) + ++processIndex; + + int sliceXs = _processList[processIndex]._xp; + _processList[processIndex].process(); + + do { + ++processIndex; + } while (!_processList[processIndex]._yDiff2); + + int sliceXe = _processList[processIndex]._xp; + _processList[processIndex].process(); + + sliceSet.items.push_back(LineSlice(sliceXs, sliceXe)); + } + + uniteLine(yp, sliceSet); +} + +/*--------------------------------------------------------------------------*/ + +void WRField18::load(byte *data) { + _pt1.x = READ_LE_UINT16(data); + _pt1.y = READ_LE_UINT16(data + 2); + _pt2.x = READ_LE_UINT16(data + 4); + _pt2.y = READ_LE_UINT16(data + 6); + _v = READ_LE_UINT16(data + 8); +} + +/*--------------------------------------------------------------------------*/ + +void WalkRegions::clear() { + _regionList.clear(); + _field18.clear(); + _idxList.clear(); + _idxList2.clear(); +} + +void WalkRegions::load(int sceneNum) { + clear(); + + _resNum = sceneNum; + byte *regionData = _vm->_dataManager->getResource(RES_WALKRGNS, sceneNum, 1, true); + if (!regionData) { + // No data, so return + _resNum = -1; + return; + } + + byte *dataP; + int dataSize; + + // Load the field 18 list + dataP = _vm->_dataManager->getResource(RES_WALKRGNS, sceneNum, 2); + dataSize = _vm->_memoryManager.getSize(dataP); + assert(dataSize % 10 == 0); + + byte *p = dataP; + for (int idx = 0; idx < (dataSize / 10); ++idx, p += 10) { + WRField18 rec; + rec.load(p); + _field18.push_back(rec); + } + + DEALLOCATE(dataP); + + // Load the idx list + dataP = _vm->_dataManager->getResource(RES_WALKRGNS, sceneNum, 3); + dataSize = _vm->_memoryManager.getSize(dataP); + assert(dataSize % 2 == 0); + + p = dataP; + for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2) + _idxList.push_back(READ_LE_UINT16(p)); + + DEALLOCATE(dataP); + + // Load the secondary idx list + dataP = _vm->_dataManager->getResource(RES_WALKRGNS, sceneNum, 4); + dataSize = _vm->_memoryManager.getSize(dataP); + assert(dataSize % 2 == 0); + + p = dataP; + for (int idx = 0; idx < (dataSize / 2); ++idx, p += 2) + _idxList2.push_back(READ_LE_UINT16(p)); + + DEALLOCATE(dataP); + + // Handle the loading of the actual regions themselves + dataP = _vm->_dataManager->getResource(RES_WALKRGNS, sceneNum, 5); + + byte *pWalkRegion = regionData + 16; + byte *srcP = dataP; + for (; (int16)READ_LE_UINT16(pWalkRegion) != -20000; pWalkRegion += 16) { + WalkRegion wr; + + // Set the Walk region specific fields + wr._pt.x = (int16)READ_LE_UINT16(pWalkRegion); + wr._pt.y = (int16)READ_LE_UINT16(pWalkRegion + 2); + wr._idxListIndex = READ_LE_UINT32(pWalkRegion + 4); + wr._idxList2Index = READ_LE_UINT32(pWalkRegion + 8); + + // Region in the region data + int size = READ_LE_UINT16(srcP); + srcP += 2; + wr.loadRegion(srcP, size); + + srcP += size * 4; + _regionList.push_back(wr); + } + + DEALLOCATE(dataP); + DEALLOCATE(regionData); +} + +/** + * Returns the index of the walk region that contains the given point + * @param pt Point to locate + * @param indexList List of region indexes that should be ignored + */ +int WalkRegions::indexOf(const Common::Point &pt, const Common::List<int> *indexList) { + for (uint idx = 0; idx < _regionList.size(); ++idx) { + if ((!indexList || contains(*indexList, int(idx + 1))) && _regionList[idx].contains(pt)) + return idx + 1; + } + + return -1; +} + +/*--------------------------------------------------------------------------*/ + +void ScenePriorities::load(int resNum) { + _resNum = resNum; + clear(); + + byte *regionData = _vm->_dataManager->getResource(RES_PRIORITY, resNum, 9999, true); + + if (regionData) { + int regionCount = READ_LE_UINT16(regionData); + for (int regionCtr = 0; regionCtr < regionCount; ++regionCtr) { + int rlbNum = READ_LE_UINT16(regionData + regionCtr * 6 + 2); + + push_back(Region(resNum, rlbNum, RES_PRIORITY)); + } + + DEALLOCATE(regionData); + } +} + +Region *ScenePriorities::find(int priority) { + // If no priority regions are loaded, then return the placeholder region + if (empty()) + return &_defaultPriorityRegion; + + if (priority > 255) + priority = 255; + + // Loop through the regions to find the closest for the givne priority level + int minRegionId = 9998; + Region *region = NULL; + for (ScenePriorities::iterator i = begin(); i != end(); ++i) { + Region *r = &(*i); + int regionId = r->_regionId; + + if ((regionId > priority) && (regionId < minRegionId)) { + minRegionId = regionId; + region = r; + } + } + + assert(region); + return region; +} + +/*--------------------------------------------------------------------------*/ + +void FloatSet::add(double v1, double v2, double v3) { + _float1 += v1; + _float2 += v2; + _float3 += v3; +} + +void FloatSet::proc1(double v) { + double diff = (cos(v) * _float1) - (sin(v) * _float2); + _float2 = (sin(v) * _float1) + (cos(v) * _float2); + _float1 = diff; +} + +double FloatSet::sqrt(FloatSet &floatSet) { + double f1Diff = _float1 - floatSet._float1; + double f2Diff = _float2 - floatSet._float2; + double f3Diff = _float3 - floatSet._float3; + + return ::sqrt(f1Diff * f1Diff + f2Diff * f2Diff + f3Diff * f3Diff); +} + +/*--------------------------------------------------------------------------*/ + +GameHandler::GameHandler() : EventHandler() { + _nextWaitCtr = 1; + _waitCtr.setCtr(1); + _field14 = 10; +} + +GameHandler::~GameHandler() { + if (_globals) + _globals->_game.removeHandler(this); +} + +void GameHandler::execute() { + if (_waitCtr.decCtr() == 0) { + _waitCtr.setCtr(_nextWaitCtr); + dispatch(); + } +} + +void GameHandler::synchronise(Serialiser &s) { + _lockCtr.synchronise(s); + _waitCtr.synchronise(s); + s.syncAsSint16LE(_nextWaitCtr); + s.syncAsSint16LE(_field14); +} + +/*--------------------------------------------------------------------------*/ + +SceneHandler::SceneHandler() { + _saveGameSlot = -1; + _loadGameSlot = -1; +} + +void SceneHandler::registerHandler() { + postInit(); + _globals->_game.addHandler(this); +} + +void SceneHandler::postInit(SceneObjectList *OwnerList) { + _delayTicks = 2; + + _globals->_scenePalette.loadPalette(0); + _globals->_scenePalette.refresh(); + + // TODO: Bunch of other scene related setup goes here + _globals->_soundManager.postInit(); + + // Set some default flags and cursor + _globals->setFlag(12); + _globals->setFlag(34); + _globals->_events.setCursor(CURSOR_WALK); + + // Set the screen to scroll in response to the player moving off-screen + _globals->_scrollFollower = &_globals->_player; + + // Set the object's that will be in the player's inventory by default + _globals->_inventory._stunner._sceneNumber = 1; + _globals->_inventory._scanner._sceneNumber = 1; + _globals->_inventory._ring._sceneNumber = 1; + + // Switch to the title screen + _globals->_sceneManager.setNewScene(1000); +} + +void SceneHandler::process(Event &event) { + // Main keypress handler + if ((event.eventType == EVENT_KEYPRESS) && !event.handled) { + switch (event.kbd.keycode) { + case Common::KEYCODE_F1: + // F1 - Help + _globals->_events.setCursor(CURSOR_ARROW); + MessageDialog::show(HELP_MSG, OK_BTN_STRING); + break; + + case Common::KEYCODE_F2: { + // F2 - Sound Options + ConfigDialog *dlg = new ConfigDialog(); + dlg->runModal(); + delete dlg; + _globals->_events.setCursorFromFlag(); + break; + } + + case Common::KEYCODE_F3: + // F3 - Quit + _globals->_game.quitGame(); + event.handled = false; + break; + + case Common::KEYCODE_F4: + // F4 - Restart + _globals->_game.restartGame(); + _globals->_events.setCursorFromFlag(); + break; + + case Common::KEYCODE_F7: + // F7 - Restore + _globals->_game.restoreGame(); + _globals->_events.setCursorFromFlag(); + break; + + case Common::KEYCODE_F10: + // F10 - Pause + GfxDialog::setPalette(); + MessageDialog::show(GAME_PAUSED_MSG, OK_BTN_STRING); + _globals->_events.setCursorFromFlag(); + break; + + default: + break; + } + + _globals->_events.setCursorFromFlag(); + } + + // Check for displaying right-click dialog + if ((event.eventType == EVENT_BUTTON_DOWN) && (event.btnState == BTNSHIFT_RIGHT) && + _globals->_player._uiEnabled) { + RightClickDialog *dlg = new RightClickDialog(); + dlg->execute(); + delete dlg; + + event.handled = true; + return; + } + + // If there is an active scene, pass the event to it + if (_globals->_sceneManager._scene) + _globals->_sceneManager._scene->process(event); + + if (!event.handled) { + // Separate check for F5 - Save key + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_F5)) { + // F5 - Save + _globals->_game.saveGame(); + event.handled = true; + _globals->_events.setCursorFromFlag(); + } + + // Check for debugger + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_d) && + (event.kbd.flags & Common::KBD_CTRL)) { + // Attach to the debugger + _vm->_debugger->attach(); + _vm->_debugger->onFrame(); + } + + // Mouse press handling + if (_globals->_player._uiEnabled && (event.eventType == EVENT_BUTTON_DOWN) && + !_globals->_sceneItems.empty()) { + // Scan the item list to find one the mouse is within + SynchronisedList<SceneItem *>::iterator i = _globals->_sceneItems.begin(); + while ((i != _globals->_sceneItems.end()) && !(*i)->contains(event.mousePos)) + ++i; + + if (i != _globals->_sceneItems.end()) { + // Pass the action to the item + (*i)->doAction(_globals->_events.getCursor()); + event.handled = _globals->_events.getCursor() != CURSOR_WALK; + + if (_globals->_player._uiEnabled && _globals->_player._canWalk && + (_globals->_events.getCursor() != CURSOR_LOOK)) { + _globals->_events.setCursor(CURSOR_WALK); + } else if (_globals->_player._canWalk && (_globals->_events.getCursor() != CURSOR_LOOK)) { + _globals->_events.setCursor(CURSOR_WALK); + } else if (_globals->_player._uiEnabled && (_globals->_events.getCursor() != CURSOR_LOOK)) { + _globals->_events.setCursor(CURSOR_USE); + } + } + + // Handle player processing + _globals->_player.process(event); + } + } +} + +void SceneHandler::dispatch() { + // Handle game saving and loading + if (_saveGameSlot != -1) { + int saveSlot = _saveGameSlot; + _saveGameSlot = -1; + if (_saver->save(saveSlot, _saveName) != Common::kNoError) + GUIErrorMessage(SAVE_ERROR_MSG); + } + if (_loadGameSlot != -1) { + int loadSlot = _loadGameSlot; + _loadGameSlot = -1; + _saver->restore(loadSlot); + _globals->_events.setCursorFromFlag(); + } + + _globals->_soundManager.dispatch(); + _globals->_scenePalette.signalListeners(); + + // Dispatch to any objects registered in the scene + _globals->_sceneObjects->recurse(SceneHandler::dispatchObject); + + // If a scene is active, then dispatch to it + if (_globals->_sceneManager._scene) + _globals->_sceneManager._scene->dispatch(); + + //TODO: Figure out purpose of the given list + //_globals->_regions.forEach(SceneHandler::handleListener); + + Event event; + while (_globals->_events.getEvent(event)) + process(event); + + // Handle drawing the contents of the scene + if (_globals->_sceneManager._scene) + _globals->_sceneObjects->draw(); + + // Check to see if any scene change is required + _globals->_sceneManager.checkScene(); + + // Signal the ScummVM debugger + _vm->_debugger->onFrame(); + + // Delay between frames + _globals->_events.delay(_delayTicks); +} + +void SceneHandler::dispatchObject(EventHandler *obj) { + obj->dispatch(); +} + +void SceneHandler::saveListener(Serialiser &ser) { + warning("TODO: SceneHandler::saveListener"); +} + +/*--------------------------------------------------------------------------*/ + +void Game::execute() { + // Main game loop + bool activeFlag = false; + do { + // Process all currently atcive game handlers + activeFlag = false; + for (SynchronisedList<GameHandler *>::iterator i = _handlers.begin(); i != _handlers.end(); ++i) { + GameHandler *gh = *i; + if (gh->_lockCtr.getCtr() == 0) { + gh->execute(); + activeFlag = true; + } + } + } while (activeFlag && !_vm->getEventManager()->shouldQuit()); +} + +void Game::restartGame() { + if (MessageDialog::show(RESTART_MSG, CANCEL_BTN_STRING, RESTART_BTN_STRING) == 1) + _globals->_game.restart(); +} + +void Game::saveGame() { + if (_globals->getFlag(50)) + MessageDialog::show(SAVING_NOT_ALLOWED_MSG, OK_BTN_STRING); + else { + // Show the save dialog + handleSaveLoad(true, _globals->_sceneHandler._saveGameSlot, _globals->_sceneHandler._saveName); + } +} + +void Game::restoreGame() { + if (_globals->getFlag(50)) + MessageDialog::show(RESTORING_NOT_ALLOWED_MSG, OK_BTN_STRING); + else { + // Show the load dialog + handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName); + } +} + +void Game::quitGame() { + if (MessageDialog::show(QUIT_CONFIRM_MSG, CANCEL_BTN_STRING, QUIT_BTN_STRING) == 1) + _vm->quitGame(); +} + +void Game::handleSaveLoad(bool saveFlag, int &saveSlot, Common::String &saveName) { + const EnginePlugin *plugin = 0; + EngineMan.findGame(_vm->getGameId(), &plugin); + GUI::SaveLoadChooser *dialog; + if (saveFlag) + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save")); + else + dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load")); + + dialog->setSaveMode(saveFlag); + + saveSlot = dialog->runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); + saveName = dialog->getResultString(); + + delete dialog; +} + +void Game::restart() { + _globals->_scenePalette.clearListeners(); + _globals->_soundHandler.proc3(); + + // Reset the flags + _globals->reset(); + _globals->setFlag(34); + + // Clear save/load slots + _globals->_sceneHandler._saveGameSlot = -1; + _globals->_sceneHandler._loadGameSlot = -1; + + _globals->_stripNum = 0; + _globals->_events.setCursor(CURSOR_WALK); + + // Reset item properties + _globals->_inventory._stunner._sceneNumber = 1; + _globals->_inventory._scanner._sceneNumber = 1; + _globals->_inventory._stasisBox._sceneNumber = 5200; + _globals->_inventory._infoDisk._sceneNumber = 40; + _globals->_inventory._stasisNegator._sceneNumber = 0; + _globals->_inventory._keyDevice._sceneNumber = 0; + _globals->_inventory._medkit._sceneNumber = 2280; + _globals->_inventory._ladder._sceneNumber = 4100; + _globals->_inventory._rope._sceneNumber = 4150; + _globals->_inventory._key._sceneNumber = 7700; + _globals->_inventory._translator._sceneNumber = 2150; + _globals->_inventory._paper._sceneNumber = 7700; + _globals->_inventory._waldos._sceneNumber = 0; + _globals->_inventory._ring._sceneNumber = 1; + _globals->_inventory._stasisBox2._sceneNumber = 8100; + _globals->_inventory._cloak._sceneNumber = 9850; + _globals->_inventory._tunic._sceneNumber = 9450; + _globals->_inventory._candle._sceneNumber = 9500; + _globals->_inventory._straw._sceneNumber = 9400; + _globals->_inventory._scimitar._sceneNumber = 9850; + _globals->_inventory._sword._sceneNumber = 9850; + _globals->_inventory._helmet._sceneNumber = 9500; + _globals->_inventory._items._sceneNumber = 4300; + _globals->_inventory._concentrator._sceneNumber = 4300; + _globals->_inventory._nullifier._sceneNumber = 4300; + _globals->_inventory._peg._sceneNumber = 4045; + _globals->_inventory._vial._sceneNumber = 5100; + _globals->_inventory._jacket._sceneNumber = 9850; + _globals->_inventory._tunic2._sceneNumber = 9850; + _globals->_inventory._bone._sceneNumber = 5300; + _globals->_inventory._jar._sceneNumber = 7700; + _globals->_inventory._emptyJar._sceneNumber = 7700; + + // Change to the first game scene + _globals->_sceneManager.changeScene(30); +} + +void Game::endGame(int resNum, int lineNum) { + _globals->_events.setCursor(CURSOR_WALK); + Common::String msg = _vm->_dataManager->getMessage(resNum, lineNum); + bool savesExist = _saver->savegamesExist(); + + if (!savesExist) { + // No savegames exist, so prompt the user to restart or quit + if (MessageDialog::show(msg, QUIT_BTN_STRING, RESTART_BTN_STRING) == 0) + _vm->quitGame(); + else + restart(); + } else { + // Savegames exist, so prompt for Restore/Restart + bool breakFlag; + do { + if (MessageDialog::show(msg, RESTART_BTN_STRING, RESTORE_BTN_STRING) == 0) { + breakFlag = true; + } else { + handleSaveLoad(false, _globals->_sceneHandler._loadGameSlot, _globals->_sceneHandler._saveName); + breakFlag = _globals->_sceneHandler._loadGameSlot > 0; + } + } while (!breakFlag); + } + + _globals->_events.setCursorFromFlag(); +} + +} // End of namespace tSage diff --git a/engines/tsage/core.h b/engines/tsage/core.h new file mode 100644 index 0000000000..77923606d1 --- /dev/null +++ b/engines/tsage/core.h @@ -0,0 +1,956 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_CORE_H +#define TSAGE_CORE_H + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/error.h" +#include "common/list.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "tsage/events.h" +#include "tsage/graphics.h" +#include "tsage/resources.h" +#include "tsage/saveload.h" +#include "tsage/sound.h" + +namespace tSage { + +#define MAX_FLAGS 256 + +class EventHandler; +class SceneObject; +class SceneObjectList; +class ObjectMover; +class Action; +class Serialiser; + +class InvObject : public SavedObject { +public: + int _sceneNumber; + int _displayResNum; + int _rlbNum; + int _cursorNum; + Rect _bounds; + CursorType _cursorId; + Common::String _description; + int _iconResNum; +public: + InvObject(int sceneNumber, int rlbNum, int cursorNum, CursorType cursorId, const Common::String description); + + bool inInventory() const { return _sceneNumber == 1; } + void setCursor(); + + virtual Common::String getClassName() { return "InvObject"; } + virtual void synchronise(Serialiser &s) { + s.syncAsUint16LE(_sceneNumber); + } +}; + +class InvObjectList : public SavedObject { +public: + InvObject _stunner; + InvObject _scanner; + InvObject _stasisBox; + InvObject _infoDisk; + InvObject _stasisNegator; + InvObject _keyDevice; + InvObject _medkit; + InvObject _ladder; + InvObject _rope; + InvObject _key; + InvObject _translator; + InvObject _ale; + InvObject _paper; + InvObject _waldos; + InvObject _stasisBox2; + InvObject _ring; + InvObject _cloak; + InvObject _tunic; + InvObject _candle; + InvObject _straw; + InvObject _scimitar; + InvObject _sword; + InvObject _helmet; + InvObject _items; + InvObject _concentrator; + InvObject _nullifier; + InvObject _peg; + InvObject _vial; + InvObject _jacket; + InvObject _tunic2; + InvObject _bone; + InvObject _jar; + InvObject _emptyJar; + + SynchronisedList<InvObject *> _itemList; + InvObject *_selectedItem; +public: + InvObjectList(); + + virtual Common::String getClassName() { return "InvObjectList"; } + virtual void synchronise(Serialiser &s); +}; + +/*--------------------------------------------------------------------------*/ + +/** + * Basic reference counter class + */ +class RefCounter : public Serialisable { +private: + int _ctr; +public: + RefCounter() { clear(); } + virtual ~RefCounter() {} + + RefCounter(int v) { _ctr = v; } + + void clear() { _ctr = 0; } + void setCtr(int v) { _ctr = v; } + int decCtr() { + if (_ctr > 0) --_ctr; + return _ctr; + } + int incCtr() { return ++_ctr; } + int getCtr() const { return _ctr; } + + virtual void synchronise(Serialiser &s) { s.syncAsSint16LE(_ctr); } +}; + +class EventHandler : public SavedObject { +public: + Action *_action; + + EventHandler() : SavedObject() { _action = NULL; } + virtual ~EventHandler() { destroy(); } + + virtual void synchronise(Serialiser &s) { SYNC_POINTER(_action); } + virtual Common::String getClassName() { return "EventHandler"; } + virtual void postInit(SceneObjectList *OwnerList = NULL) {} + virtual void remove() {} + virtual void signal() {} + virtual void process(Event &event) {} + virtual void dispatch(); + virtual void setAction(Action *action) { setAction(action, NULL); } + virtual void setAction(Action *action, EventHandler *fmt, ...); + virtual void destroy() {}; +}; + +class Action : public EventHandler { +public: + EventHandler *_owner; + int _actionIndex; + int _delayFrames; + uint32 _startFrame; + int _field16; + EventHandler *_fmt; + + Action(); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "Action"; } + virtual void remove(); + virtual void process(Event &event); + virtual void dispatch(); + virtual void attached(EventHandler *newOwner, EventHandler *fmt, va_list va); + + void attach(EventHandler *newOwner, EventHandler *fmt, ...) { + va_list va; + va_start(va, fmt); + attached(newOwner, fmt, va); + va_end(va); + } + int getActionIndex() const { return _actionIndex; } + void setActionIndex(int index) { _actionIndex = index; } + void setDelay(int numFrames); +}; + +class ActionExt : public Action { +public: + int _state; +}; + +class ObjectMover : public EventHandler { +public: + Common::Point _destPosition; + Common::Point _moveDelta; + Common::Point _moveSign; + int _minorDiff; + int _majorDiff; + int _field1A; + Action *_action; + SceneObject *_sceneObject; +public: + ObjectMover() { _action = NULL; _sceneObject = NULL; } + virtual ~ObjectMover(); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "ObjectMover"; } + virtual void remove(); + virtual void dispatch(); + virtual void startMove(SceneObject *sceneObj, va_list va) {} + virtual void setup(const Common::Point &destPos); + virtual bool dontMove() const; + virtual void endMove(); +}; + +class ObjectMover2 : public ObjectMover { +public: + SceneObject *_destObject; + int _minArea; + int _maxArea; +public: + ObjectMover2(); + virtual ~ObjectMover2() {} + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "ObjectMover2"; } + virtual void dispatch(); + virtual void startMove(SceneObject *sceneObj, va_list va); + virtual void endMove(); +}; + +class ObjectMover3 : public ObjectMover2 { +public: + virtual Common::String getClassName() { return "ObjectMover3"; } + virtual void dispatch(); + virtual void startMove(SceneObject *sceneObj, va_list va); + virtual void endMove(); +}; + +class NpcMover : public ObjectMover { +public: + virtual Common::String getClassName() { return "NpcMover"; } + virtual void startMove(SceneObject *sceneObj, va_list va); +}; + +#define MAX_ROUTE_SIZE 20 +#define ROUTE_END_VAL -20000 + +class RouteEnds { +public: + Common::Point moveSrc; + Common::Point moveDest; +}; + +class PlayerMover : public NpcMover { +protected: + void setDest(const Common::Point &destPos); + void pathfind(Common::Point *routeList, Common::Point srcPos, Common::Point destPos, RouteEnds routeEnds); + int regionIndexOf(const Common::Point &pt); + int regionIndexOf(int xp, int yp) { return regionIndexOf(Common::Point(xp, yp)); } + int findClosestRegion(Common::Point &pt, const Common::List<int> &indexList); + int checkMover(Common::Point &srcPos, const Common::Point &destPos); + void checkMovement2(const Common::Point &pt1, const Common::Point &pt2, int numSteps, Common::Point &ptOut); + int proc1(int *routeList, int srcRegion, int destRegion, int &v); + + static Common::Point *findLinePoint(RouteEnds *routeEnds, Common::Point *objPos, int length, Common::Point *outPos); + static int findDistance(const Common::Point &pt1, const Common::Point &pt2); + static bool sub_F8E5(const Common::Point &pt1, const Common::Point &pt2, const Common::Point &pt3, + const Common::Point &pt4, Common::Point *ptOut = NULL); +public: + Common::Point _finalDest; + Common::Point _routeList[MAX_ROUTE_SIZE]; + int _routeIndex; + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "PlayerMover"; } + virtual void startMove(SceneObject *sceneObj, va_list va); + virtual void endMove(); +}; + +class PlayerMover2 : public PlayerMover { +public: + SceneObject *_destObject; + int _field7E; + int _minArea; + PlayerMover2() : PlayerMover() { _destObject = NULL; } + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "PlayerMover2"; } + virtual void dispatch(); + virtual void startMove(SceneObject *sceneObj, va_list va); + virtual void endMove(); +}; + +/*--------------------------------------------------------------------------*/ + +class ScenePalette; + +class PaletteModifier : public SavedObject { +public: + ScenePalette *_scenePalette; + Action *_action; +public: + PaletteModifier(); + + virtual void synchronise(Serialiser &s) { + SYNC_POINTER(_scenePalette); + SYNC_POINTER(_action); + } + virtual void signal() = 0; + virtual void remove() = 0; +}; + +class PaletteRotation : public PaletteModifier { +public: + bool _disabled; + int _delayFrames; + int _delayCtr; + uint32 _frameNumber; + int _currIndex; + int _start; + int _end; + int _rotationMode; + int _duration; + RGB8 _palette[256]; +public: + PaletteRotation(); + + virtual Common::String getClassName() { return "PaletteRotation"; } + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void remove(); + + void setDisabled(bool v) { _disabled = v; } + void set(ScenePalette *palette, int start, int end, int rotationMode, int duration, Action *action); + void setPalette(ScenePalette *palette, bool disabled); + bool decDuration(); + void setDelay(int amount); +}; + +/*--------------------------------------------------------------------------*/ + +class PaletteUnknown : public PaletteModifier { +public: + int _step, _percent, _field12, _field14; + RGB8 _palette[256]; +public: + virtual Common::String getClassName() { return "PaletteUnknown"; } + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void remove(); +}; + +enum FadeMode {FADEMODE_NONE = 0, FADEMODE_GRADUAL = 1, FADEMODE_IMMEDIATE = 2}; + +class ScenePalette : public SavedObject { +public: + RGB8 _palette[256]; + GfxColours _colours; + SynchronisedList<PaletteModifier *> _listeners; + int _field412; + + uint8 _redColour; + uint8 _greenColour; + uint8 _blueColour; + uint8 _aquaColour; + uint8 _purpleColour; + uint8 _limeColour; +public: + ScenePalette(); + ScenePalette(int paletteNum); + + bool loadPalette(int paletteNum); + void refresh(); + void setPalette(int index, int count); + uint8 indexOf(uint r, uint g, uint b, int threshold = 0xffff); + void getPalette(int start = 0, int count = 256); + void signalListeners(); + void clearListeners(); + void fade(const byte *adjustData, bool fullAdjust, int percent); + PaletteRotation *addRotation(int start, int end, int rotationMode, int duration = 0, Action *action = NULL); + PaletteUnknown *addUnkPal(RGB8 *arrBufferRGB, int unkNumb, bool disabled, Action *action); + + static void changeBackground(const Rect &bounds, FadeMode fadeMode); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "ScenePalette"; } +}; + +// DisplayParamType constant set. This must not be an enum +const int SET_WIDTH = 0; +const int SET_X = 1; +const int SET_Y = 2; +const int SET_FONT = 3; +const int SET_BG_COLOUR = 4; +const int SET_FG_COLOUR = 5; +const int SET_KEEP_ONSCREEN = 6; +const int SET_EXT_BGCOLOUR = 7; +const int SET_EXT_FGCOLOUR = 8; +const int SET_POS_MODE = 9; +const int SET_TEXT_MODE = 10; +const int LIST_END = -999; + +class SceneItem : public EventHandler { +public: + Rect _bounds; + Common::String _msg; + int _fieldE, _field10; + Common::Point _position; + int _yDiff; + int _sceneRegionId; +public: + SceneItem() : EventHandler() { _msg = "Feature"; _action = NULL; _sceneRegionId = 0; } + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "SceneItem"; } + virtual void remove(); + virtual void destroy() {} + virtual void startMover(CursorType action) { doAction(action); } + virtual void doAction(int action); + + bool contains(const Common::Point &pt); + void setBounds(const Rect &newBounds) { _bounds = newBounds; } + void setBounds(const int ys, const int xe, const int ye, const int xs) { _bounds = Rect(MIN(xs, xe), MIN(ys, ye), MAX(xs, xe), MAX(ys, ye)); } + static void display(int resNum, int lineNum, ...); + static void display2(int resNum, int lineNum) { + display(resNum, lineNum, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } +}; + +class SceneItemExt : public SceneItem { +public: + int _state; + + virtual Common::String getClassName() { return "SceneItemExt"; } + virtual void synchronise(Serialiser &s) { + SceneItem::synchronise(s); + s.syncAsSint16LE(_state); + } +}; + +class SceneHotspot : public SceneItem { +public: + SceneHotspot() : SceneItem() {} + + virtual Common::String getClassName() { return "SceneHotspot"; } + virtual void doAction(int action); +}; + +class NamedHotspot : public SceneHotspot { +public: + int _resnum, _lookLineNum, _useLineNum; + NamedHotspot() : SceneHotspot() {} + + void setup(const int ys, const int xe, const int ye, const int xs, const int resnum, const int lookLineNum, const int useLineNum); + virtual void doAction(int action); + virtual Common::String getClassName() { return "NamedHotspot"; } +}; + +enum AnimateMode {ANIM_MODE_NONE = 0, ANIM_MODE_1 = 1, ANIM_MODE_2 = 2, ANIM_MODE_3 = 3, + ANIM_MODE_4 = 4, ANIM_MODE_5 = 5, ANIM_MODE_6 = 6, ANIM_MODE_7 = 7, ANIM_MODE_8 = 8}; + +class SceneObject; + +class Visage { +private: + byte *_data; +public: + int _resNum; + int _rlbNum; +public: + Visage(); + Visage(const Visage &v); + ~Visage(); + + void setVisage(int resNum, int rlbNum = 9999); + GfxSurface getFrame(int frameNum); + int getFrameCount() const; + Visage &operator=(const Visage &s); +}; + +class SceneObjectWrapper : public EventHandler { +private: + Visage _visageImages; +public: + SceneObject *_sceneObject; +public: + SceneObjectWrapper() { _sceneObject = NULL; } + virtual ~SceneObjectWrapper() {} + + void setSceneObject(SceneObject *so); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "SceneObjectWrapper"; } + virtual void remove(); + virtual void dispatch(); +}; + +enum ObjectFlags {OBJFLAG_FIXED_PRIORITY = 1, OBJFLAG_NO_UPDATES = 2, OBJFLAG_ZOOMED = 4, + OBJFLAG_SUPPRESS_DISPATCH = 8, OBJFLAG_HIDE = 0x100, OBJFLAG_HIDING = 0x200, OBJFLAG_REMOVE = 0x400, + OBJFLAG_CLONED = 0x800, OBJFLAG_CHECK_REGION = 0x1000, OBJFLAG_PANE_0 = 0x4000, OBJFLAG_PANE_1 = 0x8000, + OBJFLAG_PANES = OBJFLAG_PANE_0 | OBJFLAG_PANE_1 +}; + +class SceneObject : public SceneHotspot { +private: + Visage _visageImages; + + int getNewFrame(); + void animEnded(); + int changeFrame(); + bool isNoMover() const { return !_mover || (_regionIndex > 0); } +public: + uint32 _updateStartFrame; + uint32 _walkStartFrame; + Common::Point _field2E; + int _percent; + int _priority; + int _angle; + uint32 _flags; + int _xs, _xe; + Rect _paneRects[2]; + int _visage; + SceneObjectWrapper *_objectWrapper; + int _strip; + AnimateMode _animateMode; + int _frame; + int _endFrame; + int _field68; + int _frameChange; + int _numFrames; + int _regionIndex; + EventHandler *_mover; + Common::Point _moveDiff; + int _field7A; + Action *_endAction; + uint32 _regionBitList; +public: + SceneObject(); + SceneObject(const SceneObject &so); + virtual ~SceneObject(); + + void setPosition(const Common::Point &p, int yDiff = 0); + void setStrip(int frameNum); + void setStrip2(int frameNum); + void setZoom(int percent); + void updateZoom(); + void changeZoom(int percent); + void setFrame(int frameNum); + void setFrame2(int frameNum); + void setPriority(int priority); + void setPriority2(int priority); + void setVisage(int visage); + void setObjectWrapper(SceneObjectWrapper *objWrapper); + void addMover(ObjectMover *mover, ...); + void getHorizBounds(); + int getRegionIndex(); + int checkRegion(const Common::Point &pt); + void animate(AnimateMode animMode, ...); + SceneObject *clone() const; + void checkAngle(const SceneObject *obj); + void hide(); + void show(); + int getSpliceArea(const SceneObject *obj); + int getFrameCount(); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "SceneObject"; } + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void remove(); + virtual void process(Event &event) { event.handled = true; } + virtual void dispatch(); + virtual void calcAngle(const Common::Point &pt); + virtual void removeObject(); + virtual GfxSurface getFrame(); + virtual void reposition(); + virtual void draw(); + virtual void proc19() {} + virtual void updateScreen(); + void setup(int visage, int stripFrameNum, int frameNum, int posX, int posY, int priority); +}; + +class SceneObjectExt : public SceneObject { +public: + int _state; + + virtual void synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsSint16LE(_state); + } + virtual Common::String getClassName() { return "SceneObjectExt"; } +}; + +class SceneText : public SceneObject { +public: + int _fontNumber; + int _width; + TextAlign _textMode; + int _colour1; + int _colour2; + int _colour3; + GfxSurface _textSurface; +public: + SceneText(); + ~SceneText(); + + void setup(const Common::String &msg); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "SceneText"; } + virtual GfxSurface getFrame() { return _textSurface; } +}; + +class Player : public SceneObject { +public: + bool _canWalk; + bool _uiEnabled; + int _field8C; +public: + Player() : SceneObject() {} + + virtual Common::String getClassName() { return "Player"; } + virtual void synchronise(Serialiser &s); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void process(Event &event); + + void disableControl(); + void enableControl(); +}; + +/*--------------------------------------------------------------------------*/ + +class LineSliceSet { +public: + Common::Array<LineSlice> items; + + void load(int size, const byte *srcP) { + for (int i = 0; i < size; ++i, srcP += 4) + items.push_back(LineSlice(READ_LE_UINT16(srcP), READ_LE_UINT16(srcP + 2))); + } + void load2(int size, ...) { + va_list va; + va_start(va, size); + + while (size-- > 0) { + int xs = va_arg(va, int); + int xe = va_arg(va, int); + items.push_back(LineSlice(xs, xe)); + } + } + + void add(LineSlice &slice) { items.push_back(slice); } + void add(int xs, int xe) { items.push_back(LineSlice(xs, xe)); } + static LineSliceSet mergeSlices(const LineSliceSet &set1, LineSliceSet &set2); +}; + +class Region { +public: + int _regionSize; + int _regionId; + Rect _bounds; + Common::Array<LineSliceSet> _ySlices; +public: + Region() { _regionSize = 0; _regionId = 0; } + Region(int resNum, int rlbNum, ResourceType ctlType = RES_CONTROL); + + bool contains(const Common::Point &pt); + bool empty() const; + void clear(); + void setRect(const Rect &r); + void setRect(int xs, int ys, int xe, int ye); + const LineSliceSet &getLineSlices(int yp); + LineSliceSet sectPoints(int yp, const LineSliceSet &sliceSet); + void draw(); + void uniteLine(int yp, LineSliceSet &sliceSet); + void uniteRect(const Rect &rect); + + static LineSliceSet mergeSlices(const LineSliceSet &set1, const LineSliceSet &set2); +}; + +class SceneRegions : public Common::List<Region> { +public: + void load(int sceneNum); + + int indexOf(const Common::Point &pt); +}; + +class SceneObjectList : public SavedObject { +private: + void checkIntersection(Common::Array<SceneObject *> &ObjList, uint ObjIndex, int PaneNum); + + SynchronisedList<SceneObject *> _objList; + bool _listAltered; +public: + SceneObjectList() { _listAltered = false; } + void sortList(Common::Array<SceneObject *> &ObjList); + + virtual Common::String getClassName() { return "SceneObjectList"; } + virtual void synchronise(Serialiser &s); + + void draw(); + void activate(); + static void deactivate(); + + typedef void (*EventHandlerFn)(EventHandler *fn); + void recurse(EventHandlerFn Fn) { + // Loop through each object + _listAltered = false; + for (SynchronisedList<SceneObject *>::iterator i = _objList.begin(); i != _objList.end() && !_listAltered; ) { + SceneObject *o = *i; + ++i; + Fn(o); + } + } + SynchronisedList<SceneObject *>::iterator begin() { return _objList.begin(); } + SynchronisedList<SceneObject *>::iterator end() { return _objList.end(); } + bool contains(SceneObject *sceneObj) { return tSage::contains(_objList, sceneObj); } + void push_back(SceneObject *sceneObj) { _objList.push_back(sceneObj); } + void push_front(SceneObject *sceneObj) { _objList.push_front(sceneObj); } + void remove(SceneObject *sceneObj) { + _objList.remove(sceneObj); + _listAltered = true; + } +}; + +class ScenePriorities : public Common::List<Region> { +public: + int _resNum; + int _field14; + int _field16; + Region _defaultPriorityRegion; +public: + void load(int resNum); + + Region *find(int priority); +}; + +/*--------------------------------------------------------------------------*/ + +class GameSoundHandler { +public: + void proc1() { + warning("TODO: GameSoundHandler::proc1"); + } + void proc5(int v) { + warning("TODO: GameSoundHandler::proc5"); + } + void proc11(int v1, int v2, int v3, int v4) { + warning("TODO: GameSoundHandler::proc11"); + } + int proc12() { + // TODO + return -1; + } + void proc2(int v) { + // TODO + } + int proc3() { + return 0; + } + void setVolume(int volume) { + warning("TODO GameSoundHandler::setVolume"); + } + void startSound(int soundNum) { + warning("TODO GameSoundHandler::startSound"); + } +}; + +class SoundHandler : public EventHandler { +public: + GameSoundHandler _sound; + Action *_action; + int _field280; +public: + SoundHandler(); + ~SoundHandler(); + + void startSound(int soundNum, Action *action = NULL, int volume = 127); + void proc1(Action *action) { + proc11(0, 5, 10, 1, action); + } + void proc2(int v) { + warning("TODO: SoundHandler::proc2"); + } + void proc3() { + warning("TODO: SoundHandler::proc5"); + } + void proc4() { + _sound.proc1(); + } + void proc5(int v) { + _sound.proc5(v); + } + void proc11(int v1, int v2, int v3, int v4, Action *action) { + if (action) + _action = action; + + _sound.proc11(v1, v2, v3, v4); + } + void setVolume(int volume) { _sound.setVolume(volume); } + + virtual Common::String getClassName() { return "SoundHandler"; } + virtual void dispatch(); +}; + +/*--------------------------------------------------------------------------*/ + +class SceneItemList : public SynchronisedList<SceneItem *> { +public: + void addItems(SceneItem *first, ...); +}; + +/*--------------------------------------------------------------------------*/ + +class RegionSupportRec { +public: + int _yp; + int _xp; + int _xDiff; + int _yDiff; + int _xDirection; + int _halfDiff; + int _yDiff2; + + void process(); +}; + +#define PROCESS_LIST_SIZE 100 + +class WalkRegion : public Region { +private: + static RegionSupportRec _processList[PROCESS_LIST_SIZE]; + void loadProcessList(byte *dataP, int dataSize, int &dataIndex, int ®ionHeight); + int process1(int idx, byte *dataP, int dataSize); + void process2(int dataIndex, int x1, int y1, int x2, int y2); + void process3(int yp, int dataCount, int &idx1, int &idx2); + void process4(int yp, int idx1, int idx2, int &count); + void process5(int idx1, int idx2); + void loadRecords(int yp, int size, int processIndex); + void process6(RegionSupportRec &rec); +public: + Common::Point _pt; + int _idxListIndex; + int _idxList2Index; +public: + void loadRegion(byte *dataP, int size); +}; + +class WRField18 { +public: + Common::Point _pt1, _pt2; + int _v; +public: + void load(byte *data); +}; + +class WalkRegions { +public: + int _resNum; + RouteEnds _routeEnds; + Common::Array<WalkRegion> _regionList; + Common::Array<WRField18> _field18; + Common::Array<int> _idxList; + Common::Array<int> _idxList2; +public: + WalkRegions() { _resNum = -1; } + + void clear(); + void load(int sceneNum); + int indexOf(const Common::Point &pt, const Common::List<int> *indexList = NULL); + WalkRegion &operator[](int idx) { + assert((idx >= 1) && (idx <= (int)_regionList.size())); + return _regionList[idx - 1]; + } +}; + +/*--------------------------------------------------------------------------*/ + +class FloatSet { +public: + double _float1, _float2, _float3, _float4; + + FloatSet() { _float1 = _float2 = _float3 = _float4 = 0; } + void add(double v1, double v2, double v3); + void proc1(double v); + double sqrt(FloatSet &floatSet); +}; + +/*--------------------------------------------------------------------------*/ + +class GameHandler : public EventHandler { +public: + RefCounter _lockCtr; + RefCounter _waitCtr; + int _nextWaitCtr; + int _field14; +public: + GameHandler(); + virtual ~GameHandler(); + void execute(); + + virtual void synchronise(Serialiser &s); + virtual Common::String getClassName() { return "GameHandler"; } + virtual void postInit(SceneObjectList *OwnerList = NULL) {} + virtual void dispatch() {} +}; + +class SceneHandler : public GameHandler { +public: + int _saveGameSlot; + int _loadGameSlot; + int _delayTicks; + Common::String _saveName; +public: + SceneHandler(); + void registerHandler(); + + virtual Common::String getClassName() { return "SceneHandler"; } + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void process(Event &event); + virtual void dispatch(); + + static void dispatchObject(EventHandler *obj); + static void saveListener(Serialiser &ser); +}; + +/*--------------------------------------------------------------------------*/ + +class Game { +private: + SynchronisedList<GameHandler *> _handlers; + + static bool notLockedFn(GameHandler *g); + void restart(); + void handleSaveLoad(bool saveFlag, int &saveSlot, Common::String &saveName); +public: + void addHandler(GameHandler *entry) { _handlers.push_back(entry); } + void removeHandler(GameHandler *entry) { _handlers.remove(entry); } + + void execute(); + void restartGame(); + void saveGame(); + void restoreGame(); + void quitGame(); + void endGame(int resNum, int lineNum); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/debugger.cpp b/engines/tsage/debugger.cpp new file mode 100644 index 0000000000..d04fd71461 --- /dev/null +++ b/engines/tsage/debugger.cpp @@ -0,0 +1,172 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/debugger.h" +#include "common/config-manager.h" +#include "common/endian.h" +#include "tsage/globals.h" +#include "tsage/graphics.h" + + +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("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; +} + +/** + * This command loads up the specified new scene number + */ +bool Debugger::Cmd_Scene(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: %s <scene number> [prior scene #]\n", argv[0]); + return true; + } else { + if (argc == 3) + _globals->_sceneManager._sceneNumber = strToInt(argv[2]); + + _globals->_sceneManager.changeScene(strToInt(argv[1])); + return false; + } +} + +/** + * This command draws the walk regions onto the screen + */ +bool Debugger::Cmd_WalkRegions(int argc, const char **argv) { + if (argc != 1) { + DebugPrintf("Usage: %s\n", argv[0]); + return true; + } + + // Colour index to use for the first walk region + int colour = 16; + + // Lock the background surface for access + Graphics::Surface destSurface = _globals->_sceneManager._scene->_backSurface.lockSurface(); + + // Loop through drawing each walk region in a different colour to the background surface + for (uint regionIndex = 0; regionIndex < _globals->_walkRegions._regionList.size(); ++regionIndex, ++colour) { + WalkRegion &wr = _globals->_walkRegions._regionList[regionIndex]; + + for (int yp = wr._bounds.top; yp < wr._bounds.bottom; ++yp) { + LineSliceSet sliceSet = wr.getLineSlices(yp); + + for (uint idx = 0; idx < sliceSet.items.size(); ++idx) + destSurface.hLine(sliceSet.items[idx].xs - _globals->_sceneOffset.x, yp, + sliceSet.items[idx].xe - _globals->_sceneOffset.x, colour); + } + } + + // Release the surface + _globals->_sceneManager._scene->_backSurface.unlockSurface(); + + // Mark the scene as requiring a full redraw + _globals->_paneRefreshFlag[0] = 2; + + return false; +} + +/* + * This command draws the priority regions onto the screen + */ +bool Debugger::Cmd_PriorityRegions(int argc, const char **argv) { + int regionNum = 0; + + // Check for an optional specific region to display + if (argc == 2) + regionNum = strToInt(argv[1]); + + // Colour index to use for the first priority region + int colour = 16; + int count = 0; + + // Lock the background surface for access + Graphics::Surface destSurface = _globals->_sceneManager._scene->_backSurface.lockSurface(); + + Common::List<Region>::iterator i = _globals->_sceneManager._scene->_priorities.begin(); + Common::String regionsDesc; + + for (; i != _globals->_sceneManager._scene->_priorities.end(); ++i, ++colour, ++count) { + Region &r = *i; + + if ((regionNum == 0) || (regionNum == (count + 1))) { + for (int y = 0; y < destSurface.h; ++y) { + byte *destP = (byte *)destSurface.getBasePtr(0, y); + + for (int x = 0; x < destSurface.w; ++x) { + if (r.contains(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + x, + _globals->_sceneManager._scene->_sceneBounds.top + y))) + *destP = colour; + ++destP; + } + } + } + + regionsDesc += Common::String::format("Region Priority = %d bounds=%d,%d,%d,%d\n", + r._regionId, r._bounds.left, r._bounds.top, r._bounds.right, r._bounds.bottom); + } + + // Release the surface + _globals->_sceneManager._scene->_backSurface.unlockSurface(); + + // Mark the scene as requiring a full redraw + _globals->_paneRefreshFlag[0] = 2; + + DebugPrintf("Total regions = %d\n", count); + DebugPrintf("%s", regionsDesc.c_str()); + + return true; +} + +/** + * Give a specified item to the player + */ +bool Debugger::Cmd_Item(int argc, const char **argv) { + _globals->_inventory._infoDisk._sceneNumber = 1; + return true; +} + +} // End of namespace tSage diff --git a/engines/tsage/debugger.h b/engines/tsage/debugger.h new file mode 100644 index 0000000000..c94d77b2ab --- /dev/null +++ b/engines/tsage/debugger.h @@ -0,0 +1,48 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_DEBUGGER_H +#define TSAGE_DEBUGGER_H + +#include "common/scummsys.h" +#include "gui/debugger.h" + +namespace tSage { + +class Debugger : public GUI::Debugger { +public: + Debugger(); + virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ + +protected: + bool Cmd_Scene(int argc, const char **argv); + bool Cmd_WalkRegions(int argc, const char **argv); + bool Cmd_PriorityRegions(int argc, const char **argv); + bool Cmd_Item(int argc, const char **argv); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp new file mode 100644 index 0000000000..371166d782 --- /dev/null +++ b/engines/tsage/detection.cpp @@ -0,0 +1,186 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "common/system.h" +#include "common/savefile.h" + +#include "engines/advancedDetector.h" + +#include "base/plugins.h" + +#include "tsage/tsage.h" + +namespace tSage { + +struct tSageGameDescription { + ADGameDescription desc; + + int gameID; + uint32 features; +}; + +const char *TSageEngine::getGameId() const { + return _gameDescription->desc.gameid; +} + +uint32 TSageEngine::getGameID() const { + return _gameDescription->gameID; +} + +uint32 TSageEngine::getFeatures() const { + return _gameDescription->features; +} + +} // End of namespace tSage + +static const PlainGameDescriptor tSageGameTitles[] = { + { "tsage", "Unknown Tsunami TSAGE-based Game" }, + { "ring", "Ringworld: Revenge of the Patriarch" }, + { "blueforce", "Blue Force" }, + { 0, 0 } +}; + +#include "engines/tsage/detection_tables.h" + +static const ADParams detectionParams = { + (const byte *)tSage::gameDescriptions, + sizeof(tSage::tSageGameDescription), + 0, + tSageGameTitles, + 0, + "tsage", + NULL, + 0, + Common::GUIO_NONE, + 0, + NULL +}; + +#define MAX_SAVES 100 + +class TSageMetaEngine : public AdvancedMetaEngine { +public: + TSageMetaEngine() : AdvancedMetaEngine(detectionParams) { + } + + virtual const char *getName() const { + return "TsAGE Engine"; + } + + virtual const char *getOriginalCopyright() const { + return "(c) Tsunami Media"; + } + + virtual bool hasFeature(MetaEngineFeature f) const { + switch (f) { + case kSupportsListSaves: + case kSupportsDeleteSave: + case kSupportsLoadingDuringStartup: + case kSavesSupportMetaInfo: + case kSavesSupportThumbnail: + case kSavesSupportCreationDate: + case kSavesSupportPlayTime: + return true; + default: + return false; + } + } + + virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + if (desc) { + *engine = new tSage::TSageEngine(syst, (const tSage::tSageGameDescription *)desc); + } + return desc != 0; + } + + static Common::String generateGameStateFileName(const char *target, int slot) { + return Common::String::format("%s.%03d", target, slot); + } + + virtual SaveStateList listSaves(const char *target) const { + Common::String pattern = target; + pattern += ".*"; + + Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles(pattern); + tSage::tSageSavegameHeader header; + + SaveStateList saveList; + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) { + int slot; + const char *ext = strrchr(file->c_str(), '.'); + if (ext && (slot = atoi(ext + 1)) >= 0 && slot < MAX_SAVES) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file); + + if (in) { + if (tSage::Saver::readSavegameHeader(in, header)) { + saveList.push_back(SaveStateDescriptor(slot, header.saveName)); + delete header.thumbnail; + } + + delete in; + } + } + } + + return saveList; + } + + virtual int getMaximumSaveSlot() const { + return MAX_SAVES - 1; + } + + virtual void removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); + } + + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const { + Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading( + generateGameStateFileName(target, slot)); + assert(f); + + tSage::tSageSavegameHeader header; + tSage::Saver::readSavegameHeader(f, header); + delete f; + + // Create the return descriptor + SaveStateDescriptor desc(slot, header.saveName); + desc.setDeletableFlag(true); + desc.setWriteProtectedFlag(false); + desc.setThumbnail(header.thumbnail); + desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay); + desc.setSaveTime(header.saveHour, header.saveMinutes); + desc.setPlayTime(header.totalFrames * GAME_FRAME_TIME); + + return desc; + } +}; + +#if PLUGIN_ENABLED_DYNAMIC(TSAGE) +REGISTER_PLUGIN_DYNAMIC(TSAGE, PLUGIN_TYPE_ENGINE, TSageMetaEngine); +#else +REGISTER_PLUGIN_STATIC(TSAGE, PLUGIN_TYPE_ENGINE, TSageMetaEngine); +#endif diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h new file mode 100644 index 0000000000..f932c62367 --- /dev/null +++ b/engines/tsage/detection_tables.h @@ -0,0 +1,91 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +namespace tSage { + +static const tSageGameDescription gameDescriptions[] = { + + // Ringworld English CD version + { + { + "ring", + "CD", + AD_ENTRY1s("ring.rlb", "466f0e6492d9d0f34d35c5cd088de90f", 37847618), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_Ringworld, + GF_CD + }, + // Ringworld First Wave English CD version + { + { + "ring", + "CD", + AD_ENTRY1s("ring.rlb", "0a25b4ee58d44a54425c0b47e5096bbc", 37847618), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_Ringworld, + GF_CD + }, + // Ringworld English Floppy version + { + { + "ring", + "Floppy", + AD_ENTRY1s("ring.rlb", "61f78f68a56832ae95fe06748c403234", 8438770), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_Ringworld, + GF_FLOPPY + }, + + // Blue Force + { + { + "blueforce", + "", + AD_ENTRY1s("blue.rlb", "467da43c848cc0e800b547c59d84ccb1", 10032614), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_BlueForce, + GF_FLOPPY + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace tSage diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp new file mode 100644 index 0000000000..b76d60ac48 --- /dev/null +++ b/engines/tsage/dialogs.cpp @@ -0,0 +1,598 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/translation.h" +#include "tsage/tsage.h" +#include "tsage/core.h" +#include "tsage/dialogs.h" +#include "tsage/graphics.h" +#include "tsage/core.h" +#include "tsage/staticres.h" +#include "tsage/globals.h" + +namespace tSage { + +/*--------------------------------------------------------------------------*/ + +/** + * This dialog class provides a simple message display with support for either one or two buttons. + */ +MessageDialog::MessageDialog(const Common::String &message, const Common::String &btn1Message, + const Common::String &btn2Message) : GfxDialog() { + // Set up the message + addElements(&_msg, &_btn1, NULL); + + _msg.set(message, 200, ALIGN_LEFT); + _btn1._bounds.moveTo(_msg._bounds.left, _msg._bounds.bottom + 2); + _defaultButton = &_btn1; + + // Set up the first button + _btn1.setText(btn1Message); + _btn1._bounds.moveTo(_msg._bounds.right - _btn1._bounds.width(), _msg._bounds.bottom); + + if (!btn2Message.empty()) { + // Set up the second button + _defaultButton = &_btn2; + add(&_btn2); + _btn2.setText(btn2Message); + _btn2._bounds.moveTo(_msg._bounds.right - _btn2._bounds.width(), _msg._bounds.bottom); + _btn1._bounds.translate(-(_btn2._bounds.width() + 4), 0); + } + + // Do post setup for the dialog + setDefaults(); + + // Set the dialog's centre + setCentre(_globals->_dialogCentre.x, _globals->_dialogCentre.y); +} + +int MessageDialog::show(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message) { + // Ensure that the cursor is the arrow + CursorType currentCursor = _globals->_events.getCursor(); + if (currentCursor != CURSOR_ARROW) + _globals->_events.setCursor(CURSOR_ARROW); + _globals->_events.showCursor(); + + int result = show2(message, btn1Message, btn2Message); + + // If the cursor was changed, change it back + if (currentCursor != CURSOR_ARROW) + _globals->_events.setCursor(currentCursor); + + return result; +} + +int MessageDialog::show2(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message) { + MessageDialog *dlg = new MessageDialog(message, btn1Message, btn2Message); + dlg->draw(); + + GfxButton *selectedButton = dlg->execute(); + int result = (selectedButton == &dlg->_btn1) ? 0 : 1; + + delete dlg; + return result; +} + + +/*--------------------------------------------------------------------------*/ + +ConfigDialog::ConfigDialog() : GUI::OptionsDialog("", "GlobalConfig") { + // + // Sound controllers + // + + addVolumeControls(this, "GlobalConfig."); + setVolumeSettingsState(true); // could disable controls by GUI options + + // + // Add the buttons + // + + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd); +} + +/*--------------------------------------------------------------------------*/ + +#define BUTTON_WIDTH 28 +#define BUTTON_HEIGHT 29 + +RightClickButton::RightClickButton(int buttonIndex, int xp, int yp) : GfxButton() { + _buttonIndex = buttonIndex; + this->_bounds.left = xp; + this->_bounds.top = yp; + this->_bounds.setWidth(BUTTON_WIDTH); + this->_bounds.setHeight(BUTTON_HEIGHT); + _savedButton = NULL; +} + +void RightClickButton::highlight() { + if (_savedButton) { + // Button was previously highlighted, so de-highlight by restoring saved area + _globals->gfxManager().copyFrom(*_savedButton, _bounds.left, _bounds.top); + delete _savedButton; + _savedButton = NULL; + } else { + // Highlight button by getting the needed highlighted image resource + _savedButton = Surface_getArea(_globals->gfxManager().getSurface(), _bounds); + + uint size; + byte *imgData = _vm->_dataManager->getSubResource(7, 2, _buttonIndex, &size); + + GfxSurface btnSelected = surfaceFromRes(imgData); + _globals->gfxManager().copyFrom(btnSelected, _bounds.left, _bounds.top); + + DEALLOCATE(imgData); + } +} + +/*--------------------------------------------------------------------------*/ + +/** + * This dialog implements the right-click dialog + */ +RightClickDialog::RightClickDialog() : GfxDialog(), + _walkButton(1, 48, 12), _lookButton(2, 31, 29), _useButton(3, 65, 29), + _talkButton(4, 14, 47), _inventoryButton(5, 48, 47), _optionsButton(6, 83, 47) { + Rect rectArea, dialogRect; + + // Set the palette and change the cursor + _gfxManager.setDialogPalette(); + _globals->_events.setCursor(CURSOR_ARROW); + + // Get the dialog image + _surface = surfaceFromRes(7, 1, 1); + + // Set the dialog position + dialogRect.resize(_surface, 0, 0, 100); + dialogRect.centre(_globals->_events._mousePos.x, _globals->_events._mousePos.y); + + // Ensure the dialog will be entirely on-screen + Rect screenRect = _globals->gfxManager()._bounds; + screenRect.collapse(4, 4); + dialogRect.contain(screenRect); + + _bounds = dialogRect; + _gfxManager._bounds = _bounds; + + _highlightedButton = NULL; + _selectedAction = -1; +} + +RightClickDialog::~RightClickDialog() { +} + +RightClickButton *RightClickDialog::findButton(const Common::Point &pt) { + RightClickButton *btnList[] = { &_walkButton, &_lookButton, &_useButton, &_talkButton, &_inventoryButton, &_optionsButton }; + + for (int i = 0; i < 6; ++i) { + btnList[i]->_owner = this; + + if (btnList[i]->_bounds.contains(pt)) + return btnList[i]; + } + + return NULL; +} + +void RightClickDialog::draw() { + // Save the covered background area + _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds); + + // Draw the dialog image + _globals->gfxManager().copyFrom(_surface, _bounds.left, _bounds.top); +} + +bool RightClickDialog::process(Event &event) { + switch (event.eventType) { + case EVENT_MOUSE_MOVE: { + // Check whether a button is highlighted + RightClickButton *btn = findButton(event.mousePos); + + if (btn != _highlightedButton) { + // De-highlight any previously selected button + if (_highlightedButton) { + _highlightedButton->highlight(); + _highlightedButton = NULL; + } + if (btn) { + // Highlight the new button + btn->highlight(); + _highlightedButton = btn; + } + } + event.handled = true; + return true; + } + + case EVENT_BUTTON_DOWN: + // If a button is highlighted, then flag the selected button index + if (_highlightedButton) + _selectedAction = _highlightedButton->_buttonIndex; + else + _selectedAction = _lookButton._buttonIndex; + event.handled = true; + return true; + + default: + break; + } + + return false; +} + +void RightClickDialog::execute() { + // Draw the dialog + draw(); + + // Dialog event handler loop + _gfxManager.activate(); + + while (!_vm->getEventManager()->shouldQuit() && (_selectedAction == -1)) { + Event evt; + while (_globals->_events.getEvent(evt, EVENT_MOUSE_MOVE | EVENT_BUTTON_DOWN)) { + evt.mousePos.x -= _bounds.left; + evt.mousePos.y -= _bounds.top; + + process(evt); + } + + g_system->delayMillis(10); + g_system->updateScreen(); + } + + // Execute the specified action + switch (_selectedAction) { + case 1: + // Look action + _globals->_events.setCursor(CURSOR_LOOK); + break; + case 2: + // Walk action + _globals->_events.setCursor(CURSOR_WALK); + break; + case 3: + // Use cursor + _globals->_events.setCursor(CURSOR_USE); + break; + case 4: + // Talk cursor + _globals->_events.setCursor(CURSOR_TALK); + break; + case 5: + // Inventory dialog + InventoryDialog::show(); + break; + case 6: + // Dialog options + OptionsDialog::show(); + break; + } + + _gfxManager.deactivate(); +} + +/*--------------------------------------------------------------------------*/ + +void ModalDialog::draw() { + // Set the palette for use in the dialog + setPalette(); + + // Make a backup copy of the area the dialog will occupy + Rect tempRect = _bounds; + tempRect.collapse(-10, -10); + _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), tempRect); + + _gfxManager.activate(); + + // Fill in the contents of the entire dialog + _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + drawFrame(); + + // Draw each element in the dialog in order + GfxElementList::iterator i; + for (i = _elements.begin(); i != _elements.end(); ++i) { + (*i)->draw(); + } + + _gfxManager.deactivate(); +} + +void ModalDialog::drawFrame() { + Rect origRect = _bounds; + _bounds.collapse(-10, -10); + + // Fill the dialog area + _globals->gfxManager().fillRect(origRect, 54); + + // Draw top line + GfxSurface surface = surfaceFromRes(8, 1, 7); + for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) + surface.draw(Common::Point(xp, _bounds.top)); + surface.draw(Common::Point(_bounds.right - 20, _bounds.top)); + + surface = surfaceFromRes(8, 1, 1); + surface.draw(Common::Point(_bounds.left, _bounds.top)); + + surface = surfaceFromRes(8, 1, 4); + surface.draw(Common::Point(_bounds.right - 10, _bounds.top)); + + // Draw vertical edges + surface = surfaceFromRes(8, 1, 2); + for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) + surface.draw(Common::Point(_bounds.left, yp)); + surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20)); + + surface = surfaceFromRes(8, 1, 5); + for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10) + surface.draw(Common::Point(_bounds.right - 10, yp)); + surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20)); + + // Draw bottom line + surface = surfaceFromRes(8, 1, 8); + for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10) + surface.draw(Common::Point(xp, _bounds.bottom - 10)); + surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10)); + + surface = surfaceFromRes(8, 1, 3); + surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10)); + + surface = surfaceFromRes(8, 1, 6); + surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10)); + + // Set the dialog's manager bounds + _gfxManager._bounds = origRect; +} + +/*--------------------------------------------------------------------------*/ + +bool GfxInvImage::process(Event &event) { + if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) { + event.handled = _bounds.contains(event.mousePos); + return event.handled; + } + + return false; +} + +/*--------------------------------------------------------------------------*/ + +void InventoryDialog::show(bool allFlag) { + if (!allFlag) { + // Determine how many items are in the player's inventory + int itemCount = 0; + SynchronisedList<InvObject *>::iterator i; + for (i = _globals->_inventory._itemList.begin(); i != _globals->_inventory._itemList.end(); ++i) { + if ((*i)->inInventory()) + ++itemCount; + } + + if (itemCount == 0) { + MessageDialog::show(INV_EMPTY_MSG, OK_BTN_STRING); + return; + } + } + + InventoryDialog *dlg = new InventoryDialog(allFlag); + dlg->draw(); + dlg->execute(); + delete dlg; +} + +InventoryDialog::InventoryDialog(bool allFlag) { + // Determine the maximum size of the image of any item in the player's inventory + int imgWidth = 0, imgHeight = 0; + + SynchronisedList<InvObject *>::iterator i; + for (i = _globals->_inventory._itemList.begin(); i != _globals->_inventory._itemList.end(); ++i) { + InvObject *invObject = *i; + if (allFlag || invObject->inInventory()) { + // Get the image for the item + GfxSurface itemSurface = surfaceFromRes(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum); + + // Maintain the dimensions of the largest item image + imgWidth = MAX(imgWidth, (int)itemSurface.getBounds().width()); + imgHeight = MAX(imgHeight, (int)itemSurface.getBounds().height()); + + // Add the item to the display list + _images.push_back(GfxInvImage()); + _images[_images.size() - 1].setDetails(invObject->_displayResNum, invObject->_rlbNum, invObject->_cursorNum); + _images[_images.size() - 1]._invObject = invObject; + add(&_images[_images.size() - 1]); + } + } + assert(_images.size() > 0); + + // Figure out the number of columns/rows to show all the items + int cellsSize = 3; + while ((cellsSize * cellsSize) < (int)_images.size()) + ++cellsSize; + + // Set the position of each inventory item to be displayed + int cellX = 0; + Common::Point pt(0, 0); + + for (uint idx = 0; idx < _images.size(); ++idx) { + if (cellX == cellsSize) { + // Move to the start of the next line + pt.x = 0; + pt.y += imgHeight + 2; + cellX = 0; + } + + _images[idx]._bounds.moveTo(pt.x, pt.y); + + pt.x += imgWidth + 2; + ++cellX; + } + + // Set up the buttons + pt.y += imgHeight + 2; + _btnOk.setText(OK_BTN_STRING); + _btnOk._bounds.moveTo((imgWidth + 2) * cellsSize - _btnOk._bounds.width(), pt.y); + _btnLook.setText(LOOK_BTN_STRING); + _btnLook._bounds.moveTo(_btnOk._bounds.left - _btnLook._bounds.width() - 2, _btnOk._bounds.top); + addElements(&_btnLook, &_btnOk, NULL); + + frame(); + setCentre(SCREEN_CENTRE_X, SCREEN_CENTRE_Y); +} + +void InventoryDialog::execute() { + if ((_globals->_inventory._selectedItem) && _globals->_inventory._selectedItem->inInventory()) + _globals->_inventory._selectedItem->setCursor(); + + GfxElement *hiliteObj; + bool lookFlag = false; + + while (!_vm->getEventManager()->shouldQuit()) { + // Get events + Event event; + while (!_globals->_events.getEvent(event) && !_vm->getEventManager()->shouldQuit()) + ; + if (_vm->getEventManager()->shouldQuit()) + return; + + hiliteObj = NULL; + if ((event.eventType == EVENT_BUTTON_DOWN) && !_bounds.contains(event.mousePos)) + break; + + // Pass event to elements + event.mousePos.x -= _gfxManager._bounds.left; + event.mousePos.y -= _gfxManager._bounds.top; + + for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) { + if ((*i)->process(event)) + hiliteObj = *i; + } + + if (!event.handled && event.eventType == EVENT_KEYPRESS) { + if ((event.kbd.keycode == Common::KEYCODE_RETURN) || (event.kbd.keycode == Common::KEYCODE_ESCAPE)) { + // Exit the dialog + hiliteObj = &_btnOk; + break; + } + } + + if (hiliteObj == &_btnOk) { + // Ok button clicked + if (lookFlag) + _globals->_events.setCursor(CURSOR_WALK); + break; + } else if (hiliteObj == &_btnLook) { + // Look button clicked + if (_btnLook._message == LOOK_BTN_STRING) { + _btnLook._message = PICK_BTN_STRING; + lookFlag = 1; + _globals->_events.setCursor(CURSOR_LOOK); + } else { + _btnLook._message = LOOK_BTN_STRING; + lookFlag = 0; + _globals->_events.setCursor(CURSOR_WALK); + } + + _gfxManager.activate(); + hiliteObj->draw(); + _gfxManager.deactivate(); + } else if (hiliteObj) { + // Inventory item selected + InvObject *invObject = static_cast<GfxInvImage *>(hiliteObj)->_invObject; + if (lookFlag) { + _globals->_screenSurface.displayText(invObject->_description); + } else { + _globals->_inventory._selectedItem = invObject; + invObject->setCursor(); + } + } + } +} + +/*--------------------------------------------------------------------------*/ + +void OptionsDialog::show() { + OptionsDialog *dlg = new OptionsDialog(); + dlg->draw(); + + GfxButton *btn = dlg->execute(); + + if (btn == &dlg->_btnQuit) { + // Quit game + if (MessageDialog::show(QUIT_CONFIRM_MSG, CANCEL_BTN_STRING, QUIT_BTN_STRING) == 1) { + _vm->quitGame(); + } + } else if (btn == &dlg->_btnRestart) { + // Restart game + _globals->_game.restartGame(); + } else if (btn == &dlg->_btnSound) { + // Sound dialog + } else if (btn == &dlg->_btnSave) { + // Save button + _globals->_game.saveGame(); + } else if (btn == &dlg->_btnRestore) { + // Restore button + _globals->_game.restoreGame(); + } + + dlg->remove(); + delete dlg; +} + +OptionsDialog::OptionsDialog() { + // Set the element text + _gfxMessage.set(OPTIONS_MSG, 140, ALIGN_LEFT); + _btnRestore.setText(RESTORE_BTN_STRING); + _btnSave.setText(SAVE_BTN_STRING); + _btnRestart.setText(RESTART_BTN_STRING); + _btnQuit.setText(QUIT_BTN_STRING); + _btnSound.setText(SOUND_BTN_STRING); + _btnResume.setText(RESUME_BTN_STRING); + + // Set position of the elements + _gfxMessage._bounds.moveTo(0, 1); + _btnRestore._bounds.moveTo(0, _gfxMessage._bounds.bottom + 1); + _btnSave._bounds.moveTo(0, _btnRestore._bounds.bottom + 1); + _btnRestart._bounds.moveTo(0, _btnSave._bounds.bottom + 1); + _btnQuit._bounds.moveTo(0, _btnRestart._bounds.bottom + 1); + _btnSound._bounds.moveTo(0, _btnQuit._bounds.bottom + 1); + _btnResume._bounds.moveTo(0, _btnSound._bounds.bottom + 1); + + // Set all the buttons to the widest button + GfxButton *btnList[6] = {&_btnRestore, &_btnSave, &_btnRestart, &_btnQuit, &_btnSound, &_btnResume}; + int16 btnWidth = 0; + for (int idx = 0; idx < 6; ++idx) + btnWidth = MAX(btnWidth, btnList[idx]->_bounds.width()); + for (int idx = 0; idx < 6; ++idx) + btnList[idx]->_bounds.setWidth(btnWidth); + + // Add the items to the dialog + addElements(&_gfxMessage, &_btnRestore, &_btnSave, &_btnRestart, &_btnQuit, &_btnSound, &_btnResume, NULL); + + // Set the dialog size and position + frame(); + setCentre(160, 100); +} + + +} // End of namespace tSage diff --git a/engines/tsage/dialogs.h b/engines/tsage/dialogs.h new file mode 100644 index 0000000000..8e766372b4 --- /dev/null +++ b/engines/tsage/dialogs.h @@ -0,0 +1,136 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_DIALOGS_H +#define TSAGE_DIALOGS_H + +#include "gui/options.h" +#include "tsage/events.h" +#include "tsage/graphics.h" +#include "common/list.h" +#include "common/rect.h" +#include "common/system.h" + +namespace tSage { + +class MessageDialog : public GfxDialog { +public: + GfxButton _btn1, _btn2; + GfxDialog _dialog; + GfxMessage _msg; +public: + MessageDialog(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String()); + + static int show(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String()); + static int show2(const Common::String &message, const Common::String &btn1Message, const Common::String &btn2Message = Common::String()); +}; + +class ConfigDialog : public GUI::OptionsDialog { +public: + ConfigDialog(); +}; + +class RightClickButton : public GfxButton { +private: + GfxSurface *_savedButton; +public: + int _buttonIndex; + + RightClickButton(int buttonIndex, int xp, int yp); + ~RightClickButton() { delete _savedButton; } + + virtual void highlight(); +}; + +class RightClickDialog : public GfxDialog { +private: + GfxSurface _surface; + RightClickButton *_highlightedButton; + int _selectedAction; + RightClickButton _walkButton, _lookButton, _useButton, _talkButton, _inventoryButton, _optionsButton; + + RightClickButton *findButton(const Common::Point &pt); +public: + RightClickDialog(); + ~RightClickDialog(); + + virtual void draw(); + virtual bool process(Event &event); + void execute(); +}; + +/*--------------------------------------------------------------------------*/ + +class ModalDialog : public GfxDialog { +protected: + void drawFrame(); +public: + virtual void draw(); +}; + +/*--------------------------------------------------------------------------*/ + +class GfxInvImage : public GfxImage { +public: + InvObject *_invObject; +public: + GfxInvImage() : GfxImage(), _invObject(NULL) {} + + virtual bool process(Event &event); +}; + +#define MAX_INVOBJECT_DISPLAY 20 + +class InventoryDialog : public ModalDialog { +private: + Common::Array<GfxInvImage> _images; + GfxButton _btnOk, _btnLook; +public: + InventoryDialog(bool allFlag = false); + virtual ~InventoryDialog() {} + void execute(); + + static void show(bool allFlag = false); +}; + +/*--------------------------------------------------------------------------*/ + +class OptionsDialog : public ModalDialog { +private: + GfxButton _btnSave, _btnRestore, _btnRestart; + GfxButton _btnQuit, _btnResume; + GfxButton _btnSound; + GfxMessage _gfxMessage; +public: + OptionsDialog(); + virtual ~OptionsDialog() {} + GfxButton *execute() { return GfxDialog::execute(&_btnResume); } + + static void show(); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp new file mode 100644 index 0000000000..4d2a1cce8c --- /dev/null +++ b/engines/tsage/events.cpp @@ -0,0 +1,247 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/events.h" +#include "common/singleton.h" +#include "graphics/cursorman.h" +#include "common/system.h" + +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/staticres.h" +#include "tsage/tsage.h" +#include "tsage/globals.h" + +namespace tSage { + +EventsClass::EventsClass() { + _currentCursor = CURSOR_NONE; + _frameNumber = 0; + _priorFrameTime = 0; + _prevDelayFrame = 0; + _saver->addListener(this); +} + +bool EventsClass::pollEvent() { + uint32 milli = g_system->getMillis(); + if ((milli - _priorFrameTime) >= GAME_FRAME_TIME) { + _priorFrameTime = milli; + ++_frameNumber; + + g_system->updateScreen(); + } + + if (!g_system->getEventManager()->pollEvent(_event)) return false; + + // Handle keypress + switch (_event.type) { + case Common::EVENT_QUIT: + case Common::EVENT_RTL: + break; + + case Common::EVENT_MOUSEMOVE: + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_RBUTTONUP: + // Keep a copy of the current mouse position + _mousePos = _event.mouse; + break; + + default: + break; + } + + return true; +} + +void EventsClass::waitForPress(int eventMask) { + Event evt; + while (!_vm->getEventManager()->shouldQuit() && !getEvent(evt, eventMask)) + g_system->delayMillis(10); +} + +/** + * Standard event retrieval, which only returns keyboard and mouse clicks + */ +bool EventsClass::getEvent(Event &evt, int eventMask) { + while (pollEvent() && !_vm->getEventManager()->shouldQuit()) { + evt.handled = false; + evt.eventType = EVENT_NONE; + evt.mousePos = _event.mouse; + evt.kbd = _event.kbd; + + switch (_event.type) { + case Common::EVENT_MOUSEMOVE: + evt.eventType = EVENT_MOUSE_MOVE; + break; + case Common::EVENT_LBUTTONDOWN: + evt.eventType = EVENT_BUTTON_DOWN; + evt.btnState = BTNSHIFT_LEFT; + break; + case Common::EVENT_RBUTTONDOWN: + evt.eventType = EVENT_BUTTON_DOWN; + evt.btnState = BTNSHIFT_RIGHT; + break; + case Common::EVENT_MBUTTONDOWN: + evt.eventType = EVENT_BUTTON_DOWN; + evt.btnState = BTNSHIFT_MIDDLE; + break; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + case Common::EVENT_MBUTTONUP: + evt.eventType = EVENT_BUTTON_UP; + evt.btnState = 0; + break; + case Common::EVENT_KEYDOWN: + evt.eventType = EVENT_KEYPRESS; + evt.kbd = _event.kbd; + break; + default: + break; + } + + if (evt.eventType & eventMask) + return true; + } + + return false; +} + +/** + * Sets the specified cursor + * + * @cursorType Specified cursor number + */ +void EventsClass::setCursor(CursorType cursorType) { + _globals->clearFlag(122); + + if ((_currentCursor == cursorType) && CursorMan.isVisible()) + return; + + if (cursorType == CURSOR_NONE) { + if (CursorMan.isVisible()) + CursorMan.showMouse(false); + return; + } + + CursorMan.showMouse(true); + + const byte *cursor; + bool delFlag = true; + uint size; + + switch (cursorType) { + case CURSOR_CROSSHAIRS: + // Crosshairs cursor + cursor = _vm->_dataManager->getSubResource(4, 1, 6, &size); + _globals->setFlag(122); + break; + + case CURSOR_LOOK: + // Look cursor + cursor = _vm->_dataManager->getSubResource(4, 1, 5, &size); + _currentCursor = CURSOR_LOOK; + break; + + case CURSOR_USE: + // Use cursor + cursor = _vm->_dataManager->getSubResource(4, 1, 4, &size); + _currentCursor = CURSOR_USE; + break; + + case CURSOR_TALK: + // Talk cursor + cursor = _vm->_dataManager->getSubResource(4, 1, 3, &size); + _currentCursor = CURSOR_TALK; + break; + + case CURSOR_ARROW: + // Arrow cursor + cursor = CURSOR_ARROW_DATA; + delFlag = false; + break; + + case CURSOR_WALK: + default: + // Walk cursor + cursor = CURSOR_WALK_DATA; + _currentCursor = CURSOR_WALK; + delFlag = false; + break; + } + + // Decode the cursor + GfxSurface s = surfaceFromRes(cursor); + + Graphics::Surface surface = s.lockSurface(); + const byte *cursorData = (const byte *)surface.getBasePtr(0, 0); + CursorMan.replaceCursor(cursorData, surface.w, surface.h, s._centroid.x, s._centroid.y, s._transColour); + s.unlockSurface(); + + if (delFlag) + DEALLOCATE(cursor); +} + +void EventsClass::setCursor(Graphics::Surface &cursor, int transColour, const Common::Point &hotspot, CursorType cursorId) { + const byte *cursorData = (const byte *)cursor.getBasePtr(0, 0); + CursorMan.replaceCursor(cursorData, cursor.w, cursor.h, hotspot.x, hotspot.y, transColour); + + _currentCursor = cursorId; +} + +void EventsClass::setCursorFromFlag() { + setCursor(_globals->getFlag(122) ? CURSOR_CROSSHAIRS : _currentCursor); +} + +void EventsClass::showCursor() { + CursorMan.showMouse(true); +} + +void EventsClass::hideCursor() { + CursorMan.showMouse(false); +} + +/** + * Delays the game for the specified number of frames, if necessary, from the + * previous time the delay method was called + */ +void EventsClass::delay(int numFrames) { + while (_frameNumber < (_prevDelayFrame + numFrames)) { + uint32 delayAmount = CLIP(_priorFrameTime + GAME_FRAME_TIME - g_system->getMillis(), + (uint32)0, (uint32)GAME_FRAME_TIME); + if (delayAmount > 0) + g_system->delayMillis(delayAmount); + + ++_frameNumber; + _priorFrameTime = g_system->getMillis(); + } + + g_system->updateScreen(); + _prevDelayFrame = _frameNumber; + _priorFrameTime = g_system->getMillis(); +} + +} // end of namespace tSage diff --git a/engines/tsage/events.h b/engines/tsage/events.h new file mode 100644 index 0000000000..202ac9ccd2 --- /dev/null +++ b/engines/tsage/events.h @@ -0,0 +1,109 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_EVENTS_H +#define TSAGE_EVENTS_H + +#include "common/events.h" +#include "common/array.h" +#include "common/str.h" +#include "graphics/surface.h" +#include "tsage/saveload.h" + +namespace tSage { + +enum EventType {EVENT_NONE = 0, EVENT_BUTTON_DOWN = 1, EVENT_BUTTON_UP = 2, EVENT_KEYPRESS = 4, + EVENT_MOUSE_MOVE = 8}; + +enum ButtonShiftFlags {BTNSHIFT_LEFT = 0, BTNSHIFT_RIGHT = 3, BTNSHIFT_MIDDLE = 4}; + +// Intrinisc game delay between execution frames. This runs at 60Hz +#define GAME_FRAME_TIME (1000 / 60) + +class GfxManager; + +class Event { +public: + EventType eventType; + Common::Point mousePos; + int btnState; + Common::KeyState kbd; + int ctr; + GfxManager *gfxMan; + bool handled; +}; + +enum CursorType { + OBJECT_STUNNER = 0, OBJECT_SCANNER = 1, OBJECT_STASIS_BOX = 2, + OBJECT_INFODISK = 3, OBJECT_STASIS_NEGATOR = 4, OBJECT_KEY_DEVICE = 5, OBJECT_MEDKIT = 6, + OBJECT_LADDER = 7, OBJECT_ROPE = 8, OBJECT_KEY = 9, OBJECT_TRANSLATOR = 10, OBJECT_ALE = 11, + OBJECT_PAPER = 12, OBJECT_WALDOS = 13, OBJECT_STASIS_BOX2 = 14, OBJECT_RING = 15, + OBJECT_CLOAK = 16, OBJECT_TUNIC = 17, OBJECT_CANDLE = 18, OBJECT_STRAW = 19, OBJECT_SCIMITAR = 20, + OBJECT_SWORD = 21, OBJECT_HELMET = 22, OBJECT_ITEMS = 23, OBJECT_CONCENTRATOR = 24, + OBJECT_NULLIFIER = 25, OBJECT_PEG = 26, OBJECT_VIAL = 27, OBJECT_JACKET = 28, + OBJECT_TUNIC2 = 29, OBJECT_BONE = 30, OBJECT_EMPTY_JAR = 31, OBJECT_JAR = 32, + + CURSOR_WALK = 0x100, CURSOR_LOOK = 0x200, CURSOR_700 = 700, CURSOR_USE = 0x400, CURSOR_TALK = 0x800, + CURSOR_NONE = -1, CURSOR_CROSSHAIRS = -2, CURSOR_ARROW = -3 +}; + +class EventsClass : public SaveListener { +private: + Common::Event _event; + uint32 _frameNumber; + uint32 _prevDelayFrame; + uint32 _priorFrameTime; +public: + EventsClass(); + + Common::Point _mousePos; + CursorType _currentCursor; + + void setCursor(CursorType cursorType); + void setCursor(Graphics::Surface &cursor, int transColour, const Common::Point &hotspot, CursorType cursorId); + void setCursorFromFlag(); + CursorType getCursor() const { return _currentCursor; } + void showCursor(); + void hideCursor(); + + bool pollEvent(); + void waitForPress(int eventMask = EVENT_BUTTON_DOWN | EVENT_KEYPRESS); + + bool getEvent(Event &evt, int eventMask = ~EVENT_MOUSE_MOVE); + Common::Event event() { return _event; } + Common::EventType type() { return _event.type; } + uint32 getFrameNumber() const { return _frameNumber; } + void delay(int numFrames); + + virtual void listenerSynchronise(Serialiser &s) { + s.syncAsUint32LE(_frameNumber); + s.syncAsUint32LE(_prevDelayFrame); + // TODO: Synchronise unknown stuff + } +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp new file mode 100644 index 0000000000..b9abb9d751 --- /dev/null +++ b/engines/tsage/globals.cpp @@ -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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/globals.h" + +namespace tSage { + +Globals *_globals = NULL; + +/*--------------------------------------------------------------------------*/ + +/** + * Instantiates a saved object that can be instantiated + */ +static SavedObject *classFactoryProc(const Common::String &className) { + if (className == "ObjectMover") return new ObjectMover(); + if (className == "NpcMover") return new NpcMover(); + if (className == "ObjectMover2") return new ObjectMover2(); + if (className == "ObjectMover3") return new ObjectMover3(); + if (className == "PlayerMover") return new PlayerMover(); + + return NULL; +} + +/*--------------------------------------------------------------------------*/ + +Globals::Globals() : + _dialogCentre(160, 140), + _gfxManagerInstance(_screenSurface) { + reset(); + _stripNum = 0; + _gfxFontNumber = 50; + _gfxColours.background = 53; + _gfxColours.foreground = 18; + _fontColours.background = 51; + _fontColours.foreground = 54; + + _screenSurface.setScreenSurface(); + _gfxManagers.push_back(&_gfxManagerInstance); + + _sceneObjects = &_sceneObjectsInstance; + _sceneObjects_queue.push_front(_sceneObjects); + + _prevSceneOffset = Common::Point(-1, -1); + _sceneListeners.push_back(&_soundHandler); + _sceneListeners.push_back(&_sequenceManager._soundHandler); +} + +Globals::~Globals() { + _globals = NULL; +} + +void Globals::reset() { + Common::set_to(&_flags[0], &_flags[MAX_FLAGS], false); + _saver->addFactory(classFactoryProc); +} + +void Globals::synchronise(Serialiser &s) { + assert(_gfxManagers.size() == 1); + + _sceneItems.synchronise(s); + SYNC_POINTER(_sceneObjects); + _sceneObjects_queue.synchronise(s); + s.syncAsSint32LE(_gfxFontNumber); + s.syncAsSint32LE(_gfxColours.background); + s.syncAsSint32LE(_gfxColours.foreground); + s.syncAsSint32LE(_fontColours.background); + s.syncAsSint32LE(_fontColours.foreground); + + s.syncAsSint16LE(_dialogCentre.x); s.syncAsSint16LE(_dialogCentre.y); + _sceneListeners.synchronise(s); + for (int i = 0; i < 256; ++i) + s.syncAsByte(_flags[i]); + + s.syncAsSint16LE(_sceneOffset.x); s.syncAsSint16LE(_sceneOffset.y); + s.syncAsSint16LE(_prevSceneOffset.x); s.syncAsSint16LE(_prevSceneOffset.y); + SYNC_POINTER(_scrollFollower); + s.syncAsSint32LE(_stripNum); +} + +} // end of namespace tSage diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h new file mode 100644 index 0000000000..59afe140a0 --- /dev/null +++ b/engines/tsage/globals.h @@ -0,0 +1,100 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_GLOBALS_H +#define TSAGE_GLOBALS_H + +#include "common/random.h" +#include "tsage/core.h" +#include "tsage/dialogs.h" +#include "tsage/scenes.h" +#include "tsage/events.h" +#include "tsage/saveload.h" + +namespace tSage { + +class Globals : public SavedObject { +public: + GfxSurface _screenSurface; + GfxManager _gfxManagerInstance; + Common::List<GfxManager *> _gfxManagers; + SceneHandler _sceneHandler; + Game _game; + EventsClass _events; + SceneManager _sceneManager; + ScenePalette _scenePalette; + SceneRegions _sceneRegions; + SceneItemList _sceneItems; + SceneObjectList _sceneObjectsInstance; + SceneObjectList *_sceneObjects; + SynchronisedList<SceneObjectList *> _sceneObjects_queue; + SceneText _sceneText; + int _gfxFontNumber; + GfxColours _gfxColours; + GfxColours _fontColours; + SoundManager _soundManager; + Common::Point _dialogCentre; + WalkRegions _walkRegions; + SynchronisedList<EventHandler *> _sceneListeners; + bool _flags[256]; + Player _player; + SoundHandler _soundHandler; + InvObjectList _inventory; + Region _paneRegions[2]; + int _paneRefreshFlag[2]; + Common::Point _sceneOffset; + Common::Point _prevSceneOffset; + SceneObject *_scrollFollower; + SequenceManager _sequenceManager; + Common::RandomSource _randomSource; + int _stripNum; +public: + Globals(); + ~Globals(); + + void reset(); + void setFlag(int flagNum) { + assert((flagNum > 0) && (flagNum < MAX_FLAGS)); + _flags[flagNum] = true; + } + void clearFlag(int flagNum) { + assert((flagNum > 0) && (flagNum < MAX_FLAGS)); + _flags[flagNum] = false; + } + bool getFlag(int flagNum) const { + assert((flagNum > 0) && (flagNum < MAX_FLAGS)); + return _flags[flagNum]; + } + + GfxManager &gfxManager() { return **_gfxManagers.begin(); } + virtual Common::String getClassName() { return "Globals"; } + virtual void synchronise(Serialiser &s); +}; + +extern Globals *_globals; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp new file mode 100644 index 0000000000..641e10b3e9 --- /dev/null +++ b/engines/tsage/graphics.cpp @@ -0,0 +1,1430 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/events.h" +#include "tsage/graphics.h" +#include "tsage/resources.h" +#include "tsage/tsage.h" +#include "tsage/core.h" +#include "common/algorithm.h" +#include "graphics/surface.h" +#include "tsage/globals.h" + +namespace tSage { + +/** + * Creates a new graphics surface with the specified area of another surface + * + * @src Source surface + * @bounds Area to backup + */ +GfxSurface *Surface_getArea(GfxSurface &src, const Rect &bounds) { + assert(bounds.isValidRect()); + GfxSurface *dest = new GfxSurface(); + dest->create(bounds.width(), bounds.height()); + + Graphics::Surface srcSurface = src.lockSurface(); + Graphics::Surface destSurface = dest->lockSurface(); + + byte *srcP = (byte *)srcSurface.getBasePtr(bounds.left, bounds.top); + byte *destP = (byte *)destSurface.getBasePtr(0, 0); + + for (int y = bounds.top; y < bounds.bottom; ++y, srcP += srcSurface.pitch, destP += destSurface.pitch) + Common::copy(srcP, srcP + destSurface.pitch, destP); + + src.unlockSurface(); + dest->unlockSurface(); + return dest; +} + +/** + * Translates a raw image resource into a graphics surface. The caller is then responsible + * for managing and destroying the surface when done with it + * + * @imgData Raw image resource + * @size Size of the resource + */ +GfxSurface surfaceFromRes(const byte *imgData) { + Rect r(0, 0, READ_LE_UINT16(imgData), READ_LE_UINT16(imgData + 2)); + GfxSurface s; + s.create(r.width(), r.height()); + s._centroid.x = READ_LE_UINT16(imgData + 4); + s._centroid.y = READ_LE_UINT16(imgData + 6); + s._transColour = *(imgData + 8); + + bool rleEncoded = (imgData[9] & 2) != 0; + + const byte *srcP = imgData + 10; + Graphics::Surface destSurface = s.lockSurface(); + byte *destP = (byte *)destSurface.getBasePtr(0, 0); + + if (!rleEncoded) { + Common::copy(srcP, srcP + (r.width() * r.height()), destP); + } else { + Common::set_to(destP, destP + (r.width() * r.height()), s._transColour); + + for (int yp = 0; yp < r.height(); ++yp) { + int width = r.width(); + destP = (byte *)destSurface.getBasePtr(0, yp); + + while (width > 0) { + uint8 controlVal = *srcP++; + if ((controlVal & 0x80) == 0) { + // Copy specified number of bytes + + Common::copy(srcP, srcP + controlVal, destP); + width -= controlVal; + srcP += controlVal; + destP += controlVal; + } else if ((controlVal & 0x40) == 0) { + // Skip a specified number of output pixels + destP += controlVal & 0x3f; + width -= controlVal & 0x3f; + } else { + // Copy a specified pixel a given number of times + controlVal &= 0x3f; + int pixel = *srcP++; + + Common::set_to(destP, destP + controlVal, pixel); + destP += controlVal; + width -= controlVal; + } + } + assert(width == 0); + } + } + + s.unlockSurface(); + return s; +} + +GfxSurface surfaceFromRes(int resNum, int rlbNum, int subNum) { + uint size; + byte *imgData = _vm->_dataManager->getSubResource(resNum, rlbNum, subNum, &size); + GfxSurface surface = surfaceFromRes(imgData); + DEALLOCATE(imgData); + + return surface; +} +/*--------------------------------------------------------------------------*/ + +void Rect::set(int16 x1, int16 y1, int16 x2, int16 y2) { + left = x1; top = y1; + right = x2; bottom = y2; +} + +/** + * Collapses the rectangle in all four directions by the given x and y amounts + * + * @dx x amount to collapse x edges by + * @dy y amount to collapse y edges by + */ +void Rect::collapse(int dx, int dy) { + left += dx; right -= dx; + top += dy; bottom -= dy; +} + +/** + * Centres the rectangle at a given position + * + * @xp x position for new centre + * @yp y position for new centre + */ +void Rect::centre(int xp, int yp) { + moveTo(xp - (width() / 2), yp - (height() / 2)); +} + +/** + * Centres the rectangle at the centre of a second passed rectangle + * + * @r Second rectangle whose centre to use + */ +void Rect::centre(const Rect &r) { + centre(r.left + (r.width() / 2), r.top + (r.height() / 2)); +} + +/* + * Repositions the bounds if necessary so it falls entirely within the passed bounds + * + * @r The bounds the current rect should be within + */ +void Rect::contain(const Rect &r) { + if (left < r.left) translate(r.left - left, 0); + if (right > r.right) translate(r.right - right, 0); + if (top < r.top) translate(0, r.top - top); + if (bottom > r.bottom) translate(0, r.bottom - bottom); +} + +/** + * Resizes and positions a given rect based on raw image data and a passed scaling percentage + * + * @frame Raw image frame + * @xp New x position + * @yp New y position + * @percent Scaling percentage + */ +void Rect::resize(const GfxSurface &surface, int xp, int yp, int percent) { + int xe = surface.getBounds().width() * percent / 100; + int ye = surface.getBounds().height() * percent / 100; + this->set(0, 0, xe, ye); + + if (!right) ++right; + if (!bottom) ++bottom; + + this->moveTo(xp, yp); + + int xd = surface._centroid.x * percent / 100; + int yd = surface._centroid.y * percent / 100; + this->translate(-xd, -yd); +} + +/** + * Expands the pane region to contain the specified Rect + */ +void Rect::expandPanes() { + _globals->_paneRegions[0].uniteRect(*this); + _globals->_paneRegions[1].uniteRect(*this); +} + +/** + * Serialises the given rect + */ +void Rect::synchronise(Serialiser &s) { + s.syncAsSint16LE(left); + s.syncAsSint16LE(top); + s.syncAsSint16LE(right); + s.syncAsSint16LE(bottom); +} + +/*--------------------------------------------------------------------------*/ + +GfxSurface::GfxSurface() : _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) { + _disableUpdates = false; + _screenSurface = false; + _lockSurfaceCtr = 0; + _customSurface = NULL; + _screenSurfaceP = NULL; +} + +GfxSurface::GfxSurface(const GfxSurface &s) { + _lockSurfaceCtr = 0; + _customSurface = NULL; + this->operator =(s); +} + +GfxSurface::~GfxSurface() { + if (_customSurface) { + _customSurface->free(); + delete _customSurface; + } +} + +/** + * Specifies that the surface will encapsulate the ScummVM screen surface + */ +void GfxSurface::setScreenSurface() { + _screenSurface = true; + _customSurface = NULL; + _lockSurfaceCtr = 0; +} + +/** + * Specifies that the surface should maintain it's own internal surface + */ +void GfxSurface::create(int width, int height) { + assert((width >= 0) && (height >= 0)); + _screenSurface = false; + _customSurface = new Graphics::Surface(); + _customSurface->create(width, height, 1); + _bounds = Rect(0, 0, width, height); +} + +/** + * Locks the surface for access, and returns a raw ScummVM surface to manipulate it + */ +Graphics::Surface GfxSurface::lockSurface() { + ++_lockSurfaceCtr; + + Graphics::Surface *src; + if (_screenSurface) { + if (_lockSurfaceCtr == 1) + _screenSurfaceP = g_system->lockScreen(); + src = _screenSurfaceP; + } else + src = _customSurface; + assert(src); + + // Setup the returned surface either as one pointing to the same pixels as the source, or + // as a subset of the source one based on the currently set bounds + Graphics::Surface result; + result.w = _bounds.width(); + result.h = _bounds.height(); + result.pitch = src->pitch; + result.bytesPerPixel = src->bytesPerPixel; + result.pixels = src->getBasePtr(_bounds.left, _bounds.top); + + return result; +} + +/** + * Unlocks the surface after having accessed it with the lockSurface method + */ +void GfxSurface::unlockSurface() { + assert(_lockSurfaceCtr > 0); + --_lockSurfaceCtr; + + if ((_lockSurfaceCtr == 0) && _screenSurface) { + g_system->unlockScreen(); + } +} + +/** + * Fills a specified rectangle on the surface with the specified colour + * + * @bounds Area to fill + * @colour Colour to use + */ +void GfxSurface::fillRect(const Rect &bounds, int colour) { + Graphics::Surface surface = lockSurface(); + surface.fillRect(bounds, colour); + unlockSurface(); +} + +GfxSurface &GfxSurface::operator=(const GfxSurface &s) { + assert(_lockSurfaceCtr == 0); + assert(s._lockSurfaceCtr == 0); + + if (_customSurface) { + _customSurface->free(); + delete _customSurface; + } + + _customSurface = s._customSurface; + _screenSurface = s._screenSurface; + _disableUpdates = s._disableUpdates; + _bounds = s._bounds; + _centroid = s._centroid; + _transColour = s._transColour; + + if (_customSurface) { + // Surface owns the internal data, so replicate it so new surface owns it's own + _customSurface = new Graphics::Surface(); + _customSurface->create(s._customSurface->w, s._customSurface->h, 1); + const byte *srcP = (const byte *)s._customSurface->getBasePtr(0, 0); + byte *destP = (byte *)_customSurface->getBasePtr(0, 0); + + Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP); + } + + return *this; +} + +/** + * Displays a message on-screen until either a mouse or keypress + */ +bool GfxSurface::displayText(const Common::String &msg, const Common::Point &pt) { + // Set up a new graphics manager + GfxManager gfxManager; + gfxManager.activate(); + gfxManager._font._colours.background = 0; + gfxManager._font._colours.foreground = 7; + gfxManager._font.setFontNumber(2); + + // Get the area for text display + Rect textRect; + gfxManager.getStringBounds(msg.c_str(), textRect, 200); + textRect.centre(pt.x, pt.y); + + // Make a backup copy of the area the text will occupy + Rect saveRect = textRect; + saveRect.collapse(-20, -8); + GfxSurface *savedArea = Surface_getArea(gfxManager.getSurface(), saveRect); + + // Display the text + gfxManager._font.writeLines(msg.c_str(), textRect, ALIGN_LEFT); + + // Write for a mouse or keypress + Event event; + while (!_globals->_events.getEvent(event, EVENT_BUTTON_DOWN | EVENT_KEYPRESS) && !_vm->getEventManager()->shouldQuit()) + ; + + // Restore the display area + gfxManager.copyFrom(*savedArea, saveRect.left, saveRect.top); + delete savedArea; + + gfxManager.deactivate(); + return (event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN); +} + +/** + * Loads a quarter of a screen from a resource + */ +void GfxSurface::loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection) { + int screenNum = _globals->_sceneManager._scene->_activeScreenNumber; + Rect updateRect(0, 0, 160, 100); + updateRect.translate(xHalf * 160, yHalf * 100); + int xHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.right + 159) / 160; + int yHalfCount = (_globals->_sceneManager._scene->_backgroundBounds.bottom + 99) / 100; + + if (xSection < xHalfCount && ySection < yHalfCount) { + int rlbNum = xSection * yHalfCount + ySection; + byte *data = _vm->_dataManager->getResource(RES_BITMAP, screenNum, rlbNum); + + for (int y = 0; y < updateRect.height(); ++y) { + byte *pSrc = data + y * 160; + byte *pDest = (byte *)dest.getBasePtr(updateRect.left, updateRect.top + y); + + for (int x = 0; x < updateRect.width(); ++x, ++pSrc, ++pDest) { + *pDest = *pSrc; + } + } + + DEALLOCATE(data); + } +} + +/** + * Returns an array indicating which pixels of a source image horizontally or vertically get + * included in a scaled image + */ +static int *scaleLine(int size, int srcSize) { + int scale = 100 * size / srcSize; + assert(scale >= 0); + int *v = new int[size]; + Common::set_to(v, &v[size], 0); + + int distCtr = 0; + int *destP = v; + for (int distIndex = 0; distIndex < srcSize; ++distIndex) { + distCtr += scale; + while (distCtr >= 100) { + assert(destP < &v[size]); + *destP++ = distIndex; + distCtr -= 100; + } + } + + return v; +} + +/** + * Scales a passed surface, creating a new surface with the result + * @param srcImage Source image to scale + * @param NewWidth New width for scaled image + * @param NewHeight New height for scaled image + * @remarks Caller is responsible for freeing the returned surface + */ +static GfxSurface ResizeSurface(GfxSurface &src, int xSize, int ySize) { + GfxSurface s; + s.create(xSize, ySize); + + Graphics::Surface srcImage = src.lockSurface(); + Graphics::Surface destImage = s.lockSurface(); + + int *horizUsage = scaleLine(xSize, srcImage.w); + int *vertUsage = scaleLine(ySize, srcImage.h); + + // Loop to create scaled version + for (int yp = 0; yp < ySize; ++yp) { + const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]); + byte *destP = (byte *)destImage.getBasePtr(0, yp); + + for (int xp = 0; xp < xSize; ++xp) { + const byte *tempSrcP = srcP + horizUsage[xp]; + *destP++ = *tempSrcP++; + } + } + + // Unlock surfaces + src.unlockSurface(); + s.unlockSurface(); + + // Delete arrays and return surface + delete[] horizUsage; + delete[] vertUsage; + return s; +} + +/** + * Copys an area from one GfxSurface to another + */ +void GfxSurface::copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion) { + GfxSurface srcImage; + + if (srcBounds == src.getBounds()) + srcImage = src; + else { + // Set the source image to be the subset specified by the source bounds + Graphics::Surface srcSurface = src.lockSurface(); + + srcImage.create(srcBounds.width(), srcBounds.height()); + Graphics::Surface destSurface = srcImage.lockSurface(); + + const byte *srcP = (const byte *)srcSurface.getBasePtr(srcBounds.left, srcBounds.top); + byte *destP = (byte *)destSurface.pixels; + for (int yp = srcBounds.top; yp < srcBounds.bottom; ++yp, srcP += srcSurface.pitch, destP += destSurface.pitch) { + Common::copy(srcP, srcP + srcBounds.width(), destP); + } + + srcImage.unlockSurface(); + src.unlockSurface(); + } + + if ((destBounds.width() != srcBounds.width()) || (destBounds.height() != srcBounds.height())) + srcImage = ResizeSurface(srcImage, destBounds.width(), destBounds.height()); + + Graphics::Surface srcSurface = srcImage.lockSurface(); + Graphics::Surface destSurface = lockSurface(); + + // Adjust bounds to ensure destination will be on-screen + int srcX = 0, srcY = 0; + if (destBounds.left < 0) { + srcX = -destBounds.left; + destBounds.left = 0; + } + if (destBounds.top < 0) { + srcY = -destBounds.top; + destBounds.top = 0; + } + if (destBounds.right > destSurface.w) + destBounds.right = destSurface.w; + if (destBounds.bottom > destSurface.h) + destBounds.bottom = destSurface.h; + + if (destBounds.isValidRect()) { + const byte *pSrc = (const byte *)srcSurface.getBasePtr(srcX, srcY); + byte *pDest = (byte *)destSurface.getBasePtr(destBounds.left, destBounds.top); + + for (int y = 0; y < destBounds.height(); ++y, pSrc += srcSurface.pitch, pDest += destSurface.pitch) { + + if (!priorityRegion && (src._transColour == -1)) + Common::copy(pSrc, pSrc + destBounds.width(), pDest); + else { + const byte *tempSrc = pSrc; + byte *tempDest = pDest; + int xp = destBounds.left; + + while (tempSrc < (pSrc + destBounds.width())) { + if (!priorityRegion || !priorityRegion->contains(Common::Point( + xp + _globals->_sceneManager._scene->_sceneBounds.left, + destBounds.top + y + _globals->_sceneManager._scene->_sceneBounds.top))) { + if (*tempSrc != src._transColour) + *tempDest = *tempSrc; + } + ++tempSrc; + ++tempDest; + ++xp; + } + } + } + } + + unlockSurface(); + srcImage.unlockSurface(); +} + +void GfxSurface::draw(const Common::Point &pt, Rect *rect) { + Rect tempRect = getBounds(); + tempRect.translate(-_centroid.x, -_centroid.y); + tempRect.translate(pt.x, pt.y); + + if (rect) { + // Only copy needed rect out without drawing + *rect = tempRect; + } else { + // Draw image + _globals->gfxManager().copyFrom(*this, tempRect, NULL); + } +} + +/*--------------------------------------------------------------------------*/ + +GfxElement::GfxElement() { + _owner = NULL; + _keycode = 0; + _flags = 0; +} + +void GfxElement::setDefaults() { + _flags = 0; + _fontNumber = _globals->_gfxFontNumber; + _colours = _globals->_gfxColours; + _fontColours = _globals->_fontColours; +} + +/** + * Highlights the specified graphics element + */ +void GfxElement::highlight() { + // Get a lock on the surface + GfxManager &gfxManager = _globals->gfxManager(); + Graphics::Surface surface = gfxManager.lockSurface(); + + // Scan through the contents of the element, switching any occurances of the foreground + // colour with the background colour and vice versa + Rect tempRect(_bounds); + tempRect.collapse(2, 2); + + for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) { + byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp); + for (int xp = tempRect.left; xp < tempRect.right; ++xp, ++lineP) { + if (*lineP == _colours.background) *lineP = _colours.foreground; + else if (*lineP == _colours.foreground) *lineP = _colours.background; + } + } + + // Release the surface + gfxManager.unlockSurface(); +} + +/** + * Fills the background of the specified element with a border frame + */ +void GfxElement::drawFrame() { + // Get a lock on the surface and save the active font + GfxManager &gfxManager = _globals->gfxManager(); + gfxManager.lockSurface(); + + uint8 bgColour, fgColour; + if (_flags & GFXFLAG_THICK_FRAME) { + bgColour = 0; + fgColour = 0; + } else { + bgColour = _fontColours.background; + fgColour = _fontColours.foreground; + } + + Rect tempRect = _bounds; + tempRect.collapse(3, 3); + tempRect.collapse(-1, -1); + gfxManager.fillRect(tempRect, _colours.background); + + --tempRect.bottom; --tempRect.right; + gfxManager.fillArea(tempRect.left, tempRect.top, bgColour); + gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColour); + gfxManager.fillArea(tempRect.right, tempRect.top, fgColour); + gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColour); + + tempRect.collapse(-1, -1); + gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColour); + gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColour); + gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColour); + gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColour); + + gfxManager.fillArea(tempRect.left, tempRect.top, 0); + gfxManager.fillArea(tempRect.left, tempRect.bottom, 0); + gfxManager.fillArea(tempRect.right, tempRect.top, 0); + gfxManager.fillArea(tempRect.right, tempRect.bottom, 0); + + tempRect.collapse(-1, -1); + gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0); + gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0); + gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0); + gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0); + + gfxManager.unlockSurface(); +} + +/** + * Handles events when the control has focus + * + * @event Event to process + */ +bool GfxElement::focusedEvent(Event &event) { + bool highlightFlag = false; + + while (!_vm->getEventManager()->shouldQuit()) { + g_system->delayMillis(10); + + if (_bounds.contains(event.mousePos)) { + if (!highlightFlag) { + // First highlight call to show the highlight + highlightFlag = true; + highlight(); + } + } else if (highlightFlag) { + // Mouse is outside the element, so remove the highlight + highlightFlag = false; + highlight(); + } + + if (_globals->_events.getEvent(event, EVENT_BUTTON_UP)) + break; + } + + if (highlightFlag) { + // Mouse is outside the element, so remove the highlight + highlight(); + } + + return highlightFlag; +} + +/*--------------------------------------------------------------------------*/ + +GfxImage::GfxImage() : GfxElement() { + _resNum = 0; + _rlbNum = 0; + _cursorNum = 0; +} + +void GfxImage::setDetails(int resNum, int rlbNum, int cursorNum) { + _resNum = resNum; + _rlbNum = rlbNum; + _cursorNum = cursorNum; + setDefaults(); +} + +void GfxImage::setDefaults() { + GfxElement::setDefaults(); + + // Decode the image + uint size; + byte *imgData = _vm->_dataManager->getSubResource(_resNum, _rlbNum, _cursorNum, &size); + _surface = surfaceFromRes(imgData); + DEALLOCATE(imgData); + + // Set up the display bounds + Rect imgBounds = _surface.getBounds(); + imgBounds.moveTo(_bounds.left, _bounds.top); + _bounds = imgBounds; +} + +void GfxImage::draw() { + Rect tempRect = _bounds; + tempRect.translate(_globals->gfxManager()._topLeft.x, _globals->gfxManager()._topLeft.y); + + _globals->gfxManager().copyFrom(_surface, tempRect); +} + +/*--------------------------------------------------------------------------*/ + +GfxMessage::GfxMessage() : GfxElement() { + _textAlign = ALIGN_LEFT; + _width = 0; +} + +void GfxMessage::set(const Common::String &s, int width, TextAlign textAlign) { + _message = s; + _width = width; + _textAlign = textAlign; + + setDefaults(); +} + +void GfxMessage::setDefaults() { + GfxElement::setDefaults(); + + GfxFontBackup font; + GfxManager &gfxManager = _globals->gfxManager(); + Rect tempRect; + + gfxManager._font.setFontNumber(this->_fontNumber); + gfxManager.getStringBounds(_message.c_str(), tempRect, _width); + + tempRect.collapse(-1, -1); + tempRect.moveTo(_bounds.left, _bounds.top); + _bounds = tempRect; +} + +void GfxMessage::draw() { + GfxFontBackup font; + GfxManager &gfxManager = _globals->gfxManager(); + + // Set the font and colour + gfxManager.setFillFlag(false); + gfxManager._font.setFontNumber(_fontNumber); + gfxManager._font._colours.foreground = this->_colours.foreground; + + // Display the text + gfxManager._font.writeLines(_message.c_str(), _bounds, _textAlign); +} + +/*--------------------------------------------------------------------------*/ + +void GfxButton::setDefaults() { + GfxElement::setDefaults(); + + GfxFontBackup font; + GfxManager &gfxManager = _globals->gfxManager(); + Rect tempRect; + + // Get the string bounds and round up the x end to a multiple of 16 + gfxManager._font.setFontNumber(this->_fontNumber); + gfxManager._font.getStringBounds(_message.c_str(), tempRect, 240); + tempRect.right = ((tempRect.right + 15) / 16) * 16; + + // Set the button bounds to a reduced area + tempRect.collapse(-3, -3); + tempRect.moveTo(_bounds.left, _bounds.top); + _bounds = tempRect; +} + +void GfxButton::draw() { + // Get a lock on the surface and save the active font + GfxFontBackup font; + GfxManager &gfxManager = _globals->gfxManager(); + gfxManager.lockSurface(); + + // Draw a basic frame for the button + drawFrame(); + + // Set the font and colour + gfxManager._font.setFontNumber(_fontNumber); + gfxManager._font._colours.foreground = this->_colours.foreground; + + // Display the button's text + Rect tempRect(_bounds); + tempRect.collapse(3, 3); + gfxManager._font.writeLines(_message.c_str(), tempRect, ALIGN_CENTRE); + + gfxManager.unlockSurface(); +} + +bool GfxButton::process(Event &event) { + switch (event.eventType) { + case EVENT_BUTTON_DOWN: + if (!event.handled) { + if (_bounds.contains(event.mousePos)) { + bool result = focusedEvent(event); + event.handled = true; + return result; + } + } + break; + + case EVENT_KEYPRESS: + if (!event.handled && (event.kbd.keycode == _keycode)) { + // TODO: Ensure momentary click operation displays + highlight(); + g_system->delayMillis(20); + highlight(); + + event.handled = true; + return true; + } + + default: + break; + } + + return false; +} + +/*--------------------------------------------------------------------------*/ + +GfxDialog::GfxDialog() { + _savedArea = NULL; + _defaultButton = NULL; +} + +GfxDialog::~GfxDialog() { + remove(); +} + +void GfxDialog::setDefaults() { + GfxElement::setDefaults(); + + // Initialise the embedded graphics manager + _gfxManager.setDefaults(); + + // Figure out a rect needed for all the added elements + GfxElementList::iterator i; + Rect tempRect; + for (i = _elements.begin(); i != _elements.end(); ++i) + tempRect.extend((*i)->_bounds); + + // Set the dialog boundaries + _gfxManager._bounds = tempRect; + tempRect.collapse(-6, -6); + _bounds = tempRect; +} + +void GfxDialog::remove() { + if (_savedArea) { + // Restore the area the dialog covered + _globals->_gfxManagerInstance.copyFrom(*_savedArea, _bounds.left, _bounds.top); + + delete _savedArea; + _savedArea = NULL; + } +} + +void GfxDialog::draw() { + Rect tempRect(_bounds); + + // Make a backup copy of the area the dialog will occupy + _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds); + + // Set the palette for use in the dialog + setPalette(); + + _gfxManager.activate(); + + // Fill in the contents of the entire dialog + _gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + drawFrame(); + + // Reset the dialog's graphics manager to only draw within the dialog boundaries + tempRect.translate(6, 6); + _gfxManager._bounds = tempRect; + + // Draw each element in the dialog in order + GfxElementList::iterator i; + for (i = _elements.begin(); i != _elements.end(); ++i) { + (*i)->draw(); + } + + // If there's a default button, then draw it + if (_defaultButton) { + _defaultButton->_flags |= GFXFLAG_THICK_FRAME; + _defaultButton->draw(); + } + + _gfxManager.deactivate(); +} + +void GfxDialog::add(GfxElement *element) { + _elements.push_back(element); + element->_owner = this; +} + +void GfxDialog::addElements(GfxElement *ge, ...) { + va_list va; + va_start(va, ge); + GfxElement *gfxElement = ge; + while (gfxElement) { + add(gfxElement); + + gfxElement = va_arg(va, GfxElement *); + } + + va_end(va); +} + +void GfxDialog::setTopLeft(int xp, int yp) { + _bounds.moveTo(xp - 6, yp - 6); +} + +void GfxDialog::setCentre(int xp, int yp) { + setTopLeft(xp - (_bounds.width() / 2), yp - (_bounds.height() / 2)); +} + +GfxButton *GfxDialog::execute(GfxButton *defaultButton) { + _gfxManager.activate(); + + if (defaultButton != _defaultButton) { + if (_defaultButton) { + _defaultButton->_flags &= ~GFXFLAG_THICK_FRAME; + _defaultButton->draw(); + } + _defaultButton = defaultButton; + } + if (_defaultButton) { + _defaultButton->_flags |= GFXFLAG_THICK_FRAME; + _defaultButton->draw(); + } + + // Event loop + GfxButton *selectedButton = NULL; + + while (!_vm->getEventManager()->shouldQuit()) { + Event event; + while (_globals->_events.getEvent(event)) { + // Adjust mouse positions to be relative within the dialog + event.mousePos.x -= _gfxManager._bounds.left; + event.mousePos.y -= _gfxManager._bounds.top; + + for (GfxElementList::iterator i = _elements.begin(); i != _elements.end(); ++i) { + if ((*i)->process(event)) + selectedButton = static_cast<GfxButton *>(*i); + } + } + + if (selectedButton) + break; + else if (!event.handled) { + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) { + selectedButton = NULL; + break; + } else if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_RETURN)) { + selectedButton = defaultButton; + break; + } + } + } + + _gfxManager.deactivate(); + if (_defaultButton) + _defaultButton->_flags &= ~GFXFLAG_THICK_FRAME; + + return selectedButton; +} + +void GfxDialog::setPalette() { + _globals->_scenePalette.loadPalette(0); + _globals->_scenePalette.setPalette(0, 1); + _globals->_scenePalette.setPalette(_globals->_scenePalette._colours.foreground, 1); + _globals->_scenePalette.setPalette(_globals->_fontColours.background, 1); + _globals->_scenePalette.setPalette(_globals->_fontColours.foreground, 1); + _globals->_scenePalette.setPalette(255, 1); +} + +/*--------------------------------------------------------------------------*/ + +GfxManager::GfxManager() : _surface(_globals->_screenSurface), _oldManager(NULL) { + _font.setOwner(this); + _font._fillFlag = false; + _bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); +} + +GfxManager::GfxManager(GfxSurface &s) : _surface(s), _oldManager(NULL) { + _font.setOwner(this); + _font._fillFlag = false; +} + +void GfxManager::setDefaults() { + Rect screenBounds(0, 0, g_system->getWidth(), g_system->getHeight()); + + _surface.setBounds(screenBounds); + _bounds = screenBounds; + _pane0Rect4 = screenBounds; + + _font._edgeSize = Common::Point(1, 1); + _font._colours = _globals->_fontColours; + _font.setFontNumber(_globals->_gfxFontNumber); +} + +void GfxManager::activate() { + assert(!contains(_globals->_gfxManagers, this)); + _globals->_gfxManagers.push_front(this); +} + +void GfxManager::deactivate() { + // Assert that there will still be another manager, and we're correctly removing our own + assert((_globals->_gfxManagers.size() > 1) && (&_globals->gfxManager() == this)); + _globals->_gfxManagers.pop_front(); +} + +int GfxManager::getStringWidth(const char *s, int numChars) { + return _font.getStringWidth(s, numChars); +} + +int GfxManager::getStringWidth(const char *s) { + return _font.getStringWidth(s); +} + +void GfxManager::getStringBounds(const char *s, Rect &bounds, int maxWidth) { + _font.getStringBounds(s, bounds, maxWidth); +} + +void GfxManager::fillArea(int xp, int yp, int colour) { + _surface.setBounds(_bounds); + Rect tempRect(xp, yp, xp + _font._edgeSize.x, yp + _font._edgeSize.y); + _surface.fillRect(tempRect, colour); +} + +void GfxManager::fillRect(const Rect &bounds, int colour) { + _surface.setBounds(_bounds); + _surface.fillRect(bounds, colour); +} + +void GfxManager::fillRect2(int xs, int ys, int width, int height, int colour) { + _surface.setBounds(_bounds); + _surface.fillRect(Rect(xs, ys, xs + width, ys + height), colour); +} + +/** + * Sets up the standard palette for dialog displays + */ +void GfxManager::setDialogPalette() { + // Get the main palette information + RGB8 palData[256]; + uint count, start; + _vm->_dataManager->getPalette(0, &palData[0], &start, &count); + g_system->getPaletteManager()->setPalette((byte *)&palData[0], start, count); + + // Miscellaneous + uint32 white = 0xffffffff; + g_system->getPaletteManager()->setPalette((const byte *)&white, 255, 1); +} + +/** + * Returns the angle of line connecting two points + */ +int GfxManager::getAngle(const Common::Point &p1, const Common::Point &p2) { + int xDiff = p2.x - p1.x, yDiff = p1.y - p2.y; + + if (!xDiff && !yDiff) + return -1; + else if (!xDiff) + return (p2.y >= p1.y) ? 180 : 0; + else if (!yDiff) + return (p2.x >= p1.x) ? 90 : 270; + else { + int result = (((xDiff * 100) / ((abs(xDiff) + abs(yDiff))) * 90) / 100); + + if (yDiff < 0) + result = 180 - result; + else if (xDiff < 0) + result += 360; + + return result; + } +} +/*--------------------------------------------------------------------------*/ + + +GfxFont::GfxFont() { + _fontNumber = 50; + _numChars = 0; + _bpp = 0; + _fontData = NULL; + _fillFlag = false; +} + +GfxFont::~GfxFont() { + DEALLOCATE(_fontData); +} + +/** + * Sets the current active font number + * + * @fontNumber New font number + */ +void GfxFont::setFontNumber(uint32 fontNumber) { + if ((_fontNumber == fontNumber) && (_fontData)) + return; + + DEALLOCATE(_fontData); + + _fontNumber = fontNumber; + + _fontData = _vm->_tSageManager->getResource(RES_FONT, _fontNumber, 0, true); + if (!_fontData) + _fontData = _vm->_dataManager->getResource(RES_FONT, _fontNumber, 0); + + _numChars = READ_LE_UINT16(_fontData + 4); + _fontSize.y = READ_LE_UINT16(_fontData + 6); + _fontSize.x = READ_LE_UINT16(_fontData + 8); + _bpp = READ_LE_UINT16(_fontData + 10); +} + +/** + * Returns the width of the given specified character + * + * @ch Character to return width of + */ +int GfxFont::getCharWidth(char ch) { + assert(_numChars > 0); + uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)ch * 4); + return _fontData[charOffset] & 0x1f; +} + +/** + * Returns the width of the given string in the current font + * + * @s String to return the width of + * @numChars Number of characters within the string to use + */ +int GfxFont::getStringWidth(const char *s, int numChars) { + assert(_numChars > 0); + int width = 0; + + for (; numChars > 0; --numChars, ++s) { + uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)*s * 4); + int charWidth = _fontData[charOffset] & 0x1f; + + width += charWidth; + } + + return width; +} + +/** + * Returns the width of the given string in the current font + * + * @s String to return the width of + */ +int GfxFont::getStringWidth(const char *s) { + return getStringWidth(s, strlen(s)); +} + +/** + * Returns the maximum number of characters for words that will fit into a given width + * + * @s Message to be analysed + * @maxWidth Maximum allowed width + */ +int GfxFont::getStringFit(const char *&s, int maxWidth) { + const char *nextWord = NULL; + const char *sStart = s; + int numChars = 1; + int strWidth = 1; + char nextChar; + + for (;;) { + nextChar = *s++; + + if ((nextChar == '\r') || (nextChar == '\0')) + break; + + // Check if it's a word end + if (nextChar == ' ') { + nextWord = s; + } + + strWidth = getStringWidth(sStart, numChars); + if (strWidth > maxWidth) { + if (nextWord) { + s = nextWord; + nextChar = ' '; + } + break; + } + + ++numChars; + } + + int totalChars = s - sStart; + if (nextChar == '\0') + --s; + if ((nextChar == ' ') || (nextChar == '\r') || (nextChar == '\0')) + --totalChars; + + return totalChars; +} + +/** + * Fills out the passed rect with the dimensions of a given string word-wrapped to a + * maximum specified width + * + * @s Message to be analysed + * @bounds Rectangle to put output size into + * @maxWidth Maximum allowed line width in pixels + */ +void GfxFont::getStringBounds(const char *s, Rect &bounds, int maxWidth) { + if (maxWidth == 0) { + // No maximum width, so set bounds for a single line + bounds.set(0, 0, getStringWidth(s), getHeight()); + } else { + int numLines = 0; + int lineWidth = 0; + + // Loop to figure out the number of lines required, and the maximum line width + while (*s) { + const char *msg = s; + int numChars = getStringFit(msg, maxWidth); + lineWidth = MAX(lineWidth, getStringWidth(s, numChars)); + + s = msg; + ++numLines; + } + + bounds.set(0, 0, lineWidth, numLines * getHeight()); + } +} + +/** + * Writes out a character at the currently set position using the active font + * + * @ch Character to display + */ +int GfxFont::writeChar(const char ch) { + assert((_fontData != NULL) && ((uint8)ch < _numChars)); + uint32 charOffset = READ_LE_UINT32(_fontData + 12 + (uint8)ch * 4); + int charWidth = _fontData[charOffset] & 0x1f; + int charHeight = (READ_LE_UINT16(_fontData + charOffset) >> 5) & 0x3f; + int yOffset = (_fontData[charOffset + 1] >> 3) & 0x1f; + const uint8 *dataP = &_fontData[charOffset + 2]; + + // Lock the surface for access + Graphics::Surface surfacePtr = _gfxManager->lockSurface(); + + Rect charRect; + charRect.set(0, 0, charWidth, _fontSize.y); + charRect.translate(_topLeft.x + _position.x, _topLeft.y + _position.y + yOffset); + + if (_fillFlag) + surfacePtr.fillRect(charRect, _colours.background); + + charRect.bottom = charRect.top + charHeight; + + // Display the character + int bitCtr = 0; + uint8 v = 0; + for (int yp = charRect.top; yp < charRect.bottom; ++yp) { + byte *destP = (byte *)surfacePtr.getBasePtr(charRect.left, yp); + + for (int xs = 0; xs < charRect.width(); ++xs, ++destP) { + // Get the next colour index to use + if ((bitCtr % 8) == 0) v = *dataP++; + int colIndex = 0; + for (int subCtr = 0; subCtr < _bpp; ++subCtr, ++bitCtr) { + colIndex = (colIndex << 1) | (v & 0x80 ? 1 : 0); + v <<= 1; + } + + switch (colIndex) { + //case 0: *destP = _colours.background; break; + case 1: *destP = _colours.foreground; break; + case 2: *destP = _colours2.background; break; + case 3: *destP = _colours2.foreground; break; + } + } + } + + _position.x += charWidth; + _gfxManager->unlockSurface(); + return charWidth; +} + +/** + * Writes the specified number of characters from the specified string at the current text position + * + * @s String to display + * @numChars Number of characters to print + */ +void GfxFont::writeString(const char *s, int numChars) { + // Lock the surface for access + _gfxManager->lockSurface(); + + while ((numChars-- > 0) && (*s != '\0')) { + writeChar(*s); + ++s; + } + + // Release the surface lock + _gfxManager->unlockSurface(); +} + +/** + * Writes the the specified string at the current text position + * + * @s String to display + */ +void GfxFont::writeString(const char *s) { + writeString(s, strlen(s)); +} + +/** + * Writes a specified string within a given area with support for word wrapping and text alignment types + * + * @s String to display + * @bounds Bounds to display the text within + * @align Text alignment mode + */ +void GfxFont::writeLines(const char *s, const Rect &bounds, TextAlign align) { + int lineNum = 0; + + // Lock the surface for access + _gfxManager->lockSurface(); + + while (*s) { + const char *msgP = s; + int numChars = getStringFit(msgP, bounds.width()); + + _position.y = bounds.top + lineNum * getHeight(); + + switch (align) { + case ALIGN_RIGHT: + // Right aligned text + _position.x = bounds.right - getStringWidth(s, numChars); + writeString(s, numChars); + break; + + case ALIGN_CENTRE: + // Center aligned text + _position.x = bounds.left + (bounds.width() / 2) - (getStringWidth(s, numChars) / 2); + writeString(s, numChars); + break; + + case ALIGN_JUSTIFIED: { + // Justified text + // Get the number of words in the string portion + int charCtr = 0, numWords = 0; + while (charCtr < numChars) { + if (s[charCtr] == ' ') + ++numWords; + ++charCtr; + } + // If end of string, count final word + if (*msgP == '\0') + ++numWords; + + // Display the words of the string + int spareWidth = bounds.width() - getStringWidth(s, numChars); + charCtr = 0; + _position.x = bounds.left; + + while (charCtr < numChars) { + writeChar(s[charCtr]); + if ((numWords > 0) && (s[charCtr] == ' ')) { + int separationWidth = spareWidth / numWords; + spareWidth -= separationWidth; + --numWords; + _position.x += separationWidth; + } + + ++charCtr; + } + break; + } + + case ALIGN_LEFT: + default: + // Standard text + _position.x = bounds.left; + writeString(s, numChars); + break; + } + + // Next line + s = msgP; + ++lineNum; + } + + // Release the surface lock + _gfxManager->unlockSurface(); +} + +/*--------------------------------------------------------------------------*/ + +GfxFontBackup::GfxFontBackup() { + _edgeSize = _globals->gfxManager()._font._edgeSize; + _position = _globals->gfxManager()._font._position; + _colours = _globals->gfxManager()._font._colours; + _fontNumber = _globals->gfxManager()._font._fontNumber; +} + +GfxFontBackup::~GfxFontBackup() { + _globals->gfxManager()._font.setFontNumber(_fontNumber); + _globals->gfxManager()._font._edgeSize = _edgeSize; + _globals->gfxManager()._font._position = _position; + _globals->gfxManager()._font._colours = _colours; +} + + +} // End of namespace tSage diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h new file mode 100644 index 0000000000..0ad76772b3 --- /dev/null +++ b/engines/tsage/graphics.h @@ -0,0 +1,349 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef RING_GRAPHICS_H +#define RING_GRAPHICS_H + +#include "tsage/events.h" +#include "tsage/saveload.h" +#include "common/list.h" +#include "common/rect.h" +#include "common/system.h" +#include "graphics/surface.h" + +namespace tSage { + +class GfxSurface; +class Region; + +/** + * Extended Rect class with extra support methods + */ +class Rect : public Common::Rect, public Serialisable { +public: + Rect() : Common::Rect() {}; + Rect(int16 x1, int16 y1, int16 x2, int16 y2) : Common::Rect(x1, y1, x2, y2) {}; + + void set(int16 x1, int16 y1, int16 x2, int16 y2); + void collapse(int dx, int dy); + void centre(int dx, int dy); + void centre(const Rect &r); + void centre(const Common::Point &pt) { centre(pt.x, pt.y); } + void contain(const Rect &r); + void resize(const GfxSurface &surface, int xp, int yp, int percent); + void expandPanes(); + + virtual void synchronise(Serialiser &s); +}; + +class GfxColours { +public: + uint8 foreground; + uint8 background; + + GfxColours() : foreground(0), background(0) {}; +}; + +class LineSlice { +public: + int xs, xe; + + LineSlice() { xs = 0; xe = 0; } + LineSlice(int xStart, int xEnd) { xs = xStart; xe = xEnd; } +}; + +class GfxSurface { +private: + Graphics::Surface *_customSurface; + Graphics::Surface *_screenSurfaceP; + int _lockSurfaceCtr; + bool _screenSurface; + + bool _disableUpdates; + Rect _bounds; +public: + Common::Point _centroid; + int _transColour; +public: + GfxSurface(); + GfxSurface(const GfxSurface &s); + ~GfxSurface(); + + void setScreenSurface(); + Graphics::Surface lockSurface(); + void unlockSurface(); + void create(int width, int height); + void setBounds(const Rect &bounds) { _bounds = bounds; }; + const Rect &getBounds() const { return _bounds; }; + + void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds, Region *priorityRegion = NULL); + void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL) { + copyFrom(src, src.getBounds(), destBounds, priorityRegion); + } + void copyFrom(GfxSurface &src, int destX = 0, int destY = 0, Region *priorityRegion = NULL) { + Rect tempRect = src.getBounds(); + tempRect.moveTo(destX, destY); + copyFrom(src, tempRect, priorityRegion); + } + void draw(const Common::Point &pt, Rect *rect = NULL); + void fillRect(const Rect &bounds, int colour); + GfxSurface &operator=(const GfxSurface &s); + + static void loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection); + static bool displayText(const Common::String &msg, const Common::Point &pt = Common::Point(160, 100)); +}; + +enum TextAlign {ALIGN_LEFT = 0, ALIGN_CENTRE = 1, ALIGN_RIGHT = 2, ALIGN_JUSTIFIED = 3}; + +class GfxFont { + friend class GfxFontBackup; +private: + GfxManager *_gfxManager; + // Raw font details + const byte *_fontData; + int _numChars; + Common::Point _fontSize; + int _bpp; +public: + // Font fields + Common::Point _edgeSize; + Common::Point _position; + bool _fillFlag; + GfxColours _colours; + GfxColours _colours2; + uint32 _fontNumber; + Common::Point _topLeft; +public: + GfxFont(); + virtual ~GfxFont(); + + void setFontNumber(uint32 fontNumber); + int32 getHeight() const { return _fontSize.y; } + int getCharWidth(char ch); + int getStringWidth(const char *s, int numChars); + int getStringWidth(const char *s); + int getStringFit(const char *&s, int maxWidth); + void getStringBounds(const char *s, Rect &bounds, int maxWidth); + + void setOwner(GfxManager *owner) { _gfxManager = owner; } + void setPosition(int xp, int yp) { _position.x = xp; _position.y = yp; } + int writeChar(const char ch); + void writeString(const char *s); + void writeString(const char *s, int numChars); + void writeLines(const char *s, const Rect &bounds, TextAlign align); +}; + +class GfxFontBackup { +private: + GfxSurface *_surface; + Common::Point _edgeSize; + Common::Point _position; + GfxColours _colours; + uint32 _fontNumber; +public: + GfxFontBackup(); + ~GfxFontBackup(); +}; + +enum GFX_FLAGS {GFXFLAG_THICK_FRAME = 8}; + +class GfxManager; + +class GfxElement { +public: + GfxElement *_owner; + Rect _bounds; + uint16 _flags; + uint16 _fontNumber; + GfxColours _colours; + GfxColours _fontColours; + uint16 _keycode; +public: + GfxElement(); + virtual ~GfxElement() {} + + void drawFrame(); + + // Virtual table method + virtual void setDefaults(); + virtual void remove() { _owner = NULL; } + virtual void highlight(); + virtual void draw() {}; + virtual bool process(Event &event) { return false; }; + virtual bool focusedEvent(Event &event); +}; + +class GfxImage : public GfxElement { +public: + GfxSurface _surface; + int _resNum; + int _rlbNum; + int _cursorNum; +public: + GfxImage(); + + void setDetails(int resNum, int rlbNum, int cursorNum); + + virtual void setDefaults(); + virtual void draw(); + virtual bool process(Event &event) { return false; } +}; + +class GfxMessage : public GfxElement { +public: + Common::String _message; + TextAlign _textAlign; + int _width; +public: + GfxMessage(); + virtual ~GfxMessage() {} + + void set(const Common::String &s, int width, TextAlign textAlign); + + virtual void setDefaults(); + virtual void draw(); +}; + +class GfxButton : public GfxElement { +private: + void setFocus(); +public: + Common::String _message; +public: + GfxButton() : GfxElement() {}; + virtual ~GfxButton() {} + + void setText(const Common::String &s) { + _message = s; + setDefaults(); + } + + // Virtual table method + virtual void setDefaults(); + virtual void draw(); + virtual bool process(Event &event); +}; + +class GfxManager { +private: + GfxSurface &_surface; +public: + GfxManager *_oldManager; + Common::Point _topLeft; + Rect _bounds; + Rect _pane0Rect4; + GfxFont _font; +public: + GfxManager(); + GfxManager(GfxSurface &s); + virtual ~GfxManager() {} + + void setDefaults(); + void activate(); + void deactivate(); + + // Accessor methods + int getStringWidth(const char *s, int numChars); + int getStringWidth(const char *s); + void getStringBounds(const char *s, Rect &bounds, int maxWidth); + + void setDialogPalette(); + Graphics::Surface lockSurface() { + _surface.setBounds(_bounds); + return _surface.lockSurface(); + } + void unlockSurface() { _surface.unlockSurface(); }; + void fillArea(int xp, int yp, int colour); + void fillRect(const Rect &bounds, int colour); + void fillRect2(int xs, int ys, int width, int height, int colour); + void setFillFlag(bool v) { _font._fillFlag = v; } + + static int getAngle(const Common::Point &p1, const Common::Point &p2); + + // Virtual method table + virtual void xorArea(const Common::Rect &r, int colour, int fillMode) { + //_surface->xorArea(r, colour, fillMode); + } + virtual void draw(const Common::Rect &r, void *gfxData, int v1, GfxColours *colours) { + //_surface->draw(r, gfxData, v1, colours); + } + virtual void copy(const byte *src, byte *dest, int size) { + Common::copy(src, src + size, dest); + } + virtual void set(byte *dest, int size, byte val) { + Common::set_to(dest, dest + size, val); + } + void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL) { + _surface.setBounds(_bounds); + _surface.copyFrom(src, destBounds, priorityRegion); + } + void copyFrom(GfxSurface &src, int destX, int destY) { + _surface.setBounds(_bounds); + _surface.copyFrom(src, destX, destY); + g_system->updateScreen(); + } + GfxSurface &getSurface() { + _surface.setBounds(_bounds); + return _surface; + } +}; + +typedef Common::List<GfxElement *> GfxElementList; + +class GfxDialog : public GfxElement { +public: + GfxManager _gfxManager; + GfxElementList _elements; + GfxButton *_defaultButton; + GfxSurface *_savedArea; +public: + GfxDialog(); + virtual ~GfxDialog(); + + void add(GfxElement *element); + void addElements(GfxElement *ge, ...); + void setTopLeft(int xp, int yp); + void setCentre(int xp, int yp); + void frame() { + setDefaults(); + _bounds.collapse(6, 6); + } + GfxButton *execute(GfxButton *defaultButton = NULL); + + virtual void setDefaults(); + virtual void remove(); + virtual void draw(); + + static void setPalette(); +}; + +GfxSurface *Surface_getArea(GfxSurface &src, const Rect &bounds); + +GfxSurface surfaceFromRes(const byte *imgData); +GfxSurface surfaceFromRes(int resNum, int rlbNum, int subNum); + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk new file mode 100644 index 0000000000..41a868195b --- /dev/null +++ b/engines/tsage/module.mk @@ -0,0 +1,35 @@ +MODULE := engines/tsage + +MODULE_OBJS := \ + converse.o \ + core.o \ + debugger.o \ + detection.o \ + dialogs.o \ + events.o \ + globals.o \ + graphics.o \ + resources.o \ + ringworld_logic.o \ + ringworld_scenes1.o \ + ringworld_scenes2.o \ + ringworld_scenes3.o \ + ringworld_scenes4.o \ + ringworld_scenes5.o \ + ringworld_scenes6.o \ + ringworld_scenes8.o \ + ringworld_scenes10.o \ + saveload.o \ + scenes.o \ + sound.o \ + staticres.o \ + tsage.o + +# This module can be built as a plugin +ifeq ($(ENABLE_TSAGE), DYNAMIC_PLUGIN) +PLUGIN := 1 +endif + +# Include common rules +include $(srcdir)/rules.mk + diff --git a/engines/tsage/resources.cpp b/engines/tsage/resources.cpp new file mode 100644 index 0000000000..c87c3eaf1e --- /dev/null +++ b/engines/tsage/resources.cpp @@ -0,0 +1,410 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/file.h" +#include "common/stack.h" +#include "common/util.h" +#include "tsage/resources.h" + +namespace tSage { + + +MemoryManager::MemoryManager() { + _memoryPool = new MemoryHeader*[MEMORY_POOL_SIZE]; + Common::set_to(&_memoryPool[0], &_memoryPool[MEMORY_POOL_SIZE], (MemoryHeader *)NULL); +} + +MemoryManager::~MemoryManager() { + for (int i = 0; i < MEMORY_POOL_SIZE; ++i) { + if (_memoryPool[i] != NULL) + free(_memoryPool[i]); + } + delete[] _memoryPool; +} + +uint16 MemoryManager::allocate(uint32 size) { + int idx = 0; + while ((idx < MEMORY_POOL_SIZE) && (_memoryPool[idx] != NULL)) + ++idx; + if (idx == MEMORY_POOL_SIZE) + error("Out of memory handles"); + + // Create the new entry + _memoryPool[idx] = (MemoryHeader *)malloc(sizeof(MemoryHeader) + size); + _memoryPool[idx]->id = MEMORY_ENTRY_ID; + _memoryPool[idx]->index = idx; + _memoryPool[idx]->lockCtr = 0; + _memoryPool[idx]->criticalCtr = 0; + _memoryPool[idx]->tag = 0; + _memoryPool[idx]->size = size; + + // Return it's index + return idx; +} + +byte *MemoryManager::allocate2(uint32 size) { + uint32 idx = allocate(size); + return lock(idx); +} + +byte *MemoryManager::lock(uint32 handle) { + assert((int)handle < MEMORY_POOL_SIZE); + return (byte *)_memoryPool[handle] + sizeof(MemoryHeader); +} + +int MemoryManager::indexOf(const byte *p) { + for (int idx = 0; idx < MEMORY_POOL_SIZE; ++idx) { + if (((byte *)_memoryPool[idx] + sizeof(MemoryHeader)) == p) + return idx; + } + + return -1; +} + +void MemoryManager::deallocate(const byte *p) { + if (!p) + return; + + int idx = indexOf(p); + assert(idx != -1); + if (_memoryPool[idx]->lockCtr-- == 0) { + free(_memoryPool[idx]); + _memoryPool[idx] = NULL; + } +} + +uint32 MemoryManager::getSize(const byte *p) { + int idx = indexOf(p); + assert(idx >= 0); + return _memoryPool[idx]->size; +} + +void MemoryManager::incLocks(const byte *p) { + int idx = indexOf(p); + assert(idx >= 0); + _memoryPool[idx]->lockCtr++; +} + +/*-------------------------------------------------------------------------*/ + +static uint16 bitMasks[4] = {0x1ff, 0x3ff, 0x7ff, 0xfff}; + +uint16 BitReader::readToken() { + assert((numBits >= 9) && (numBits <= 12)); + uint16 result = _remainder; + int bitsLeft = numBits - _bitsLeft; + int bitOffset = _bitsLeft; + _bitsLeft = 0; + + while (bitsLeft >= 0) { + _remainder = readByte(); + result |= _remainder << bitOffset; + bitsLeft -= 8; + bitOffset += 8; + } + + _bitsLeft = -bitsLeft; + _remainder >>= 8 - _bitsLeft; + return result & bitMasks[numBits - 9]; +} + +/*-------------------------------------------------------------------------*/ + +RlbManager::RlbManager(MemoryManager &memManager, const Common::String filename) : + _memoryManager(memManager) { + + // If the resource strings list isn't yet loaded, load them + if (_resStrings.size() == 0) { + Common::File f; + if (f.open("tsage.cfg")) { + while (!f.eos()) { + _resStrings.push_back(f.readLine()); + } + f.close(); + } + } + + if (!_file.open(filename)) + error("Missing file %s", filename.c_str()); + + loadIndex(); +} + +RlbManager::~RlbManager() { + _resStrings.clear(); +} + +void RlbManager::loadSection(uint32 fileOffset) { + _resources.clear(); + _file.seek(fileOffset); + _sections.fileOffset = fileOffset; + + if (_file.readUint32BE() != 0x544D492D) + error("Data block is not valid Rlb data"); + + /*uint8 unknown1 = */_file.readByte(); + uint16 numEntries = _file.readByte(); + + for (uint i = 0; i < numEntries; ++i) { + uint16 id = _file.readUint16LE(); + uint16 size = _file.readUint16LE(); + uint16 uncSize = _file.readUint16LE(); + uint8 sizeHi = _file.readByte(); + uint8 type = _file.readByte() >> 5; + assert(type <= 1); + uint32 offset = _file.readUint32LE(); + + ResourceEntry re; + re.id = id; + re.fileOffset = offset; + re.isCompressed = type != 0; + re.size = ((sizeHi & 0xF) << 16) | size; + re.uncompressedSize = ((sizeHi & 0xF0) << 12) | uncSize; + + _resources.push_back(re); + } +} + +struct DecodeReference { + uint16 vWord; + uint8 vByte; +}; + +/** + * Gets a resource from the currently loaded section + */ +byte *RlbManager::getResource(uint16 id, bool suppressErrors) { + // Scan for an entry for the given Id + ResourceEntry *re= NULL; + ResourceList::iterator i; + for (i = _resources.begin(); i != _resources.end(); ++i) { + if ((*i).id == id) { + re = &(*i); + break; + } + } + if (!re) { + if (suppressErrors) + return NULL; + error("Could not find resource Id #%d", id); + } + + if (!re->isCompressed) { + // Read in the resource data and return it + byte *dataP = _memoryManager.allocate2(re->size); + _file.seek(_sections.fileOffset + re->fileOffset); + _file.read(dataP, re->size); + + return dataP; + } + + /* + * Decompress the data block + */ + + _file.seek(_sections.fileOffset + re->fileOffset); + Common::ReadStream *compStream = _file.readStream(re->size); + BitReader bitReader(*compStream); + + byte *dataOut = _memoryManager.allocate2(re->uncompressedSize); + byte *destP = dataOut; + uint bytesWritten = 0; + + uint16 ctrCurrent = 0x102, ctrMax = 0x200; + uint16 word_48050 = 0, currentToken = 0, word_48054 =0; + byte byte_49068 = 0, byte_49069 = 0; + DecodeReference table[0x1000]; + Common::Stack<uint16> tokenList; + + for (;;) { + // Get the next decode token + uint16 token = bitReader.readToken(); + + // Handle the token + if (token == 0x101) { + // End of compressed stream + break; + } else if (token == 0x100) { + // Reset bit-rate + bitReader.numBits = 9; + ctrMax = 0x200; + ctrCurrent = 0x102; + + // Set variables with next token + currentToken = word_48050 = bitReader.readToken(); + byte_49069 = byte_49068 = (byte)currentToken; + + ++bytesWritten; + assert(bytesWritten <= re->uncompressedSize); + *destP++ = byte_49069; + } else { + word_48054 = word_48050 = token; + + if (token >= ctrCurrent) { + word_48050 = currentToken; + tokenList.push(byte_49068); + } + + while (word_48050 >= 0x100) { + assert(word_48050 < 0x1000); + tokenList.push(table[word_48050].vByte); + word_48050 = table[word_48050].vWord; + } + + byte_49069 = byte_49068 = (byte)word_48050; + tokenList.push(word_48050); + + // Write out any cached tokens + while (!tokenList.empty()) { + ++bytesWritten; + assert(bytesWritten <= re->uncompressedSize); + *destP++ = tokenList.pop(); + } + + assert(ctrCurrent < 0x1000); + table[ctrCurrent].vByte = byte_49069; + table[ctrCurrent].vWord = currentToken; + ++ctrCurrent; + + currentToken = word_48054; + if ((ctrCurrent >= ctrMax) && (bitReader.numBits != 12)) { + // Move to the next higher bit-rate + ++bitReader.numBits; + ctrMax <<= 1; + } + } + } + + assert(bytesWritten == re->uncompressedSize); + delete compStream; + return dataOut; +} + +/** + * Finds the correct section and loads the specified resource within it + */ +byte *RlbManager::getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors) { + SectionList::iterator i = _sections.begin(); + while ((i != _sections.end()) && ((*i).resType != resType || (*i).resNum != resNum)) + ++i; + if (i == _sections.end()) { + if (suppressErrors) + return NULL; + error("Unknown resource type %d num %d", resType, resNum); + } + + loadSection((*i).fileOffset); + + return getResource(rlbNum, suppressErrors); +} + +void RlbManager::loadIndex() { + uint16 resNum, configId, fileOffset; + + // Load the root resources section + loadSection(0); + + // Get the single resource from it + const byte *pData = getResource(0); + const byte *p = pData; + + _sections.clear(); + + // Loop through reading the entries + while ((resNum = READ_LE_UINT16(p)) != 0xffff) { + configId = READ_LE_UINT16(p + 2); + fileOffset = READ_LE_UINT16(p + 4); + p += 6; + + SectionEntry se; + se.resNum = resNum; + se.resType = (ResourceType)(configId & 0x1f); + se.fileOffset = (((configId >> 5) & 0x7ff) << 16) | fileOffset; + + _sections.push_back(se); + } + + _memoryManager.deallocate(pData); +} + +/** + * Retrieves the specified palette resource and returns it's data + * + * @paletteNum Specefies the palette number + */ +void RlbManager::getPalette(int paletteNum, RGB8 *palData, uint *startNum, uint *numEntries) { + // Get the specified palette + byte *dataIn = getResource(RES_PALETTE, 0, paletteNum); + assert(dataIn); + + *startNum = READ_LE_UINT16(dataIn); + *numEntries = READ_LE_UINT16(dataIn + 2); + RGB8 *srcPal = (RGB8 *)(dataIn + 6); + assert((*startNum < 256) && ((*startNum + *numEntries) <= 256)); + + // Copy over the data + Common::copy(&srcPal[0], &srcPal[*numEntries], palData); + + _memoryManager.deallocate(dataIn); +} + +byte *RlbManager::getSubResource(int resNum, int rlbNum, int index, uint *size) { + // Get the specified image set + byte *dataIn = getResource(RES_VISAGE, resNum, rlbNum); + assert(dataIn); + + int numEntries = READ_LE_UINT16(dataIn); + uint32 entryOffset = READ_LE_UINT32(dataIn + 2 + (index - 1) * 4); + uint32 nextOffset = (index == numEntries) ? + _memoryManager.getSize(dataIn) : READ_LE_UINT32(dataIn + 2 + index * 4); + *size = nextOffset - entryOffset; + assert(*size < (1024 * 1024)); + + byte *entry = _memoryManager.allocate2(*size); + Common::copy(&dataIn[entryOffset], &dataIn[nextOffset], entry); + + _memoryManager.deallocate(dataIn); + return entry; +} + +/** + * Retrieves a given message resource, and returns the specified message number + */ +Common::String RlbManager::getMessage(int resNum, int lineNum) { + byte *msgData = getResource(RES_MESSAGE, resNum, 0); + assert(msgData); + + const char *srcP = (const char *)msgData; + while (lineNum-- > 0) + srcP += strlen(srcP) + 1; + + Common::String result(srcP); + _memoryManager.deallocate(msgData); + return result; +} + +} // end of namespace tSage diff --git a/engines/tsage/resources.h b/engines/tsage/resources.h new file mode 100644 index 0000000000..1af1bb8d2f --- /dev/null +++ b/engines/tsage/resources.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef RING_RESOURCES_H +#define RING_RESOURCES_H + +#include "common/scummsys.h" +#include "common/file.h" +#include "common/list.h" +#include "common/str.h" +#include "common/str-array.h" +#include "common/util.h" +#include "graphics/surface.h" + +namespace tSage { + +// Magic number used by original game to identify valid memory blocks +const uint32 MEMORY_ENTRY_ID = 0xE11DA722; + +const int MEMORY_POOL_SIZE = 1000; + +enum ResourceType { RES_LIBRARY, RES_STRIP, RES_IMAGE, RES_PALETTE, RES_VISAGE, RES_SOUND, RES_MESSAGE, + RES_FONT, RES_POINTER, RES_BANK, RES_SND_DRIVER, RES_PRIORITY, RES_CONTROL, RES_WALKRGNS, + RES_BITMAP, RES_SAVE, RES_SEQUENCE }; + +#include "common/pack-start.h" // START STRUCT PACKING + +struct RGB8 { + uint8 r; + uint8 g; + uint8 b; +} PACKED_STRUCT; + +#include "common/pack-end.h" // END STRUCT PACKING + +class MemoryHeader { +public: + uint32 id; + int16 index; + int lockCtr; + int criticalCtr; + uint8 tag; + uint32 size; + + MemoryHeader() { + id = 0; + index = 0; + lockCtr = 0; + criticalCtr = 0; + tag = 0; + size = 0; + } +}; + +class SectionEntry { +public: + ResourceType resType; + uint16 resNum; + uint32 fileOffset; + + SectionEntry() { + resType = RES_LIBRARY; + resNum = 0; + fileOffset = 0; + } +}; + +class ResourceEntry { +public: + uint16 id; + bool isCompressed; + uint32 fileOffset; + uint32 size; + uint32 uncompressedSize; + + ResourceEntry() { + id = 0; + isCompressed = false; + fileOffset = 0; + size = 0; + uncompressedSize = 0; + } +}; + +typedef Common::List<ResourceEntry> ResourceList; + +class SectionList : public Common::List<SectionEntry> { +public: + uint32 fileOffset; + + SectionList() { + fileOffset = 0; + } +}; + +class MemoryManager { +private: + MemoryHeader **_memoryPool; +public: + MemoryManager(); + ~MemoryManager(); + + uint16 allocate(uint32 size); + byte *allocate2(uint32 size); + byte *lock(uint32 handle); + int indexOf(const byte *p); + void deallocate(const byte *p); + void deallocate(uint16 handle) { assert("TODO"); } + uint32 getSize(const byte *p); + void incLocks(const byte *p); +}; + +class BitReader { +private: + Common::ReadStream &_stream; + uint8 _remainder, _bitsLeft; + byte readByte() { return _stream.eos() ? 0 : _stream.readByte(); } +public: + BitReader(Common::ReadStream &s) : _stream(s) { + numBits = 9; + _remainder = 0; + _bitsLeft = 0; + } + uint16 readToken(); + + int numBits; +}; + +class RlbManager { +private: + Common::StringArray _resStrings; + MemoryManager &_memoryManager; +private: + Common::File _file; + ResourceList _resources; + SectionList _sections; + + void loadSection(uint32 fileOffset); + void loadIndex(); +public: + RlbManager(MemoryManager &memManager, const Common::String filename); + ~RlbManager(); + + byte *getResource(uint16 id, bool suppressErrors = false); + byte *getResource(ResourceType resType, uint16 resNum, uint16 rlbNum, bool suppressErrors = false); + void getPalette(int paletteNum, RGB8 *palData, uint *startNum, uint *numEntries); + byte *getSubResource(int resNum, int rlbNum, int index, uint *size); + Common::String getMessage(int resNum, int lineNum); +}; + + +} // end of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_logic.cpp b/engines/tsage/ringworld_logic.cpp new file mode 100644 index 0000000000..32f62bea76 --- /dev/null +++ b/engines/tsage/ringworld_logic.cpp @@ -0,0 +1,1162 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/ringworld_logic.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" +#include "tsage/ringworld_scenes1.h" +#include "tsage/ringworld_scenes2.h" +#include "tsage/ringworld_scenes3.h" +#include "tsage/ringworld_scenes4.h" +#include "tsage/ringworld_scenes5.h" +#include "tsage/ringworld_scenes6.h" +#include "tsage/ringworld_scenes8.h" +#include "tsage/ringworld_scenes10.h" + +namespace tSage { + +Scene *SceneFactory::createScene(int sceneNumber) { + switch (sceneNumber) { + /* Scene group 1 */ + // Kziniti Palace (Introduction) + case 10: return new Scene10(); + // Outer Space (Introduction) + case 15: return new Scene15(); + // Cut-scenes for Ch'mee house in distance + case 20: return new Scene20(); + // Outside Ch'mee residence + case 30: return new Scene30(); + // Chmeee Home + case 40: return new Scene40(); + // By Flycycles + case 50: return new Scene50(); + // Flycycle controls + case 60: return new Scene60(); + // Shipyard Entrance + case 90: return new Scene90(); + // Ship Close-up + case 95: return new Scene95(); + // Sunflower navigation sequence + case 6100: return new Scene6100(); + + /* Scene group 2 */ + // Title screen + case 1000: return new Scene1000(); + // Fleeing planet cutscene + case 1001: return new Scene1001(); + // Unused + case 1250: return new Scene1250(); + // Ringworld Wall + case 1400: return new Scene1400(); + // Ringworld Space-port + case 1500: return new Scene1500(); + + /* Scene group 3 - Part #1 */ + // Cockpit cutscenes + case 2000: return new Scene2000(); + // Starcraft - Cockpit + case 2100: return new Scene2100(); + // Encyclopedia + case 2120: return new Scene2120(); + // Starcraft - Level 2 + case 2150: return new Scene2150(); + // Starcraft - AutoDoc + case 2200: return new Scene2200(); + // Stasis Field Map + case 2222: return new Scene2222(); + // Starcraft - Quinn's Room + case 2230: return new Scene2230(); + + /* Scene group 3 - Part #2 */ + // Starcraft - Storage Room + case 2280: return new Scene2280(); + // Starcraft - Hanger Bay + case 2300: return new Scene2300(); + // Starcraft - Copy Protection Screen + case 2310: return new Scene2310(); + // Starcraft - Lander Bay + case 2320: return new Scene2320(); + // Scene 2400 - Descending in Lander + case 2400: return new Scene2400(); + + /* Scene group 4 */ + // Ringworld Scan + case 3500: return new Scene3500(); + // Remote Viewer + case 3700: return new Scene3700(); + + /* Scene group 5 */ + // Village + case 4000: return new Scene4000(); + // Village - Outside Lander + case 4010: return new Scene4010(); + // Village - Puzzle Board + case 4025: return new Scene4025(); + // Village - Temple Antechamber + case 4045: return new Scene4045(); + // Village - Temple + case 4050: return new Scene4050(); + // Village - Hut + case 4100: return new Scene4100(); + // Village - Bedroom + case 4150: return new Scene4150(); + // Village - Near Slaver Ship + case 4250: return new Scene4250(); + // Village - Slaver Ship + case 4300: return new Scene4300(); + // Village - Slaver Ship Keypad + case 4301: return new Scene4301(); + + /* Scene group 6 */ + // Caverns - Entrance + case 5000: return new Scene5000(); + // Caverns + case 5100: return new Scene5100(); + // Caverns - Throne-room + case 5200: return new Scene5200(); + // Caverns - Pit + case 5300: return new Scene5300(); + + /* Scene group 8 */ + // Scene 7000: Landing + case 7000: return new Scene7000(); + // Scene 7100: swimming under water + case 7100: return new Scene7100(); + // Scene 7200: Entering the underwater cave + case 7200: return new Scene7200(); + // Scene 7300: Discussion with Lord Poria + case 7300: return new Scene7300(); + case 7600: return new Scene7600(); + case 7700: return new Scene7700(); + + /* Scene group 10 */ + case 9100: return new Scene9100(); + case 9150: return new Scene9150(); + case 9200: return new Scene9200(); + case 9300: return new Scene9300(); + case 9350: return new Scene9350(); + case 9360: return new Scene9360(); + case 9400: return new Scene9400(); + case 9450: return new Scene9450(); + case 9500: return new Scene9500(); + case 9700: return new Scene9700(); + case 9750: return new Scene9750(); + case 9850: return new Scene9850(); + // Scene 9900: Ending + case 9900: return new Scene9900(); + case 9999: return new Scene9999(); + + default: + error("Unknown scene number - %d", sceneNumber); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +DisplayHotspot::DisplayHotspot(int regionId, ...) { + _sceneRegionId = regionId; + + // Load up the actions + va_list va; + va_start(va, regionId); + + int param = va_arg(va, int); + while (param != LIST_END) { + _actions.push_back(param); + param = va_arg(va, int); + } + + va_end(va); +} + +bool DisplayHotspot::performAction(int action) { + for (uint i = 0; i < _actions.size(); i += 3) { + if (_actions[i] == action) { + display(_actions[i + 1], _actions[i + 2], SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + return true; + } + } + + return false; +} + +/*--------------------------------------------------------------------------*/ + +DisplayObject::DisplayObject(int firstAction, ...) { + // Load up the actions + va_list va; + va_start(va, firstAction); + + int param = firstAction; + while (param != LIST_END) { + _actions.push_back(param); + param = va_arg(va, int); + } + + va_end(va); +} + +bool DisplayObject::performAction(int action) { + for (uint i = 0; i < _actions.size(); i += 3) { + if (_actions[i] == action) { + display(_actions[i + 1], _actions[i + 2], SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + return true; + } + } + + return false; +} + +/*--------------------------------------------------------------------------*/ + +SceneArea::SceneArea() { + _savedArea = NULL; + _pt.x = _pt.y = 0; +} + +SceneArea::~SceneArea() { + delete _savedArea; +} + +void SceneArea::setup(int resNum, int rlbNum, int subNum, int actionId) { + _resNum = resNum; + _rlbNum = rlbNum; + _subNum = subNum; + _actionId = actionId; + + _surface = surfaceFromRes(resNum, rlbNum, subNum); +} + +void SceneArea::draw2() { + _surface.draw(Common::Point(_bounds.left, _bounds.top)); +} + +void SceneArea::display() { + _bounds.left = _pt.x - (_surface.getBounds().width() / 2); + _bounds.top = _pt.y + 1 - _surface.getBounds().height(); + _bounds.setWidth(_surface.getBounds().width()); + _bounds.setHeight(_surface.getBounds().height()); + + _savedArea = Surface_getArea(_globals->_gfxManagerInstance.getSurface(), _bounds); + draw2(); +} + +void SceneArea::restore() { + assert(_savedArea); + _savedArea->draw(Common::Point(_bounds.left, _bounds.top)); + delete _savedArea; + _savedArea = NULL; +} + +void SceneArea::draw(bool flag) { + _surface = surfaceFromRes(_resNum, _rlbNum, flag ? _subNum + 1 : _subNum); + _surface.draw(Common::Point(_bounds.left, _bounds.top)); +} + +void SceneArea::wait() { + // Wait until a mouse or keypress + Event event; + while (!_vm->getEventManager()->shouldQuit() && !_globals->_events.getEvent(event)) { + g_system->updateScreen(); + g_system->delayMillis(10); + } + + SynchronisedList<SceneItem *>::iterator ii; + for (ii = _globals->_sceneItems.begin(); ii != _globals->_sceneItems.end(); ++ii) { + SceneItem *sceneItem = *ii; + if (sceneItem->contains(event.mousePos)) { + sceneItem->doAction(_actionId); + break; + } + } + + _globals->_events.setCursor(CURSOR_ARROW); +} + +void SceneArea::synchronise(Serialiser &s) { + s.syncAsSint16LE(_pt.x); + s.syncAsSint16LE(_pt.y); + s.syncAsSint32LE(_resNum); + s.syncAsSint32LE(_rlbNum); + s.syncAsSint32LE(_subNum); + s.syncAsSint32LE(_actionId); + _bounds.synchronise(s); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerGText::SpeakerGText() { + _speakerName = "GTEXT"; + _textWidth = 160; + _textPos = Common::Point(130, 10); + _colour1 = 42; + _hideObjects = false; +} + +void SpeakerGText::setText(const Common::String &msg) { + // Set the animation properties + _sceneObject.postInit(); + _sceneObject.setVisage(9405); + _sceneObject.setStrip2(3); + _sceneObject.setPriority2(255); + _sceneObject.changeZoom(100); + _sceneObject._frame = 1; + _sceneObject.setPosition(Common::Point(183, 71)); + _sceneObject.animate(ANIM_MODE_7, 0, NULL); + + // Set the text + Rect textRect; + _globals->gfxManager()._font.getStringBounds(msg.c_str(), textRect, _textWidth); + textRect.centre(_sceneObject._position.x, _sceneObject._position.y); + _textPos.x = textRect.left; + Speaker::setText(msg); +} + +void SpeakerGText::removeText() { + _sceneObject.remove(); + Speaker::removeText(); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerPOR::SpeakerPOR() { + _speakerName = "POR"; + _newSceneNumber = 7221; + _textPos = Common::Point(10, 30); + _colour1 = 41; +} + +void SpeakerPOR::SpeakerAction1::signal(){ + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(60) + 60); + break; + case 1: + static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_5, this, NULL); + break; + case 2: + setDelay(_globals->_randomSource.getRandomNumber(10)); + _actionIndex = 0; + break; + default: + break; + } +} + +void SpeakerPOR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(7223); + _object1.setStrip2(2); + _object1.setPosition(Common::Point(191, 166), 0); + _object1.animate(ANIM_MODE_7, 0, 0); + + _object2.postInit(&_objectList); + _object2.setVisage(7223); + _object2.setPosition(Common::Point(159, 86), 0); + _object2.setAction(&_speakerAction, 0); + + _object3.postInit(&_objectList); + _object3.setVisage(7223); + _object3.setStrip(3); + _object3.setPosition(Common::Point(119, 107), 0); + _object3.setPriority2(199); + _object3.setAction(&_action2); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerOR::SpeakerOR() { + _speakerName = "OR"; + _newSceneNumber = 9430; + _textPos = Common::Point(8, 36); + _colour1 = 42; + _textWidth = 136; +} + +void SpeakerOR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(9431); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(202, 147), 0); + _object1.animate(ANIM_MODE_7, 0, 0); + + _object2.postInit(&_objectList); + _object2.setVisage(9431); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.setZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(199, 85), 0); + _object2.setAction(&_speakerAction, 0); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerOText::SpeakerOText() : SpeakerGText() { + _speakerName = "OTEXT"; + _textWidth = 240; + _textPos = Common::Point(130, 10); + _colour1 = 42; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerQText::SpeakerQText() : ScreenSpeaker() { + _speakerName = "QTEXT"; + _textPos = Common::Point(160, 40); + _colour1 = 35; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSText::SpeakerSText() : ScreenSpeaker() { + _speakerName = "STEXT"; + _colour1 = 13; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerPOText::SpeakerPOText() : ScreenSpeaker() { + _speakerName = "POTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 41; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerMText::SpeakerMText() { + _speakerName = "MTEXT"; + _colour1 = 11; + _textWidth = 160; + _textMode = ALIGN_CENTRE; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCText::SpeakerCText() { + _speakerName = "CTEXT"; + _colour1 = 4; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerEText::SpeakerEText() { + _speakerName = "ETEXT"; + _textPos = Common::Point(20, 20); + _colour1 = 22; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerGR::SpeakerGR() { + _speakerName = "GR"; + _newSceneNumber = 9220; + _textWidth = 136; + _textPos = Common::Point(168, 36); + _colour1 = 14; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerHText::SpeakerHText() { + _speakerName = "HTEXT"; + _textPos = Common::Point(160, 40); + _colour1 = 52; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSKText::SpeakerSKText() : ScreenSpeaker() { + _speakerName = "SKTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 5; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerPText::SpeakerPText() { + _speakerName = "PTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 5; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCHFText::SpeakerCHFText() { + _speakerName = "CHFTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 56; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCDRText::SpeakerCDRText() { + _speakerName = "CDRTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 52; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerFLText::SpeakerFLText() { + _speakerName = "FLTEXT"; + _textPos = Common::Point(10, 40); + _colour1 = 17; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerBatText::SpeakerBatText() { + _speakerName = "BATTEXT"; + _textWidth = 240; + _textMode = ALIGN_CENTRE; + _colour1 = 3; + _hideObjects = false; +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSKL::SpeakerSKL() : AnimatedSpeaker() { + _speakerName = "SKL"; + _newSceneNumber = 7011; + _textPos = Common::Point(10, 30); + _colour1 = 10; +} + +void SpeakerSKL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(7013); + _object1.setStrip2(2); + _object1._frame = 1; + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1.setPosition(Common::Point(203, 120)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(7013); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(197, 80)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerQL::SpeakerQL() : AnimatedSpeaker() { + _speakerName = "QL"; + _newSceneNumber = 2610; + _textPos = Common::Point(160, 30); + _colour1 = 35; + _textMode = ALIGN_CENTRE; +} + +void SpeakerQL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2612); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(128, 146)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2612); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(122, 84)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSR::SpeakerSR() { + _speakerName = "SR"; + _newSceneNumber = 2811; + _textPos = Common::Point(10, 30); + _colour1 = 13; + _textMode = ALIGN_CENTRE; +} + +void SpeakerSR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2813); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(224, 198)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2813); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(203, 96)); + _object2.setAction(&_speakerAction, NULL); + + _object3.postInit(&_objectList); + _object3.setVisage(2813); + _object3.setStrip(3); + _object3.setPosition(Common::Point(204, 91)); + _object3.setPriority2(199); + _object3._numFrames = 3; + _object3.animate(ANIM_MODE_7, 0, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSL::SpeakerSL() { + _speakerName = "SL"; + _newSceneNumber = 2810; + _textPos = Common::Point(140, 30); + _textWidth = 160; + _colour1 = 13; + _textMode = ALIGN_CENTRE; +} + +void SpeakerSL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2812); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(95, 198)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2812); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(116, 96)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerQR::SpeakerQR() { + _speakerName = "QR"; + _newSceneNumber = 2611; + _textPos = Common::Point(10, 30); + _colour1 = 13; + _textMode = ALIGN_CENTRE; +} + +void SpeakerQR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2613); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(191, 146)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2613); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(197, 84)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerQU::SpeakerQU() { + _speakerName = "QU"; + _newSceneNumber = 7020; + _textPos = Common::Point(160, 30); + _colour1 = 35; + _textMode = ALIGN_CENTRE; +} + +void SpeakerQU::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(7021); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(116, 120), 0); + _object1.animate(ANIM_MODE_7, 0, 0); + + _object2.postInit(&_objectList); + _object2.setVisage(7021); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(111, 84), 0); + _object2.setAction(&_speakerAction, 0); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCR::SpeakerCR() { + _speakerName = "CR"; + _newSceneNumber = 9010; + _textPos = Common::Point(20, 40); + _colour1 = 4; +} + +void SpeakerCR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(9011); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.setPosition(Common::Point(219, 168)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(9011); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.setPosition(Common::Point(232, 81)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerMR::SpeakerMR() { + _speakerName = "MR"; + _newSceneNumber = 2711; + _textPos = Common::Point(40, 10); + _colour1 = 22; +} + +void SpeakerMR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2713); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(220, 143)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2713); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setPosition(Common::Point(215, 99)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerSAL::SpeakerSAL() { + _speakerName = "SAL"; + _newSceneNumber = 2851; + _textPos = Common::Point(10, 30); + _colour1 = 13; + _textMode = ALIGN_CENTRE; +} + +void SpeakerSAL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2853); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(185, 200)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2853); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setPosition(Common::Point(170, 92)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerML::SpeakerML() { + _speakerName = "ML"; + _newSceneNumber = 2710; + _textPos = Common::Point(160, 40); + _colour1 = 22; +} + +void SpeakerML::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(2712); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(99, 143)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(2712); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setPosition(Common::Point(105, 99)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCHFL::SpeakerCHFL() { + _speakerName = "CHFL"; + _newSceneNumber = 4111; + _textPos = Common::Point(10, 40); + _colour1 = 56; +} + +void SpeakerCHFL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4113); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(205, 116)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4113); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setPosition(Common::Point(202, 71)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCHFR::SpeakerCHFR() { + _speakerName = "CHFR"; + _newSceneNumber = 4110; + _textPos = Common::Point(160, 40); + _colour1 = 56; +} + +void SpeakerCHFR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4112); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(103, 116)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4112); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setPosition(Common::Point(106, 71)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerPL::SpeakerPL() { + _speakerName = "PL"; + _newSceneNumber = 4060; + _textPos = Common::Point(160, 40); + _colour1 = 5; +} + +void SpeakerPL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4062); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(107, 117)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4062); + _object2.setStrip2(1); + _object2.setPriority2(200); + _object2._frame = 1; + _object2.setPosition(Common::Point(105, 62)); + _object2.setAction(&_speakerAction, NULL); + + _object3.postInit(&_objectList); + _object3.setVisage(4062); + _object3.setStrip2(3); + _object3.setPriority2(255); + _object3._frame = 1; + _object3.setPosition(Common::Point(105, 59)); + _object3.setAction(&_speakerAction2, NULL); + + Speaker::setText(msg); +} + +void SpeakerPL::removeText() { + _object3.remove(); + AnimatedSpeaker::removeText(); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerPR::SpeakerPR() { + _speakerName = "PR"; + _newSceneNumber = 4061; + _textPos = Common::Point(10, 40); + _colour1 = 5; +} + +void SpeakerPR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4063); + _object1.setStrip2(1); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(212, 117)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4063); + _object2.setStrip2(2); + _object2.setPriority2(200); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(214, 62)); + _object2.setAction(&_speakerAction, NULL); + + _object3.postInit(&_objectList); + _object3.setVisage(4063); + _object3.setStrip2(3); + _object3.setPriority2(255); + _object3.changeZoom(100); + _object3._frame = 1; + _object3.setPosition(Common::Point(214, 59)); + _object3.setAction(&_speakerAction2, NULL); + + Speaker::setText(msg); +} + +void SpeakerPR::removeText() { + _object3.remove(); + AnimatedSpeaker::removeText(); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCDR::SpeakerCDR() { + _speakerName = "CDR"; + _newSceneNumber = 4161; + _textPos = Common::Point(10, 40); + _colour1 = 52; +} + +void SpeakerCDR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4163); + _object1.setStrip2(1); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(208, 97)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4163); + _object2.setStrip2(2); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(200, 57)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerCDL::SpeakerCDL() { + _speakerName = "CDL"; + _newSceneNumber = 4160; + _textPos = Common::Point(160, 40); + _colour1 = 52; +} + +void SpeakerCDL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(4162); + _object1.setStrip2(1); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(112, 97)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(4162); + _object2.setStrip2(2); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(115, 57)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerFLL::SpeakerFLL() { + _speakerName = "FLL"; + _newSceneNumber = 5221; + _textPos = Common::Point(10, 40); + _colour1 = 17; +} + +void SpeakerFLL::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(5223); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(216, 129)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(5223); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(210, 67)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +/*--------------------------------------------------------------------------*/ + +SpeakerBatR::SpeakerBatR() { + _speakerName = "BATR"; + _newSceneNumber = 5360; + _textPos = Common::Point(140, 40); + _colour1 = 3; +} + +void SpeakerBatR::setText(const Common::String &msg) { + _object1.postInit(&_objectList); + _object1.setVisage(5361); + _object1.setStrip2(2); + _object1.setPriority2(255); + _object1.changeZoom(100); + _object1._frame = 1; + _object1.setPosition(Common::Point(137, 122)); + _object1.animate(ANIM_MODE_7, 0, NULL); + + _object2.postInit(&_objectList); + _object2.setVisage(5361); + _object2.setStrip2(1); + _object2.setPriority2(255); + _object2.changeZoom(100); + _object2._frame = 1; + _object2.setPosition(Common::Point(137, 104)); + _object2.setAction(&_speakerAction, NULL); + + Speaker::setText(msg); +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_logic.h b/engines/tsage/ringworld_logic.h new file mode 100644 index 0000000000..66c7bff912 --- /dev/null +++ b/engines/tsage/ringworld_logic.h @@ -0,0 +1,402 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_LOGIC_H +#define TSAGE_RINGWORLD_LOGIC_H + +#include "common/scummsys.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +#define ADD_PLAYER_MOVER(X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \ + _globals->_player.addMover(mover, &pt, this); } +#define ADD_PLAYER_MOVER_NULL(OBJ, X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \ + OBJ.addMover(mover, &pt, NULL); } +#define ADD_PLAYER_MOVER_THIS(OBJ, X, Y) { Common::Point pt(X, Y); PlayerMover *mover = new PlayerMover(); \ + OBJ.addMover(mover, &pt, this); } + +#define ADD_MOVER(OBJ, X, Y) { Common::Point pt(X, Y); NpcMover *mover = new NpcMover(); \ + OBJ.addMover(mover, &pt, this); } +#define ADD_MOVER_NULL(OBJ, X, Y) { Common::Point pt(X, Y); NpcMover *mover = new NpcMover(); \ + OBJ.addMover(mover, &pt, NULL); } + + +class SceneFactory { +public: + static Scene *createScene(int sceneNumber); +}; + +class DisplayHotspot : public SceneObject { +private: + Common::Array<int> _actions; + bool performAction(int action); +public: + DisplayHotspot(int regionId, ...); + + virtual void doAction(int action) { + if (!performAction(action)) + SceneHotspot::doAction(action); + } +}; + +class DisplayObject : public SceneObject { +private: + Common::Array<int> _actions; + bool performAction(int action); +public: + DisplayObject(int firstAction, ...); + + virtual void doAction(int action) { + if (!performAction(action)) + SceneHotspot::doAction(action); + } +}; + +class SceneArea : public SavedObject { +public: + GfxSurface _surface; + GfxSurface *_savedArea; + Common::Point _pt; + int _resNum; + int _rlbNum; + int _subNum; + int _actionId; + Rect _bounds; +public: + SceneArea(); + ~SceneArea(); + + void setup(int resNum, int rlbNum, int subNum, int actionId); + void draw2(); + void display(); + void restore(); + + virtual void synchronise(Serialiser &s); + virtual void draw(bool flag); + virtual void wait(); +}; + +/*--------------------------------------------------------------------------*/ +// Ringworld specific game speakers + +class SpeakerGText : public Speaker { +public: + SceneObject _sceneObject; +public: + SpeakerGText(); + + virtual Common::String getClassName() { return "SpeakerGText"; } + virtual void setText(const Common::String &msg); + virtual void removeText(); +}; + +class SpeakerPOR : public AnimatedSpeaker { + class SpeakerAction1 : public SpeakerAction { + public: + virtual void signal(); + }; + +public: + SceneObject _object3; + SpeakerAction1 _action2; +public: + SpeakerPOR(); + virtual Common::String getClassName() { return "SpeakerPOR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerOR : public AnimatedSpeaker { +public: + SpeakerOR(); + virtual Common::String getClassName() { return "SpeakerOR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerOText : public SpeakerGText { +public: + SpeakerOText(); + + virtual Common::String getClassName() { return "SpeakerOText"; } +}; + +class SpeakerPOText : public ScreenSpeaker { +public: + SpeakerPOText(); + + virtual Common::String getClassName() { return "SpeakerPOText"; } +}; + +class SpeakerSText : public ScreenSpeaker { +public: + SpeakerSText(); + + virtual Common::String getClassName() { return "SpeakerSText"; } +}; + +class SpeakerQText : public ScreenSpeaker { +public: + SpeakerQText(); + + virtual Common::String getClassName() { return "SpeakerQText"; } +}; + +class SpeakerMText : public ScreenSpeaker { +public: + SpeakerMText(); + + virtual Common::String getClassName() { return "SpeakerMText"; } +}; + +class SpeakerCText : public ScreenSpeaker { +public: + SpeakerCText(); + + virtual Common::String getClassName() { return "SpeakerCText"; } +}; + +class SpeakerEText : public ScreenSpeaker { +public: + SpeakerEText(); + + virtual Common::String getClassName() { return "SpeakerEText"; } +}; + +class SpeakerGR : public AnimatedSpeaker { +public: + SpeakerGR(); + + virtual Common::String getClassName() { return "SpeakerGR"; } +}; + +class SpeakerHText : public ScreenSpeaker { +public: + SpeakerHText(); + + virtual Common::String getClassName() { return "SpeakerHText"; } +}; + +class SpeakerPText : public ScreenSpeaker { +public: + SpeakerPText(); + + virtual Common::String getClassName() { return "SpeakerPText"; } +}; + +class SpeakerCHFText : public ScreenSpeaker { +public: + SpeakerCHFText(); + + virtual Common::String getClassName() { return "SpeakerCHFText"; } +}; + +class SpeakerSKText : public ScreenSpeaker { +public: + SpeakerSKText(); + + virtual Common::String getClassName() { return "SpeakerSKText"; } +}; + +class SpeakerCDRText : public ScreenSpeaker { +public: + SpeakerCDRText(); + + virtual Common::String getClassName() { return "SpeakerCDRText"; } +}; + +class SpeakerFLText : public ScreenSpeaker { +public: + SpeakerFLText(); + + virtual Common::String getClassName() { return "SpeakerFLText"; } +}; + +class SpeakerBatText : public ScreenSpeaker { +public: + SpeakerBatText(); + + virtual Common::String getClassName() { return "SpeakerFLText"; } +}; + +class SpeakerQR : public AnimatedSpeaker { +public: + SpeakerQR(); + + virtual Common::String getClassName() { return "SpeakerQR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerQU : public AnimatedSpeaker { +public: + SpeakerQU(); + + virtual Common::String getClassName() { return "SpeakerQU"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerSKL : public AnimatedSpeaker { +public: + SpeakerSKL(); + + virtual Common::String getClassName() { return "SpeakerQL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerQL : public AnimatedSpeaker { +public: + SpeakerQL(); + + virtual Common::String getClassName() { return "SpeakerQL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerSR : public AnimatedSpeaker { +public: + SceneObject _object3; +public: + SpeakerSR(); + + virtual Common::String getClassName() { return "SpeakerSR"; } + void setText(const Common::String &msg); +}; + +class SpeakerSL : public AnimatedSpeaker { +public: + SpeakerSL(); + + virtual Common::String getClassName() { return "SpeakerSL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerCR : public AnimatedSpeaker { +public: + SpeakerCR(); + + virtual Common::String getClassName() { return "SpeakerCR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerMR : public AnimatedSpeaker { +public: + SpeakerMR(); + + virtual Common::String getClassName() { return "SpeakerMR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerSAL : public AnimatedSpeaker { +public: + SpeakerSAL(); + + virtual Common::String getClassName() { return "SpeakerSAL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerML : public AnimatedSpeaker { +public: + SpeakerML(); + + virtual Common::String getClassName() { return "SpeakerML"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerCHFL : public AnimatedSpeaker { +public: + SpeakerCHFL(); + + virtual Common::String getClassName() { return "SpeakerCHFL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerCHFR : public AnimatedSpeaker { +public: + SpeakerCHFR(); + + virtual Common::String getClassName() { return "SpeakerCHFR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerPL : public AnimatedSpeaker { +public: + SceneObject _object3; + SpeakerAction _speakerAction2; + + SpeakerPL(); + + virtual Common::String getClassName() { return "SpeakerPL"; } + virtual void setText(const Common::String &msg); + virtual void removeText(); +}; + +class SpeakerPR : public AnimatedSpeaker { +public: + SceneObject _object3; + SpeakerAction _speakerAction2; + + SpeakerPR(); + + virtual Common::String getClassName() { return "SpeakerPR"; } + virtual void setText(const Common::String &msg); + virtual void removeText(); +}; + +class SpeakerCDR : public AnimatedSpeaker { +public: + SpeakerCDR(); + + virtual Common::String getClassName() { return "SpeakerCDR"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerCDL : public AnimatedSpeaker { +public: + SpeakerCDL(); + + virtual Common::String getClassName() { return "SpeakerCDL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerFLL : public AnimatedSpeaker { +public: + SpeakerFLL(); + + virtual Common::String getClassName() { return "SpeakerFLL"; } + virtual void setText(const Common::String &msg); +}; + +class SpeakerBatR : public AnimatedSpeaker { +public: + SpeakerBatR(); + + virtual Common::String getClassName() { return "SpeakerBatR"; } + virtual void setText(const Common::String &msg); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes1.cpp b/engines/tsage/ringworld_scenes1.cpp new file mode 100644 index 0000000000..4497d6af75 --- /dev/null +++ b/engines/tsage/ringworld_scenes1.cpp @@ -0,0 +1,3263 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/ringworld_scenes1.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 10 - Kziniti Palace (Introduction) + * + *--------------------------------------------------------------------------*/ + +void Scene10::Action1::signal() { + Scene10 *scene = (Scene10 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: + _globals->_scenePalette.addRotation(240, 254, -1); + scene->_stripManager.start(10, this); + break; + case 2: + scene->_speakerSText.setTextPos(Common::Point(20, 20)); + scene->_speakerSText._colour1 = 10; + scene->_speakerSText._textWidth = 160; + scene->_stripManager.start(11, this, scene); + break; + case 3: + scene->_object2.hide(); + scene->_object3.hide(); + scene->_object3.setAction(NULL); + scene->_object4.animate(ANIM_MODE_5, this); + break; + case 4: + case 9: + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 5: + scene->_object2.setStrip(3); + scene->_object2.setFrame(1); + scene->_object2.setPosition(Common::Point(240, 51)); + scene->_object2.show(); + + scene->_object3.setStrip(6); + scene->_object3.setFrame(1); + scene->_object3.setPosition(Common::Point(200, 76)); + scene->_object3._numFrames = 20; + scene->_object3.show(); + + scene->_stripManager.start(12, this, scene); + break; + case 6: + scene->_object2.hide(); + scene->_object3.hide(); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 7: + scene->_object3.show(); + scene->_object3.setStrip2(5); + scene->_object3._numFrames = 10; + scene->_object3.setPosition(Common::Point(180, 87)); + scene->_object3.setAction(&scene->_action2); + + scene->_object2.setStrip(4); + scene->_object2.setFrame(1); + scene->_object2.setPosition(Common::Point(204, 59)); + scene->_object2.show(); + + scene->_stripManager.start(13, this, scene); + break; + case 8: + scene->_object2.hide(); + scene->_object3.hide(); + scene->_object4.animate(ANIM_MODE_6, this); + break; + case 10: + _globals->_soundHandler.proc1(this); + break; + case 11: + _globals->_scenePalette.clearListeners(); + _globals->_sceneManager.changeScene(15); + break; + } +} + +void Scene10::Action2::signal() { + Scene10 *scene = (Scene10 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(179)); + break; + case 1: + scene->_object3.setFrame(1); + scene->_object3.animate(ANIM_MODE_5, this); + _actionIndex = 0; + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene10::postInit(SceneObjectList *OwnerList) { + loadScene(10); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerQText); + _speakerSText._speakerName = "STEXT"; + _speakerQText._speakerName = "QTEXT"; + _speakerSText._hideObjects = false; + _speakerQText._hideObjects = false; + _speakerQText.setTextPos(Common::Point(140, 120)); + _speakerQText._colour1 = 4; + _speakerQText._textWidth = 160; + _speakerSText.setTextPos(Common::Point(20, 20)); + _speakerSText._colour1 = 7; + _speakerSText._textWidth = 320; + + _stripManager.setCallback(this); + + _object1.postInit(); + _object1.setVisage(10); + _object1.setPosition(Common::Point(232, 90)); + _object1.setPriority2(1); + + _object2.postInit(); + _object2.setVisage(10); + _object2.setStrip(4); + _object2.setFrame(1); + _object2.setPosition(Common::Point(204, 59)); + _object2.setPriority2(198); + + _object3.postInit(); + _object3.setVisage(10); + _object3.setStrip2(5); + _object3.setPosition(Common::Point(180, 87)); + _object3.setPriority2(196); + _object3.setAction(&_action2); + + _object4.postInit(); + _object4.setVisage(10); + _object4.setStrip(2); + _object4.setPosition(Common::Point(0, 209)); + _object4.animate(ANIM_MODE_1, NULL); + + _object5.postInit(); + _object5.setVisage(11); + _object5.setPosition(Common::Point(107, 146)); + _object5.animate(ANIM_MODE_2, NULL); + _object5._numFrames = 5; + + _object6.postInit(); + _object6.setVisage(11); + _object6.setStrip(2); + _object6.setPosition(Common::Point(287, 149)); + _object6.animate(ANIM_MODE_2, NULL); + _object6._numFrames = 5; + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + + setAction(&_action1); + _globals->_soundHandler.startSound(5); +} + +void Scene10::stripCallback(int v) { + switch (v) { + case 1: + _object2.animate(ANIM_MODE_7, -1, NULL); + break; + case 2: + _object2.animate(ANIM_MODE_NONE); + break; + case 3: + _object2.animate(ANIM_MODE_7, -1, NULL); + _object3.animate(ANIM_MODE_5, NULL); + break; + default: + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 15 - Outer Space (Introduction) + * + *--------------------------------------------------------------------------*/ + +void Scene15::Action1::signal() { + Scene15 *scene = (Scene15 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + SceneItem::display(15, 0, SET_Y, 20, SET_FONT, 2, SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 7, + SET_WIDTH, 320, SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(300); + break; + case 2: { + SceneItem::display(15, 1, SET_Y, 20, SET_FONT, 2, SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 7, + SET_WIDTH, 320, SET_KEEP_ONSCREEN, 1, LIST_END); + scene->_object1.postInit(); + scene->_object1.setVisage(15); + scene->_object1.setPosition(Common::Point(160, -10)); + scene->_object1.animate(ANIM_MODE_2, NULL); + Common::Point pt(160, 100); + NpcMover *mover = new NpcMover(); + scene->_object1.addMover(mover, &pt, this); + scene->_soundHandler.startSound(7); + break; + } + case 3: + SceneItem::display(0, 0); + _globals->_sceneManager.changeScene(20); + break; + } +} + +void Scene15::Action1::dispatch() { + Scene15 *scene = (Scene15 *)_globals->_sceneManager._scene; + + if (scene->_object1._position.y < 100) + scene->_object1.changeZoom(100 - scene->_object1._position.y); + Action::dispatch(); +} + +/*--------------------------------------------------------------------------*/ + +void Scene15::postInit(SceneObjectList *OwnerList) { + loadScene(15); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + _globals->_soundHandler.startSound(6); + setAction(&_action1); +} + +/*-------------------------------------------------------------------------- + * Scene 20 - Cut-scenes where House Chmeee is in the distance + * + *--------------------------------------------------------------------------*/ + +void Scene20::Action1::signal() { + Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(120); + break; + case 1: + scene->_stripManager.start(20, this); + break; + case 2: + _globals->_soundHandler.proc1(this); + break; + case 3: + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_sceneManager.changeScene(30); // First game scene + break; + default: + break; + } +} + +void Scene20::Action2::signal() { + Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene; + NpcMover *npcMover; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + SceneItem::display(20, 1, SET_WIDTH, 200, SET_Y, 20, SET_X, 160, SET_KEEP_ONSCREEN, true, + SET_EXT_BGCOLOUR, 4, LIST_END); + setDelay(120); + break; + case 2: { + NpcMover *mover = new NpcMover(); + Common::Point pt(455, 77); + _globals->_player.addMover(mover, &pt, this); + ObjectMover2 *mover2 = new ObjectMover2(); + scene->_SceneObjectExt.addMover(mover2, 5, 10, &_globals->_player); + ObjectMover2 *mover3 = new ObjectMover2(); + scene->_sceneObject3.addMover(mover3, 10, 15, &_globals->_player); + break; + } + case 3: { + npcMover = new NpcMover(); + Common::Point pt(557, 100); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 4: { + npcMover = new NpcMover(); + Common::Point pt(602, 90); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 5: { + npcMover = new NpcMover(); + Common::Point pt(618, 90); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 6: { + npcMover = new NpcMover(); + Common::Point pt(615, 81); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 7: { + npcMover = new NpcMover(); + Common::Point pt(588, 79); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 8: + scene->_sound.proc4(); + scene->_sound.proc1(this); + break; + case 9: + SceneItem::display(0, 0, LIST_END); + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_sceneManager.changeScene(40); + break; + default: + break; + } +} + +void Scene20::Action3::signal() { + Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene; + NpcMover *npcMover; + + switch (_actionIndex++) { + case 0: + setDelay(120); + break; + case 1: { + npcMover = new NpcMover(); + Common::Point pt(615, 81); + _globals->_player.addMover(npcMover, &pt, this); + ObjectMover2 *mover1 = new ObjectMover2(); + scene->_SceneObjectExt.addMover(mover1, 5, 10, &_globals->_player); + ObjectMover2 *mover2 = new ObjectMover2(); + scene->_sceneObject3.addMover(mover2, 20, 25, &_globals->_player); + break; + } + case 2: { + npcMover = new NpcMover(); + Common::Point pt(618, 90); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 3: { + _globals->_player._moveDiff = Common::Point(10, 10); + scene->_SceneObjectExt._moveDiff = Common::Point(10, 10); + scene->_sceneObject3._moveDiff = Common::Point(10, 10); + npcMover = new NpcMover(); + Common::Point pt(445, 132); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 4: { + npcMover = new NpcMover(); + Common::Point pt(151, 137); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 5: { + npcMover = new NpcMover(); + Common::Point pt(-15, 137); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 6: + scene->_sound.startSound(60, this, 127); + _globals->_soundHandler.proc4(); + break; + case 7: + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_sceneManager.changeScene(90); + break; + default: + break; + } +} + +void Scene20::Action4::signal() { + Scene20 *scene = (Scene20 *)_globals->_sceneManager._scene; + NpcMover *npcMover; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: { + npcMover = new NpcMover(); + Common::Point pt(486, 134); + _globals->_player.addMover(npcMover, &pt, this); + ObjectMover2 *mover1 = new ObjectMover2(); + scene->_SceneObjectExt.addMover(mover1, 20, 35, &_globals->_player); + break; + } + case 2: { + _globals->_player._moveDiff = Common::Point(12, 12); + scene->_SceneObjectExt._moveDiff = Common::Point(12, 12); + NpcMover *mover1 = new NpcMover(); + Common::Point pt(486, 134); + scene->_sceneObject3.addMover(mover1, &pt, this); + NpcMover *mover2 = new NpcMover(); + pt = Common::Point(-15, 134); + _globals->_player.addMover(mover2, &pt, NULL); + NpcMover *mover3 = new NpcMover(); + pt = Common::Point(-15, 134); + scene->_SceneObjectExt.addMover(mover3, &pt, NULL); + break; + } + case 3: { + scene->_sceneObject3._moveDiff = Common::Point(20, 20); + npcMover = new NpcMover(); + Common::Point pt(320, 134); + scene->_sceneObject3.addMover(npcMover, &pt, this); + break; + } + case 4: { + scene->_sound.startSound(28); + scene->_sceneObject4.postInit(); + scene->_sceneObject4.setVisage(21); + scene->_sceneObject4.setStrip(3); + scene->_sceneObject4.setPosition(Common::Point(scene->_sceneObject3._position.x - 36, + scene->_sceneObject3._position.y - 1)); + scene->_sceneObject4._moveDiff.x = 48; + + ObjectMover3 *mover = new ObjectMover3(); + scene->_sceneObject4.addMover(mover, &scene->_SceneObjectExt, 4, this); + break; + } + case 5: { + scene->_sound.startSound(42); + scene->_sceneObject4.remove(); + scene->_SceneObjectExt.setVisage(21); + scene->_SceneObjectExt.setStrip(1); + scene->_SceneObjectExt.setFrame(1); + scene->_SceneObjectExt.animate(ANIM_MODE_5, NULL); + + scene->_SceneObjectExt._moveDiff.x = 4; + NpcMover *mover1 = new NpcMover(); + Common::Point pt(scene->_SceneObjectExt._position.x - 12, scene->_SceneObjectExt._position.y + 5); + scene->_SceneObjectExt.addMover(mover1, &pt, NULL); + + scene->_sceneObject5.postInit(); + scene->_sceneObject5.setVisage(21); + scene->_sceneObject5.setStrip(3); + scene->_sceneObject5.setPosition(Common::Point(scene->_sceneObject3._position.x - 36, + scene->_sceneObject3._position.y - 1)); + scene->_sceneObject5._moveDiff.x = 48; + + ObjectMover3 *mover = new ObjectMover3(); + scene->_sceneObject5.addMover(mover, &_globals->_player, 4, this); + break; + } + case 6: { + scene->_sound.startSound(42); + scene->_SceneObjectExt.setStrip(2); + scene->_SceneObjectExt.animate(ANIM_MODE_2, NULL); + + scene->_sceneObject5.remove(); + _globals->_player.setVisage(21); + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + _globals->_player._moveDiff.x = 4; + + npcMover = new NpcMover(); + Common::Point pt(_globals->_player._position.x - 25, _globals->_player._position.y + 5); + _globals->_player.addMover(npcMover, &pt, this); + break; + } + case 7: + _globals->_player.setStrip(2); + _globals->_player.animate(ANIM_MODE_2, NULL); + scene->_sound.startSound(77, this, 127); + break; + case 8: + _globals->_game.endGame(20, 0); + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene20::Scene20() { +} + +void Scene20::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerGameText); + _speakerQText._npc = &_globals->_player; + + if (_globals->_sceneManager._previousScene == 30) { + _globals->_player.postInit(); + _globals->_player.setVisage(20); + _globals->_player.setPosition(Common::Point(405, 69)); + _globals->_player._moveDiff = Common::Point(10, 10); + _globals->_player.animate(ANIM_MODE_1, NULL); + + _SceneObjectExt.postInit(); + _SceneObjectExt.setVisage(20); + _SceneObjectExt.setPosition(Common::Point(400, 69)); + _SceneObjectExt.animate(ANIM_MODE_1, NULL); + + _sceneObject3.postInit(); + _sceneObject3.setVisage(20); + _sceneObject3.setPosition(Common::Point(395, 69)); + _sceneObject3.animate(ANIM_MODE_1, NULL); + + _SceneObjectExt._moveDiff = Common::Point(10, 10); + _sceneObject3._moveDiff = Common::Point(10, 10); + _globals->_soundHandler.startSound(20); + _sound.startSound(21); + _sound.proc5(1); + setAction(&_action2); + + _sceneBounds = Rect(320, 0, 640, 200); + } else if (_globals->_sceneManager._previousScene == 60) { + _globals->_player.postInit(); + _globals->_player.setVisage(2640); + _globals->_player.animate(ANIM_MODE_NONE, NULL); + _globals->_player.setStrip2(1); + _globals->_player.setFrame2(4); + _globals->_player.setPriority2(200); + _globals->_player.setPosition(Common::Point(425, 233)); + + setAction(&_action1); + _speakerQText.setTextPos(Common::Point(350, 20)); + _speakerQText._textWidth = 260; + _speakerGameText.setTextPos(Common::Point(350, 20)); + _speakerGameText._textWidth = 260; + + _globals->_soundHandler.startSound(8); + _sceneBounds = Rect(320, 0, 640, 200); + } else { + _sound.startSound(30); + _globals->_player.postInit(); + _globals->_player.setVisage(20); + _globals->_player.setPosition(Common::Point(588, 79)); + _globals->_player._moveDiff = Common::Point(5, 5); + _globals->_player.setPriority2(50); + _globals->_player.animate(ANIM_MODE_1, NULL); + + _SceneObjectExt.postInit(); + _SceneObjectExt.setVisage(20); + _SceneObjectExt.setPosition(Common::Point(583, 79)); + _SceneObjectExt.animate(ANIM_MODE_1, NULL); + + _sceneObject3.postInit(); + _sceneObject3.setVisage(20); + _sceneObject3.setStrip(2); + _SceneObjectExt.setPosition(Common::Point(595, 79)); + _SceneObjectExt.animate(ANIM_MODE_1, NULL); + + if ((_globals->getFlag(120) && _globals->getFlag(116)) || + (_globals->getFlag(117) && _globals->getFlag(119))) { + setAction(&_action3); + } else if (_globals->getFlag(104)) { + _sceneMode = 21; + setAction(&_sequenceManager, this, 21, &_globals->_player, &_SceneObjectExt, NULL); + } else { + _sceneObject3._moveDiff = Common::Point(8, 8); + setAction(&_action4); + } + + _sceneBounds.centre(_globals->_player._position.x, _globals->_player._position.y); + } + + _globals->_player.disableControl(); + loadScene(20); +} + +void Scene20::signal() { + if (_sceneMode == 21) + _globals->_sceneManager.changeScene(90); +} + +/*-------------------------------------------------------------------------- + * Scene 30 - First game scene (Outside Ch'mee house) + * + *--------------------------------------------------------------------------*/ + +void Scene30::BeamAction::signal() { + Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + // Disable control and move player to the doorway beam + _globals->_player.disableControl(); + NpcMover *mover = new NpcMover(); + Common::Point pt(114, 198); + _globals->_player.addMover(mover, &pt, this); + break; + } + + case 1: + // Perform the animation of player raising hand + _globals->_player.setVisage(31); + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + + case 2: + // Hide the beam and lower the player's hand + scene->_sound.startSound(10, NULL, 127); + _globals->_player.animate(ANIM_MODE_6, this); + scene->_beam.remove(); + break; + + case 3: { + // Bring the Kzin to the doorway + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(7); + scene->_kzin.postInit(); + scene->_kzin.setVisage(2801); + scene->_kzin.animate(ANIM_MODE_1, NULL); + scene->_kzin.setObjectWrapper(new SceneObjectWrapper()); + scene->_kzin.setPosition(Common::Point(334, 1)); + NpcMover *mover = new NpcMover(); + Common::Point pt(158, 170); + scene->_kzin.addMover(mover, &pt, this); + _globals->_sceneItems.push_front(&scene->_kzin); + break; + } + + case 4: + // Open the door + scene->_sound.startSound(11, NULL, 127); + scene->_door.animate(ANIM_MODE_5, this); + break; + + case 5: + // Run the Kzin's talk sequence + scene->_sound.startSound(13, NULL, 127); + _globals->_soundHandler.startSound(12, NULL, 127); + scene->_stripManager.start((scene->_sceneMode == 0) ? 30 : 37, this); + break; + + case 6: + // Slight delay + setDelay(3); + break; + + case 7: + // Re-activate player control + scene->_sceneMode = 31; + scene->_kzin.setAction(&scene->_kzinAction); + _globals->_player.enableControl(); + + // End this action + remove(); + break; + + default: + break; + } +} + +void Scene30::KzinAction::signal() { + Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1200); + break; + case 1: + _globals->_soundHandler.proc2(0); + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager, _globals->_sceneManager._scene, 31, &scene->_kzin, &scene->_door, NULL); + break; + case 2: + _globals->_player.enableControl(); + remove(); + break; + default: + break; + } +} + +void Scene30::RingAction::signal() { + Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + scene->_kzin.setAction(NULL); + NpcMover *mover = new NpcMover(); + Common::Point pt(114, 198); + _globals->_player.addMover(mover, &pt, this); + break; + } + + case 1: + _globals->_player.checkAngle(&scene->_kzin); + scene->_stripManager.start(32, this); + break; + + case 2: { + _globals->_player.animate(ANIM_MODE_1, NULL); + NpcMover *mover = new NpcMover(); + Common::Point pt(143, 177); + _globals->_player.addMover(mover, &pt, this); + break; + } + + case 3: + scene->_sound.startSound(11, NULL, 127); + scene->_door.animate(ANIM_MODE_6, this); + break; + + case 4: { + scene->_sound.startSound(13, NULL, 127); + NpcMover *kzinMover = new NpcMover(); + Common::Point pt(354, 5); + scene->_kzin.addMover(kzinMover, &pt, this); + NpcMover *playerMover = new NpcMover(); + pt = Common::Point(335, 36); + _globals->_player.addMover(playerMover, &pt, this); + break; + } + + case 5: + break; + + case 6: + _globals->_sceneManager.changeScene(20); + break; + + default: + break; + } +} + +void Scene30::TalkAction::signal() { + Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + scene->_kzin.setAction(NULL); + NpcMover *mover = new NpcMover(); + Common::Point pt(114, 198); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_player.checkAngle(&scene->_kzin); + scene->_stripManager.start(34, this); + break; + case 2: + setDelay(5); + break; + case 3: + scene->_kzin.setAction(&scene->_kzinAction); + _globals->_player.enableControl(); + remove(); + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene30::KzinObject::doAction(int action) { + Scene30 *scene = (Scene30 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + display2(30, 12); + break; + case OBJECT_SCANNER: + display2(30, 11); + break; + case OBJECT_RING: + _globals->_inventory._ring._sceneNumber = 30; + scene->setAction(&scene->_ringAction); + break; + case CURSOR_LOOK: + display2(30, 6); + break; + case CURSOR_USE: + display2(30, 10); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->setAction(&scene->_talkAction); + break; + default: + SceneObject::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene30::Scene30() : + _groundHotspot(9, OBJECT_SCANNER, 50, 17, CURSOR_LOOK, 30, 3, CURSOR_USE, 30, 8, LIST_END), + _wallsHotspot(8, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 30, 0, CURSOR_USE, 30, 7, LIST_END), + _courtyardHotspot(0, CURSOR_LOOK, 30, 4, LIST_END), + _treeHotspot(10, OBJECT_SCANNER, 40, 39, CURSOR_LOOK, 30, 5, CURSOR_USE, 30, 9, LIST_END) { +} + +void Scene30::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + // Add the speaker classes to the strip manager + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerQText); + _speakerSText._npc = &_kzin; + _speakerQText._npc = &_globals->_player; + + + // Setup player + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setStrip(7); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(114, 198)); + _globals->_player.changeZoom(75); + _globals->_player.enableControl(); + + // Set up beam object + _beam.postInit(); + _beam.setVisage(31); + _beam.setStrip(2); + _beam.setPosition(Common::Point(124, 178)); + _beam.setPriority2(188); + + // Set up door object + _door.postInit(); + _door.setVisage(30); + _door.setPosition(Common::Point(150, 183)); + + // Final processing and add of scene items + _courtyardHotspot.setBounds(Rect(0, 0, 320, 200)); + + // Add the objects and hotspots to the scene + _globals->_sceneItems.addItems(&_beam, &_wallsHotspot, &_door, &_treeHotspot, &_groundHotspot, + &_courtyardHotspot, NULL); + + // Load the scene data + loadScene(30); + _sceneMode = 0; +} + +void Scene30::signal() { + if (_sceneMode == 31) { + // Re-activate beam if the Kzin goes back inside + _beam.postInit(); + _beam.setVisage(31); + _beam.setStrip(2); + _beam.setPosition(Common::Point(124, 178)); + _beam.setPriority2(188); + _globals->_sceneItems.push_front(&_beam); + _globals->_player.enableControl(); + } else if (_sceneMode == 32) { + _globals->_player.disableControl(); + _sceneMode = 31; + setAction(&_sequenceManager, _globals->_sceneManager._scene, 31, &_kzin, &_door, NULL); + } +} + +/*-------------------------------------------------------------------------- + * Scene 40 - Chmeee Home + * + *--------------------------------------------------------------------------*/ + +void Scene40::Action1::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(120); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(40, this); + break; + case 2: + scene->_doorway.postInit(); + scene->_doorway.setVisage(46); + scene->_doorway.setPosition(Common::Point(305, 61)); + scene->_doorway.animate(ANIM_MODE_5, this); + scene->_soundHandler.startSound(25); + break; + case 3: + scene->_doorway.hide(); + scene->_dyingKzin.setPosition(Common::Point(296, 62)); + _globals->_player.animate(ANIM_MODE_5, NULL); + scene->_object1.setVisage(43); + scene->_object1.setStrip(3); + scene->_object1.animate(ANIM_MODE_5, NULL); + scene->_object2.hide(); + scene->_object3.hide(); + scene->_stripManager.start(45, this); + break; + case 4: + scene->_object2.remove(); + scene->_object3.remove(); + scene->_assassin.setVisage(42); + scene->_assassin.setStrip(2); + scene->_assassin.setFrame(1); + scene->_assassin.setPosition(Common::Point(13, 171)); + scene->_assassin.animate(ANIM_MODE_5, this); + scene->_soundHandler.startSound(25); + break; + case 5: + scene->_doorway.show(); + scene->_doorway.setVisage(42); + scene->_doorway.setStrip(3); + scene->_doorway.setFrame(1); + scene->_doorway.setPosition(Common::Point(41, 144)); + scene->_assassin.animate(ANIM_MODE_6, NULL); + setDelay(6); + break; + case 6: + scene->_doorway.setPosition(Common::Point(178, 101)); + setDelay(6); + break; + case 7: + scene->_doorway.setPosition(Common::Point(271, 69)); + setDelay(6); + break; + case 8: + scene->_doorway.remove(); + scene->_dyingKzin.animate(ANIM_MODE_5, this); + break; + case 9: { + scene->_dyingKzin.setStrip(1); + scene->_dyingKzin.setFrame(1); + scene->_dyingKzin._moveDiff.y = 15; + scene->_dyingKzin.animate(ANIM_MODE_5, NULL); + Common::Point pt(223, 186); + NpcMover *mover = new NpcMover(); + scene->_dyingKzin.addMover(mover, &pt, this); + break; + } + case 10: { + scene->_soundHandler.startSound(27); + Common::Point pt(223, 184); + NpcMover *mover = new NpcMover(); + scene->_dyingKzin.addMover(mover, &pt, this); + break; + } + case 11: { + Common::Point pt(223, 186); + NpcMover *mover = new NpcMover(); + scene->_dyingKzin.addMover(mover, &pt, this); + break; + } + case 12: { + _globals->_soundHandler.startSound(26); + _globals->_player._uiEnabled = true; + scene->_assassin.setVisage(42); + scene->_assassin.setPosition(Common::Point(4, 191)); + scene->_assassin.setStrip(1); + scene->_assassin.animate(ANIM_MODE_1, NULL); + Common::Point pt(230, 187); + NpcMover *mover = new NpcMover(); + scene->_assassin.addMover(mover, &pt, this); + break; + } + case 13: + setDelay(180); + break; + case 14: + scene->_assassin.setVisage(45); + scene->_assassin.setStrip(1); + scene->_assassin.setFrame(1); + scene->_assassin.animate(ANIM_MODE_5, this); + scene->_soundHandler.startSound(28); + break; + case 15: + _globals->_player.disableControl(); + scene->_object1.setVisage(40); + scene->_object1.setStrip(4); + scene->_object1.setFrame(1); + scene->_object1.animate(ANIM_MODE_5, NULL); + _globals->_player.setVisage(40); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 16: + _globals->_soundHandler.startSound(77, this); + break; + case 17: + _globals->_game.endGame(40, 20); + remove(); + break; + } +} + +void Scene40::Action2::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + if (scene->_assassin._position.x < 229) + _actionIndex = 0; + setDelay(1); + break; + case 1: + scene->_assassin.animate(ANIM_MODE_NONE, NULL); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: { + scene->_soundHandler.startSound(28); + scene->_doorway.postInit(); + scene->_doorway.setVisage(16); + scene->_doorway.setStrip2(6); + scene->_doorway.setPriority2(200); + scene->_doorway.setPosition(Common::Point(159, 191)); + scene->_doorway._moveDiff = Common::Point(40, 40); + scene->_doorway._field7A = 60; + scene->_doorway.animate(ANIM_MODE_5, NULL); + + Common::Point pt(271, 165); + NpcMover *mover = new NpcMover(); + scene->_doorway.addMover(mover, &pt, this); + break; + } + case 3: + scene->_doorway.remove(); + scene->_assassin.setVisage(44); + scene->_assassin._frame = 1; + scene->_assassin.animate(ANIM_MODE_5, this); + scene->_soundHandler.startSound(29); + _globals->_inventory._infoDisk._sceneNumber = 40; + break; + case 4: + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 5: { + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(1); + Common::Point pt(230, 195); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: { + _globals->_player.setStrip(7); + scene->_object1.setVisage(2806); + scene->_object1.animate(ANIM_MODE_1, NULL); + SceneObjectWrapper *wrapper = new SceneObjectWrapper(); + scene->_object1.setObjectWrapper(wrapper); + Common::Point pt(200, 190); + NpcMover *mover = new NpcMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 7: + scene->_stripManager.start(44, this); + break; + case 8: { + Common::Point pt(170, 260); + NpcMover *mover = new NpcMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 9: + scene->_dyingKzin.setAction(&scene->_action7); + scene->_object1.remove(); + _globals->_stripNum = 88; + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.enableControl(); + scene->_assassin.setAction(&scene->_action8); + break; + } +} + +void Scene40::Action3::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.setAction(NULL); + _globals->_stripNum = 99; + _globals->_player.disableControl(); + Common::Point pt(240, 195); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_player.setVisage(5010); + _globals->_player._strip = 2; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_4, 5, 1, this); + break; + case 2: + scene->_assassin.setStrip(2); + scene->_assassin.setFrame(1); + _globals->_inventory._infoDisk._sceneNumber = 1; + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(7); + _globals->_stripNum = 88; + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene40::Action4::signal() { + switch (_actionIndex++) { + case 0: { + Common::Point pt(178, 190); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_stripNum = 88; + _globals->_player.enableControl(); + break; + } +} + +void Scene40::Action5::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(120)); + break; + case 1: + scene->_object2.animate(ANIM_MODE_8, 1, this); + _actionIndex = 0; + } +} + +void Scene40::Action6::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_object1.postInit(); + scene->_object1.setVisage(16); + scene->_object1.setStrip2(6); + scene->_object1.setPosition(Common::Point(313, 53)); + scene->_object1._field7A = 60; + + Common::Point pt(141, 194); + NpcMover *mover = new NpcMover(); + scene->_object1.addMover(mover, &pt, this); + scene->_object1.animate(ANIM_MODE_5, NULL); + + scene->_doorway.postInit(); + scene->_doorway.setVisage(46); + scene->_doorway.setPosition(Common::Point(305, 61)); + scene->_doorway.animate(ANIM_MODE_5, this); + scene->_soundHandler.startSound(25); + break; + } + case 1: + scene->_soundHandler.startSound(28); + scene->_doorway.setPosition(Common::Point(148, 74)); + scene->_doorway.setFrame(1); + scene->_doorway.setStrip(2); + scene->_doorway.animate(ANIM_MODE_5, this); + break; + case 2: + remove(); + break; + } +} + +void Scene40::Action7::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(500)); + break; + case 1: + scene->_object7.postInit(); + scene->_object7.setVisage(46); + + if (_globals->_randomSource.getRandomNumber(32767) >= 16384) { + scene->_object7.setStrip(3); + scene->_object7.setPosition(Common::Point(15, 185)); + } else { + scene->_object7.setPosition(Common::Point(305, 61)); + scene->_object7.setFrame(15); + } + break; + case 2: + scene->_object7.remove(); + _actionIndex = 0; + setDelay(60); + break; + } +} + +void Scene40::Action8::signal() { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(300); + break; + case 1: + _globals->_player.disableControl(); + + if ((_globals->_player._position.y >= 197) || (_globals->_player._visage)) { + _actionIndex = 1; + setDelay(30); + } else { + scene->_doorway.postInit(); + scene->_doorway.setVisage(16); + scene->_doorway.setStrip2(6); + scene->_doorway.setPriority2(200); + scene->_doorway._field7A = 60; + + if (_globals->_player._position.x >= 145) { + scene->_doorway.setPriority2(-1); + scene->_doorway.setPosition(Common::Point(6, 157)); + } else { + scene->_doorway.setPosition(Common::Point(313, 53)); + } + + scene->_doorway._moveDiff = Common::Point(40, 40); + Common::Point pt(_globals->_player._position.x, _globals->_player._position.y - 18); + NpcMover *mover = new NpcMover(); + scene->_doorway.addMover(mover, &pt, this); + scene->_doorway.animate(ANIM_MODE_5, NULL); + } + break; + case 2: + scene->_doorway.remove(); + _globals->_player.setVisage(40); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_soundHandler.startSound(77, this); + break; + case 4: + _globals->_game.endGame(40, 45); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene40::DyingKzin::doAction(int action) { + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(40, 43); + break; + case CURSOR_CROSSHAIRS: + SceneItem::display2(40, 44); + break; + case CURSOR_LOOK: + SceneItem::display2(40, 12); + break; + case CURSOR_USE: + SceneItem::display2(40, 18); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene40::Assassin::doAction(int action) { + Scene40 *scene = (Scene40 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_CROSSHAIRS: + if (scene->_assassin._visage == 44) + SceneItem::display2(40, 21); + else { + _globals->_player.disableControl(); + Common::Point pt(230, 187); + NpcMover *mover = new NpcMover(); + addMover(mover, &pt, NULL); + } + break; + case OBJECT_SCANNER: + SceneItem::display2(40, (scene->_assassin._visage == 44) ? 22 : 23); + break; + case CURSOR_LOOK: + if (scene->_assassin._visage != 44) + SceneItem::display2(40, 13); + else + SceneItem::display2(40, (_globals->_inventory._infoDisk._sceneNumber == 1) ? 19 : 14); + break; + case CURSOR_USE: + if (scene->_assassin._visage != 44) + SceneItem::display2(40, 15); + else if (_globals->_inventory._infoDisk._sceneNumber == 1) + SceneItem::display2(40, 19); + else { + _globals->_player.disableControl(); + setAction(&scene->_action3); + } + break; + case CURSOR_TALK: + SceneItem::display2(40, 38); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene40::Item2::doAction(int action) { + switch (action) { + case CURSOR_CROSSHAIRS: + SceneItem::display2(40, 35); + _globals->_events.setCursor(CURSOR_WALK); + break; + case OBJECT_SCANNER: + SceneItem::display2(40, 34); + break; + case CURSOR_LOOK: + SceneItem::display2(40, 8); + break; + case CURSOR_USE: + SceneItem::display2(40, 36); + break; + case CURSOR_TALK: + SceneItem::display2(40, 37); + break; + default: + SceneItem::doAction(action); + break; + } +} + +void Scene40::Item6::doAction(int action) { + switch (action) { + case CURSOR_CROSSHAIRS: + SceneItem::display2(40, 25); + _globals->_events.setCursor(CURSOR_WALK); + break; + case OBJECT_SCANNER: + SceneItem::display2(40, 42); + break; + case CURSOR_LOOK: + SceneItem::display2(40, 6); + break; + case CURSOR_USE: + SceneItem::display2(40, 36); + break; + default: + SceneItem::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene40::Scene40() : + _item1(2, OBJECT_SCANNER, 40, 24, CURSOR_CROSSHAIRS, 40, 25, CURSOR_LOOK, 40, 7, CURSOR_USE, 40, 16, LIST_END), + _item3(5, OBJECT_SCANNER, 40, 26, CURSOR_CROSSHAIRS, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END), + _item4(6, OBJECT_SCANNER, 40, 31, CURSOR_CROSSHAIRS, 40, 32, CURSOR_LOOK, 40, 5, CURSOR_USE, 40, 33, LIST_END), + _item5(0, CURSOR_LOOK, 40, 11, LIST_END), + _item7(4, OBJECT_SCANNER, 40, 26, CURSOR_CROSSHAIRS, 40, 27, CURSOR_LOOK, 40, 9, CURSOR_USE, 40, 17, LIST_END), + _item8(8, OBJECT_SCANNER, 40, 39, CURSOR_CROSSHAIRS, 40, 40, CURSOR_LOOK, 40, 3, CURSOR_USE, 40, 41, LIST_END) { +} + +void Scene40::postInit(SceneObjectList *OwnerList) { + loadScene(40); + Scene::postInit(); + + setZoomPercents(0, 100, 200, 100); + _globals->_stripNum = 99; + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + + _speakerGameText._colour1 = 9; + _speakerGameText.setTextPos(Common::Point(160, 30)); + _speakerQText._npc = &_globals->_player; + _speakerSText._npc = &_object1; + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(130, 220)); + _globals->_player.disableControl(); + + if (_globals->_sceneManager._previousScene == 20) { + _globals->_soundHandler.startSound(24); + _globals->_player.setVisage(43); + + _object1.postInit(); + _object1.setVisage(41); + _object1.setPosition(Common::Point(105, 220)); + _object2.postInit(); + _object2.setVisage(41); + _object2.setStrip(6); + _object2.setPriority2(200); + _object2.setPosition(Common::Point(94, 189)); + _object2.setAction(&_action5); + + _object3.postInit(); + _object3.setVisage(41); + _object3.setStrip(5); + _object3.setPriority2(205); + _object3.setPosition(Common::Point(110, 186)); + _object3._numFrames = 2; + _object3.animate(ANIM_MODE_8, NULL, NULL); + + _assassin.postInit(); + _assassin.setPosition(Common::Point(-40, 191)); + _globals->_sceneItems.push_back(&_assassin); + + _dyingKzin.postInit(); + _dyingKzin.setVisage(40); + _dyingKzin.setStrip(6); + _dyingKzin.setPosition(Common::Point(-90, 65)); + _dyingKzin.setPriority2(170); + + setAction(&_action1); + } else { + _doorway.postInit(); + _doorway.setVisage(46); + _doorway.setPosition(Common::Point(148, 74)); + _doorway.setStrip(2); + _doorway.setFrame(_doorway.getFrameCount()); + + _dyingKzin.postInit(); + _dyingKzin.setVisage(40); + _dyingKzin.setPosition(Common::Point(205, 183)); + _dyingKzin.setPriority2(170); + _dyingKzin._frame = 9; + _dyingKzin.setAction(&_action7); + + _assassin.postInit(); + _assassin.setVisage(44); + _assassin.setPosition(Common::Point(230, 187)); + _assassin.setAction(&_action8); + + if (_globals->_inventory._infoDisk._sceneNumber == 40) { + _assassin.setStrip(1); + _assassin.setFrame(_assassin.getFrameCount()); + } else { + _assassin.setStrip(2); + } + + _globals->_sceneItems.push_back(&_assassin); + _globals->_player.setPosition(Common::Point(170, 220)); + + setAction(&_action4); + } + + _item5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _item6._sceneRegionId = 3; + _item2._sceneRegionId = 7; + + _globals->_sceneItems.addItems(&_dyingKzin, &_item8, &_item1, &_item2, &_item3, &_item4, + &_item6, &_item7, &_item5, NULL); +} + +void Scene40::signal() { + if (_sceneMode == 41) + _globals->_sceneManager.changeScene(50); +} + +void Scene40::dispatch() { + if ((_globals->_stripNum == 88) && (_globals->_player._position.y >= 197)) { + _globals->_player.disableControl(); + _globals->_stripNum = 0; + _globals->_player.setAction(NULL); + _sceneMode = 41; + setAction(&_sequenceManager, this, 41, &_globals->_player, NULL); + + if (_globals->_sceneManager._previousScene == 20) { + _dyingKzin.setAction(&_action6); + } + } + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 50 - By Flycycles + * + *--------------------------------------------------------------------------*/ + +void Scene50::Action1::signal() { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setAction(&scene->_sequenceManager, this, 54, &_globals->_player, NULL); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(63, this); + break; + case 2: + if (scene->_stripManager._field2E8 != 107) { + _globals->_player.enableControl(); + remove(); + } else { + Common::Point pt(282, 139); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + } + break; + case 3: + _globals->_stripNum = -1; + _globals->_sceneManager.changeScene(60); + break; + } +} + +void Scene50::Action2::signal() { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + scene->_stripManager.start(66, this); + break; + case 1: { + Common::Point pt(141, 142); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_sceneManager.changeScene(40); + remove(); + break; + } +} + +void Scene50::Action3::signal() { + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(136, 185); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_sceneManager.changeScene(60); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene50::Object1::doAction(int action) { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(50, 20); + break; + case OBJECT_SCANNER: + SceneItem::display2(50, 19); + break; + case CURSOR_LOOK: + SceneItem::display2(50, 4); + break; + case CURSOR_USE: + SceneItem::display2(50, 21); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->_sceneMode = 52; + scene->setAction(&scene->_sequenceManager, scene, 52, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene50::Object2::doAction(int action) { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(50, 11); + break; + case OBJECT_SCANNER: + SceneItem::display2(50, 10); + break; + case CURSOR_LOOK: + SceneItem::display2(50, 1); + break; + case OBJECT_INFODISK: + case CURSOR_USE: + _globals->_stripNum = 50; + scene->setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene50::Object3::doAction(int action) { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(50, 11); + break; + case OBJECT_SCANNER: + SceneItem::display2(50, 10); + break; + case CURSOR_LOOK: + SceneItem::display2(50, 1); + break; + case OBJECT_INFODISK: + case CURSOR_USE: + SceneItem::display2(50, 8); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->_sceneMode = 52; + scene->setAction(&scene->_sequenceManager, scene, 52, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene50::Object4::doAction(int action) { + Scene50 *scene = (Scene50 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(50, 11); + break; + case OBJECT_SCANNER: + SceneItem::display2(50, 10); + break; + case CURSOR_LOOK: + SceneItem::display2(50, 1); + break; + case OBJECT_INFODISK: + case CURSOR_USE: + _globals->_player.disableControl(); + _globals->_stripNum = 0; + scene->_sceneMode = 51; + scene->setAction(&scene->_sequenceManager, scene, 51, &_globals->_player, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene50::Scene50() : + _item0(0, CURSOR_LOOK, 50, 3, LIST_END), + _item1(0, OBJECT_SCANNER, 50, 15, CURSOR_USE, 50, 16, CURSOR_LOOK, 50, 3, LIST_END), + _item2(0, CURSOR_LOOK, 50, 7, LIST_END), + _item3(8, OBJECT_STUNNER, 50, 14, OBJECT_SCANNER, 50, 13, CURSOR_LOOK, 50, 3, LIST_END), + _item4(9, OBJECT_SCANNER, 40, 39, OBJECT_STUNNER, 40, 40, CURSOR_USE, 40, 41, CURSOR_LOOK, 50, 5, LIST_END), + _item5(10, OBJECT_SCANNER, 50, 17, OBJECT_STUNNER, 50, 18, CURSOR_LOOK, 50, 6, CURSOR_USE, 30, 8, LIST_END) { +} + +void Scene50::postInit(SceneObjectList *OwnerList) { + loadScene(50); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player._canWalk = false; + _globals->_player.changeZoom(75); + _globals->_player._moveDiff.y = 3; + + if (_globals->_sceneManager._previousScene == 40) { + _globals->_player.setPosition(Common::Point(128, 123)); + } else if (_globals->_stripNum == 50) { + _globals->_player.setPosition(Common::Point(136, 185)); + } else { + _globals->_player.setPosition(Common::Point(270, 143)); + } + + _object2.postInit(); + _object2.setVisage(2331); + _object2.setStrip(6); + _object2.setPosition(Common::Point(136, 192)); + _object2.setPriority2(200); + + _object3.postInit(); + _object3.setVisage(2337); + _object3.setStrip(6); + _object3.setPosition(Common::Point(260, 180)); + _object3.setPriority2(200); + + _object4.postInit(); + _object4.setVisage(2331); + _object4.setStrip(6); + _object4.setPosition(Common::Point(295, 144)); + _object4.setPriority2(178); + + _globals->_sceneItems.addItems(&_object2, &_object3, &_object4, NULL); + + if (!_globals->getFlag(101)) { + _globals->_player.disableControl(); + _globals->setFlag(101); + setAction(&_action1); + } else { + _globals->_player.enableControl(); + + if (_globals->_sceneManager._previousScene == 40) { + _globals->_player.disableControl(); + _sceneMode = 54; + setAction(&_sequenceManager, this, 54, &_globals->_player, NULL); + } + } + + _item0.setBounds(Rect(200, 0, 320, 200)); + _globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item0, NULL); + _doorwayRect = Rect(80, 108, 160, 112); +} + +void Scene50::signal() { + switch (_sceneMode) { + case 51: + _globals->_sceneManager.changeScene(60); + break; + case 55: + _globals->_sceneManager.changeScene(40); + break; + case 52: + case 54: + _globals->_player.enableControl(); + break; + } +} + +void Scene50::dispatch() { + if ((_sceneMode != 55) && _doorwayRect.contains(_globals->_player._position)) { + // Player in house doorway, start player moving to within + _globals->_player.disableControl(); + _sceneMode = 55; + Common::Point pt(89, 111); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + } +} + +/*-------------------------------------------------------------------------- + * Scene 60 - Flycycle controls + * + *--------------------------------------------------------------------------*/ + +void Scene60::Action1::signal() { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + scene->_object9.postInit(); + scene->_object9.setVisage(60); + scene->_object9.setStrip(7); + scene->_object9.setPosition(Common::Point(136, 65)); + scene->_object9.animate(ANIM_MODE_5, this); + + scene->_soundHandler1.startSound(35); + break; + case 2: + scene->_object10.postInit(); + scene->_object10.setVisage(60); + scene->_object10.setPosition(Common::Point(199, 186)); + scene->_object10.animate(ANIM_MODE_8, 0, NULL); + scene->_object10._numFrames = 5; + + scene->_object6.animate(ANIM_MODE_2, NULL); + + if (!_globals->getFlag(83)) { + scene->_object5.postInit(); + scene->_object5.setVisage(60); + scene->_object5.setStrip2(3); + scene->_object5.setFrame(2); + scene->_object5.setPosition(Common::Point(148, 85)); + scene->_object5.animate(ANIM_MODE_2, NULL); + scene->_object5._numFrames = 5; + + _globals->_sceneItems.push_front(&scene->_object5); + scene->_soundHandler2.startSound(38); + } + + _globals->_events.setCursor(CURSOR_USE); + break; + case 3: + scene->_soundHandler2.startSound(37); + scene->loadScene(65); + scene->_object5.remove(); + + if (_globals->_sceneObjects->contains(&scene->_object10)) + scene->_object10.remove(); + + scene->_object6.remove(); + scene->_slaveButton.remove(); + scene->_object8.remove(); + scene->_item1.remove(); + scene->_item2.remove(); + + scene->_object3.postInit(); + scene->_object3.setVisage(65); + scene->_object3.setPosition(Common::Point(118, 197)); + + scene->_object2.postInit(); + scene->_object2.setVisage(65); + scene->_object2.setStrip(2); + scene->_object2.setPosition(Common::Point(160, 197)); + + scene->_object4.postInit(); + scene->_object4.setVisage(65); + scene->_object4.setStrip(3); + scene->_object4.setPosition(Common::Point(202, 197)); + + scene->_object1.postInit(); + scene->_object1.setVisage(65); + scene->_object1.setStrip(4); + scene->_object1.setFrame(1); + scene->_object1.setPosition(Common::Point(145, 165)); + + _globals->_sceneItems.push_front(&scene->_object3); + _globals->_sceneItems.push_front(&scene->_object2); + _globals->_sceneItems.push_front(&scene->_object4); + setDelay(10); + + _globals->_events.setCursor(CURSOR_USE); + break; + case 4: + _globals->setFlag(90); + // Deliberate fall-through + case 5: + case 6: + case 7: + SceneItem::display(60, _actionIndex - 4, SET_Y, 40, SET_X, 25, SET_FONT, 75, + SET_EXT_BGCOLOUR, -1, SET_FG_COLOUR, 34, SET_POS_MODE, 0, + SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END); + _globals->_events.setCursor(CURSOR_USE); + break; + case 9: + _globals->_player._uiEnabled = false; + _globals->_inventory._infoDisk._sceneNumber = 1; + + if (_globals->_sceneObjects->contains(&scene->_object5)) + scene->_object5.remove(); + + scene->_object6.animate(ANIM_MODE_NONE); + scene->_object6.setFrame(1); + scene->_object10.remove(); + + scene->_object9.postInit(); + scene->_object9.setVisage(60); + scene->_object9.setStrip(7); + scene->_object9.setPosition(Common::Point(136, 65)); + scene->_object9.setFrame(scene->_object9.getFrameCount()); + scene->_object9.animate(ANIM_MODE_6, this); + + scene->_soundHandler1.startSound(35); + scene->_soundHandler3.proc3(); + + scene->_object8.setFrame(1); + scene->_object8._state = 0; + + _globals->clearFlag(103); + _globals->clearFlag(!_globals->_stripNum ? 116 : 119); + break; + case 10: + setDelay(60); + break; + case 11: + _globals->_player._uiEnabled = true; + scene->_object9.remove(); + remove(); + break; + default: + break; + } +} + +void Scene60::Action2::signal() { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + case 2: + setDelay(3); + break; + case 1: + scene->_stripManager.start(66, this); + break; + case 3: + _globals->_sceneManager.changeScene(50); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene60::Object2::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 16); + } else if (action == CURSOR_USE) { + animate(ANIM_MODE_8, 1, NULL); + + if (scene->_action1.getActionIndex() > 5) { + scene->_soundHandler3.startSound(36); + scene->_action1.setActionIndex(scene->_action1.getActionIndex() - 2); + scene->_action1.setDelay(1); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object3::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 17); + } else if (action == CURSOR_USE) { + animate(ANIM_MODE_8, 1, NULL); + + if (scene->_action1.getActionIndex() < 8) { + scene->_soundHandler3.startSound(36); + scene->_action1.setDelay(1); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object4::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 18); + } else if (action == CURSOR_USE) { + scene->_soundHandler3.startSound(36); + animate(ANIM_MODE_8, 1, NULL); + scene->_object3.remove(); + scene->_object2.remove(); + scene->_object4.remove(); + scene->_object1.remove(); + + SceneItem::display(0, 0); + scene->loadScene(60); + + scene->_object6.setVisage(60); + scene->_object6.setPosition(Common::Point(233, 143)); + scene->_object6.animate(ANIM_MODE_2, NULL); + + scene->_slaveButton.postInit(); + scene->_slaveButton.setVisage(60); + scene->_slaveButton.setStrip(8); + scene->_slaveButton.setPosition(Common::Point(143, 125)); + + scene->_object8.postInit(); + scene->_object8.setVisage(60); + scene->_object8.setStrip(8); + scene->_object8.setPosition(Common::Point(143, 105)); + + _globals->_sceneItems.push_front(&scene->_object8); + _globals->_sceneItems.push_front(&scene->_slaveButton); + + scene->_object10.postInit(); + scene->_object10.setVisage(60); + scene->_object10.setPosition(Common::Point(199, 186)); + scene->_object10.animate(ANIM_MODE_8, 0, NULL); + scene->_object10._numFrames = 5; + scene->_object10.setAction(&scene->_sequenceManager, scene, 61, NULL); + + if (scene->_slaveButton._state) + scene->_slaveButton.setFrame(2); + if (scene->_object8._state) + scene->_object8.setFrame(2); + + _globals->_sceneItems.push_front(&scene->_item1); + _globals->_sceneItems.push_front(&scene->_object6); + _globals->_sceneItems.push_front(&scene->_slaveButton); + _globals->_sceneItems.push_front(&scene->_object8); + _globals->_sceneItems.push_back(&scene->_item2); + + _globals->gfxManager()._font.setFontNumber(2); + _globals->_sceneText._fontNumber = 2; + + scene->_action1.setActionIndex(2); + scene->_action1.setDelay(1); + scene->_sceneMode = 9999; + scene->signal(); + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object5::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 9); + } else if (action == CURSOR_USE) { + scene->_action1.setDelay(1); + _globals->setFlag(83); + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object6::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 11); + } else if (action == CURSOR_USE) { + if (_animateMode == ANIM_MODE_NONE) + SceneItem::display2(60, 14); + else if (!scene->_slaveButton._state) { + _globals->_soundHandler.startSound(40); + _globals->_soundHandler.proc5(1); + _globals->_sceneManager.changeScene(20); + } else { + scene->_sceneMode = 15; + setAction(&scene->_sequenceManager, scene, 62, NULL); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::SlaveObject::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 8); + } else if (action == CURSOR_USE) { + if (scene->_object8._state) + scene->_sceneMode = 19; + else if (_state) { + scene->_soundHandler3.proc3(); + animate(ANIM_MODE_6, NULL); + _globals->clearFlag(102); + _globals->clearFlag(!_globals->_stripNum ? 117 : 120); + _state = 0; + scene->_sceneMode = 9998; + } else { + scene->_soundHandler3.startSound(39); + _globals->setFlag(102); + _globals->setFlag(!_globals->_stripNum ? 117 : 120); + animate(ANIM_MODE_5, NULL); + _state = 1; + scene->_sceneMode = 9998; + } + + setAction(&scene->_sequenceManager, scene, 62, NULL); + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object8::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 7); + } else if (action == CURSOR_USE) { + if (!scene->_object8._state) + scene->_sceneMode = 14; + else if (_state) { + scene->_soundHandler3.proc3(); + animate(ANIM_MODE_6, NULL); + _globals->clearFlag(103); + _globals->clearFlag(!_globals->_stripNum ? 116 : 119); + _state = 0; + scene->_sceneMode = 9998; + } else { + scene->_soundHandler3.startSound(39); + animate(ANIM_MODE_5, NULL); + _state = 1; + _globals->setFlag(103); + _globals->setFlag(!_globals->_stripNum ? 116 : 119); + scene->_sceneMode = 9998; + } + + setAction(&scene->_sequenceManager, scene, 62, NULL); + } else { + SceneHotspot::doAction(action); + } +} + +void Scene60::Object9::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display2(60, 13); + } else if (action == CURSOR_USE) { + _globals->setFlag(!_globals->_stripNum ? 118 : 121); + scene->setAction(&scene->_action1); + } else { + SceneHotspot::doAction(action); + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene60::Item1::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_INFODISK: + _globals->_inventory._infoDisk._sceneNumber = 60; + _globals->setFlag(!_globals->_stripNum ? 118 : 121); + scene->_sceneMode = 0; + scene->setAction(&scene->_action1); + break; + case CURSOR_LOOK: + SceneItem::display2(60, 10); + break; + case CURSOR_USE: + if (_globals->_inventory._infoDisk._sceneNumber == 60) { + if (_globals->getFlag(118) && !_globals->_stripNum) { + _globals->clearFlag(118); + scene->setAction(&scene->_action1); + scene->_action1.setActionIndex(9); + scene->_action1.setDelay(1); + } + if (_globals->getFlag(121) && !_globals->_stripNum) { + _globals->clearFlag(121); + scene->setAction(&scene->_action1); + scene->_action1.setActionIndex(9); + scene->_action1.setDelay(1); + } + } else if (_globals->_inventory._infoDisk._sceneNumber == 1) { + scene->_sceneMode = 0; + setAction(&scene->_sequenceManager, scene, 62, NULL); + } else { + scene->setAction(&scene->_action2); + } + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene60::Item::doAction(int action) { + Scene60 *scene = (Scene60 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(60, _messageNum); + break; + case CURSOR_USE: + scene->_sceneMode = _sceneMode; + setAction(&scene->_sequenceManager, this, 62, NULL); + break; + default: + SceneItem::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene60::Scene60() : + _item2(0, 12, 12), + _item3(8, 22, 23), + _item4(9, 24, 25), + _item5(10, 26, 27), + _item6(11, 28, 29) { +} + +void Scene60::postInit(SceneObjectList *OwnerList) { + loadScene(60); + Scene::postInit(); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + + _slaveButton.postInit(); + _slaveButton.setVisage(60); + _slaveButton.setStrip(8); + _slaveButton.setPosition(Common::Point(143, 125)); + _slaveButton._state = 0; + + _object8.postInit(); + _object8.setVisage(60); + _object8.setStrip(8); + _object8.setPosition(Common::Point(143, 105)); + _object8._state = 0; + + _globals->_sceneItems.push_back(&_object8); + _globals->_sceneItems.push_back(&_slaveButton); + + _object6.postInit(); + _object6.setVisage(60); + _object6.setStrip(5); + _object6.setPosition(Common::Point(233, 143)); + _globals->_sceneItems.push_back(&_object6); + + if (_globals->_stripNum == -1) { + _globals->_stripNum = 0; + } else { + _globals->_player.disableControl(); + _sceneMode = 9999; + setAction(&_sequenceManager, this, 61, NULL); + } + + _item1.setBounds(Rect(130, 55, 174, 70)); + _item2.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + if (_globals->_stripNum == 0) { + if (_globals->getFlag(117)) { + _slaveButton._state = 1; + _slaveButton.setFrame(2); + } + + if (_globals->getFlag(116)) { + _object8._state = 1; + _object8.setFrame(2); + } + + if (_globals->getFlag(118)) { + _object6.animate(ANIM_MODE_2, NULL); + + _object10.postInit(); + _object10.setVisage(60); + _object10.setPosition(Common::Point(199, 186)); + _object10.animate(ANIM_MODE_8, 0, NULL); + + _soundHandler1.startSound(35); + + if (!_globals->getFlag(83)) { + _object5.postInit(); + _object5.setVisage(60); + _object5.setStrip2(3); + _object5.setFrame(2); + _object5.setPosition(Common::Point(148, 85)); + _object5.animate(ANIM_MODE_2, NULL); + _object5._numFrames = 5; + _globals->_sceneItems.push_front(&_object5); + + _soundHandler2.startSound(38); + } + } + } else { + if (_globals->getFlag(120)) { + _slaveButton._state = 1; + _slaveButton.setFrame(2); + } + + if (_globals->getFlag(119)) { + _object8._state = 1; + _object8.setFrame(2); + } + + if (_globals->getFlag(121)) { + _object6.animate(ANIM_MODE_2, NULL); + + _object10.postInit(); + _object10.setVisage(60); + _object10.setPosition(Common::Point(199, 186)); + _object10.animate(ANIM_MODE_8, 0, NULL); + _object10._numFrames = 5; + + _soundHandler1.startSound(35); + + if (!_globals->getFlag(83)) { + _object5.postInit(); + _object5.setVisage(60); + _object5.setStrip2(3); + _object5.setFrame(2); + _object5.setPosition(Common::Point(148, 85)); + _object5.animate(ANIM_MODE_2, NULL); + _object5._numFrames = 5; + _globals->_sceneItems.push_front(&_object5); + + _soundHandler2.startSound(38); + } + } + } + + _globals->_sceneItems.addItems(&_item3, &_item4, &_item5, &_item6, + &_item1, &_item2, NULL); +} + +void Scene60::signal() { + if (_sceneMode != 0) { + if (_sceneMode == 9998) { + _globals->_events.setCursor(CURSOR_USE); + } else if (_sceneMode == 9999) { + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + + _gfxButton.setText(EXIT_MSG); + _gfxButton._bounds.centre(160, 193); + _gfxButton.draw(); + _gfxButton._bounds.expandPanes(); + } else { + SceneItem::display2(60, _sceneMode); + _globals->_events.setCursor(CURSOR_USE); + } + } +} + +void Scene60::process(Event &event) { + Scene::process(event); + + if (_sceneNumber == 60) { + if (_gfxButton.process(event)) + _globals->_sceneManager.changeScene(50); + } +} + +/*-------------------------------------------------------------------------- + * Scene 90 - Shipyard Entrance + * + *--------------------------------------------------------------------------*/ + +void Scene90::Action1::signal() { + Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + _globals->_scenePalette.addRotation(64, 72, -1); + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(90, this); + break; + case 2: + setDelay(2); + break; + case 3: { + Common::Point pt(278, 191); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 4: + scene->_object2.setStrip(3); + setDelay(2); + break; + case 5: + scene->_soundHandler2.startSound(58); + + if (scene->_stripManager._field2E8 == 220) + scene->_stripManager.start(91, this, scene); + else { + scene->_stripManager.start(_globals->getFlag(104) ? 93 : 92, this, scene); + _actionIndex = 7; + } + break; + case 6: + scene->_object2.animate(ANIM_MODE_NONE); + _globals->_player._uiEnabled = true; + break; + case 7: + scene->_object2.animate(ANIM_MODE_NONE); + _globals->_soundHandler.startSound(56); + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 8: { + Common::Point pt(215, 127); + PlayerMover *mover = new PlayerMover(); + scene->_object5.addMover(mover, &pt, this); + break; + } + case 9: { + Common::Point pt1(215, 127); + PlayerMover *mover1 = new PlayerMover(); + scene->_object1.addMover(mover1, &pt1, this); + Common::Point pt2(86, 62); + PlayerMover *mover2 = new PlayerMover(); + scene->_object5.addMover(mover2, &pt2, this); + break; + } + case 10: { + PlayerMover2 *mover = new PlayerMover2(); + scene->_object1.addMover(mover, 10, 15, &scene->_object5); + + if (!_globals->getFlag(104)) { + mover = new PlayerMover2(); + scene->_object4.addMover(mover, 10, 15, &scene->_object1); + } + setDelay(60); + break; + } + case 11: + _globals->_soundHandler.startSound(57); + _globals->_soundHandler.startSound(68); + scene->_object3.animate(ANIM_MODE_6, NULL); + + SceneItem::display(90, _globals->getFlag(104) ? 15 : 14, + SET_EXT_BGCOLOUR, 13, SET_KEEP_ONSCREEN, -1, SET_X, 120, SET_Y, 20, LIST_END); + break; + case 12: + SceneItem::display(0, 0); + _globals->_scenePalette.clearListeners(); + _globals->_sceneManager.changeScene(95); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene90::Object1::doAction(int action) { + Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(90, 7); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 97; + setAction(&scene->_sequenceManager, scene, 97, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene90::Object2::doAction(int action) { + Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_object6.postInit(); + scene->_object6.setVisage(90); + scene->_object6.setStrip(6); + scene->_object6.setPosition(Common::Point(184, 210)); + scene->_object6.hide(); + + scene->_sceneMode = 91; + scene->_soundHandler1.startSound(59); + scene->_soundHandler1.proc5(1); + scene->setAction(&scene->_sequenceManager, scene, 91, this, &scene->_object6, NULL); + break; + case CURSOR_LOOK: + SceneItem::display2(90, 8); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager, scene, 96, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene90::Scene90() : + _item1(0, CURSOR_LOOK, 90, 9, LIST_END), + _item2(0, CURSOR_LOOK, 90, 10, LIST_END), + _item3(0, CURSOR_LOOK, 90, 11, LIST_END), + _object3(OBJECT_STUNNER, 90, 13, CURSOR_LOOK, 90, 12, CURSOR_USE, 90, 16, LIST_END), + _object4(CURSOR_LOOK, 90, 17, LIST_END), + _object5(CURSOR_LOOK, 90, 18, CURSOR_USE, 90, 19, LIST_END) { +} + +void Scene90::stripCallback(int v) { + Scene90 *scene = (Scene90 *)_globals->_sceneManager._scene; + + if (v == 1) + scene->_object2.animate(ANIM_MODE_7, NULL); + else if (v == 2) + scene->_object2.animate(ANIM_MODE_NONE); +} + +void Scene90::postInit(SceneObjectList *OwnerList) { + loadScene(90); + Scene::postInit(); + + setZoomPercents(70, 10, 180, 100); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerSR); + + _speakerMText._npc = &_object2; + _speakerQText._textWidth = 160; + _speakerQText._npc = &_object5; + _speakerSText._npc = &_object1; + + _object5.postInit(); + _object5.setVisage(2333); + _object5.setObjectWrapper(new SceneObjectWrapper()); + _object5._strip = 7; + _object5._moveDiff = Common::Point(22, 22); + _object5.setPosition(Common::Point(151, 177)); + _object5.changeZoom(-1); + _globals->_sceneItems.push_back(&_object5); + + _object1.postInit(); + _object1.setVisage(2337); + _object1.setObjectWrapper(new SceneObjectWrapper()); + _object1._strip = 4; + _object1._moveDiff = Common::Point(20, 20); + _object1.setPosition(Common::Point(212, 183)); + _object1.changeZoom(-1); + _globals->_sceneItems.push_back(&_object1); + + if (!_globals->getFlag(104)) { + _object4.postInit(); + _object4.setVisage(2331); + _object4.setObjectWrapper(new SceneObjectWrapper()); + _object4._strip = 4; + _object4._moveDiff = Common::Point(20, 20); + _object4.setPosition(Common::Point(251, 207)); + _object4.changeZoom(-1); + _globals->_sceneItems.push_back(&_object4); + } + + _object2.postInit(); + _object2.setVisage(90); + _object2.animate(ANIM_MODE_1, NULL); + _object2.setPosition(Common::Point(315, 185)); + _object2._strip = 2; + _globals->_sceneItems.push_back(&_object2); + + _object3.postInit(); + _object3.setVisage(90); + _object3.animate(ANIM_MODE_1, NULL); + _object3.setPosition(Common::Point(196, 181)); + _object3.setPriority2(175); + _globals->_sceneItems.push_back(&_object3); + + _globals->_player.disableControl(); + _globals->_soundHandler.startSound(55); + _soundHandler1.startSound(52); + _soundHandler1.proc5(1); + + setAction(&_action1); + + _item3.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _item1.setBounds(Rect(271, 65, 271, 186)); + _item2.setBounds(Rect(0, 17, 124, 77)); + + _globals->_sceneItems.addItems(&_item1, &_item2, &_item3, NULL); +} + +void Scene90::signal() { + switch (_sceneMode) { + case 91: + _sceneMode = 92; + _globals->_soundHandler.startSound(77, this); + break; + case 92: + _globals->_scenePalette.clearListeners(); + _globals->_game.endGame(90, 6); + break; + case 96: + _globals->_player.enableControl(); + break; + case 97: + _stripManager._field2E8 = 0; + _action1.setActionIndex(5); + _action1.setDelay(1); + break; + default: + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 95 - Ship Close-up + * + *--------------------------------------------------------------------------*/ + +void Scene95::Action1::signal() { + Scene95 *scene = (Scene95 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _state = 6; + setDelay(60); + break; + case 1: + if (_state) { + SceneItem::display(95, _state % 2, SET_FONT, 2, + SET_EXT_BGCOLOUR, -1, SET_EXT_BGCOLOUR, 20, + SET_WIDTH, 200, SET_KEEP_ONSCREEN, 1, SET_TEXT_MODE, 1, LIST_END); + --_state; + _actionIndex = 1; + } + setDelay(60); + break; + case 2: { + scene->_soundHandler.startSound(66); + scene->_object3._numFrames = 5; + scene->_object3.animate(ANIM_MODE_5, NULL); + SceneItem::display(0, 0); + + Common::Point pt1(5, 198); + NpcMover *mover1 = new NpcMover(); + _globals->_player.addMover(mover1, &pt1, this); + + Common::Point pt2(9, 190); + NpcMover *mover2 = new NpcMover(); + scene->_object1.addMover(mover2, &pt2, NULL); + break; + } + case 3: { + scene->_soundHandler.startSound(21); + + Common::Point pt1(235, 72); + PlayerMover *mover1 = new PlayerMover(); + _globals->_player.addMover(mover1, &pt1, NULL); + + Common::Point pt2(235, 72); + PlayerMover *mover2 = new PlayerMover(); + scene->_object1.addMover(mover2, &pt2, NULL); + + SceneItem::display(95, 2, SET_Y, 45, SET_FONT, 2, + SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 13, SET_WIDTH, 200, + SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(240); + break; + } + case 4: + scene->_object3.remove(); + + SceneItem::display(95, 3, SET_Y, 45, SET_FONT, 2, + SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 35, SET_WIDTH, 200, + SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(240); + break; + case 5: + SceneItem::display(95, 4, SET_Y, 45, SET_FONT, 2, + SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 35, SET_WIDTH, 200, + SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(240); + break; + case 6: + setDelay(20); + break; + case 7: { + SceneItem::display(0, 0); + _globals->_player.setVisage(92); + _globals->_player.setPosition(Common::Point(-25, 200)); + scene->_object1.setVisage(91); + scene->_object1.setPosition(Common::Point(-22, 220)); + + scene->_soundHandler.startSound(21); + + Common::Point pt1(5, 198); + NpcMover *mover1 = new NpcMover(); + _globals->_player.addMover(mover1, &pt1, this); + + Common::Point pt2(9, 190); + NpcMover *mover2 = new NpcMover(); + scene->_object1.addMover(mover2, &pt2, NULL); + break; + } + case 8: { + Common::Point pt1(108, 112); + PlayerMover *mover1 = new PlayerMover(); + _globals->_player.addMover(mover1, &pt1, this); + + Common::Point pt2(108, 112); + PlayerMover *mover2 = new PlayerMover(); + scene->_object1.addMover(mover2, &pt2, NULL); + break; + } + case 9: + _globals->_sceneManager.changeScene(2300); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene95::Scene95() { +} + +void Scene95::postInit(SceneObjectList *OwnerList) { + loadScene(95); + Scene::postInit(); + setZoomPercents(100, 10, 200, 100); + + _globals->_player.postInit(); + _globals->_player.setVisage(2337); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player._strip = 4; + _globals->_player._moveDiff = Common::Point(30, 30); + _globals->_player.setPosition(Common::Point(-35, 200)); + _globals->_player.changeZoom(-1); + _globals->_player.disableControl(); + + _object1.postInit(); + _object1.setVisage(2333); + _object1.setPosition(Common::Point(-22, 220)); + _object1.animate(ANIM_MODE_1, NULL); + _object1.setObjectWrapper(new SceneObjectWrapper()); + _object1._moveDiff = Common::Point(30, 30); + _object1.changeZoom(-1); + + _object3.postInit(); + _object3.setVisage(96); + _object3.setPosition(Common::Point(29, 198)); + + _soundHandler.startSound(67); + setAction(&_action1); +} + +/*-------------------------------------------------------------------------- + * Scene 6100 - Sunflower navigation sequence + * + *--------------------------------------------------------------------------*/ + +void Scene6100::Action1::signal() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->showMessage(SCENE6100_CAREFUL, 13, this); + break; + case 1: + scene->showMessage(SCENE6100_TOUGHER, 35, this); + break; + case 2: + scene->showMessage(NULL, 0, NULL); + remove(); + break; + } +} + +void Scene6100::Action2::signal() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->showMessage(SCENE6100_ONE_MORE_HIT, 13, this); + break; + case 1: + scene->showMessage(SCENE6100_DOING_BEST, 35, this); + break; + case 2: + scene->showMessage(NULL, 0, NULL); + remove(); + break; + } +} + +void Scene6100::Action3::signal() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_speed = 0; + setDelay(60); + break; + case 1: + _globals->_scenePalette.clearListeners(); + scene->_fadePercent = 0; + _globals->_scenePalette.refresh(); + scene->loadScene(9997); + scene->_object1.hide(); + scene->_object2.hide(); + scene->_object3.hide(); + scene->_sunflower1.hide(); + scene->_sunflower2.hide(); + scene->_sunflower3.hide(); + scene->_rocks.hide(); + scene->_sceneText.hide(); + + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(8120, this); + break; + case 2: + scene->showMessage(SCENE6100_REPAIR, 7, this); + break; + case 3: + scene->showMessage(NULL, 0, NULL); + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(8130, this); + break; + case 4: + _globals->setFlag(76); + _globals->_sceneManager.changeScene( + (scene->_stripManager._field2E8 == 135) ? 6100 : 2320); + remove(); + break; + } +} + +void Scene6100::Action4::signal() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->showMessage(SCENE6100_ROCKY_AREA, 13, this); + break; + case 1: + scene->showMessage(SCENE6100_REPLY, 35, this); + break; + case 2: + scene->showMessage(NULL, 0, NULL); + remove(); + break; + } +} + +void Scene6100::Action5::dispatch() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + FloatSet zeroSet; + const double MULTIPLY_FACTOR = 0.01744; // 2 * pi / 360 + + if (scene->_turnAmount) { + scene->_angle = (scene->_turnAmount + scene->_angle) % 360; + + for (int objIndex = 1; objIndex <= 3; ++objIndex) { + SceneObject *obj = &scene->_object1; + if (objIndex == 2) obj = &scene->_object2; + if (objIndex == 3) obj = &scene->_object3; + + obj->_position.x += scene->_turnAmount * 2; + if (obj->_position.x >= 320) + obj->_position.x -= 480; + if (obj->_position.x < -160) + obj->_position.x += 480; + } + } + + scene->_object1._flags |= OBJFLAG_PANES; + scene->_object2._flags |= OBJFLAG_PANES; + scene->_object3._flags |= OBJFLAG_PANES; + + double distance = scene->_speed; + double angle = (double)scene->_angle * MULTIPLY_FACTOR; + scene->_probe._floats._float1 += sin(angle) * distance; + scene->_probe._floats._float2 += cos(angle) * distance; + + for (int idx = 0; idx < 4; ++idx) { + FloatSet tempSet = scene->_objList[idx]->_floats; + tempSet.add(-scene->_probe._floats._float1, -scene->_probe._floats._float2, + -scene->_probe._floats._float3); + + tempSet.proc1(scene->_angle * MULTIPLY_FACTOR); + + double sqrtVal = tempSet.sqrt(zeroSet); + if (sqrtVal != 0.0) { + scene->_objList[idx]->_position.y = static_cast<int>(13800.0 / sqrtVal + 62.0); + } + + scene->_objList[idx]->_position.x = static_cast<int>( + 160.0 - (330.0 / (tempSet._float2 + 330.0) * tempSet._float1)); + scene->_objList[idx]->dispatch(); + + if (tempSet._float2 < 0) { + scene->_objList[idx]->_position.y = 300; + + if (idx != 3) { + scene->_objList[idx]->_floats._float1 = + _globals->_randomSource.getRandomNumber(199); + scene->_objList[idx]->_floats._float2 = + _globals->_randomSource.getRandomNumber(999) + 750.0; + + scene->_objList[idx]->_floats.proc1( + -(scene->_turnAmount * 10 + scene->_angle) * MULTIPLY_FACTOR); + scene->_objList[idx]->_floats.add(scene->_probe._floats._float1, + scene->_probe._floats._float2, scene->_probe._floats._float3); + } + } + + if (idx == 3) { + scene->_rocksCheck = (ABS((int)tempSet._float1) < 100) && (tempSet._float2 > 0); + } + + scene->_objList[idx]->_flags |= OBJFLAG_PANES; +/* + if ((idx != 3) && (scene->_fadePercent == 100) && + (tempSet.sqrt(floatSet) < 150.0)) { + switch (scene->_hitCount++) { + case 1: + scene->_soundHandler.startSound(233); + scene->showMessage(0, NULL, 0); + + if (!_globals->getFlag(76)) + scene->_object5.setAction(&scene->_action2); + + case 2: + scene->_soundHandler.startSound(234); + scene->showMessage(0, NULL, 0); + + if (!_globals->getFlag(76)) + scene->_object5.setAction(NULL); + scene->setAction(&scene->_action3); + break; + + default: + scene->_soundHandler.startSound(233); + scene->showMessage(0, NULL, 0); + + if (!_globals->getFlag(76)) + scene->_object5.setAction(&scene->_action1); + break; + } + + _globals->_scenePalette.clearListeners(); + scene->_fadePercent = 0; + } + */ + } +} + +void Scene6100::GetBoxAction::signal() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_turnAmount = 0; + Common::Point pt(scene->_rocks._position.x, scene->_rocks._position.y + 10); + ProbeMover *mover = new ProbeMover(); + scene->_probe.addMover(mover, &pt, NULL); + scene->_probe.show(); + break; + } + case 1: { + scene->showMessage(SCENE6100_TAKE_CONTROLS, 35, this); + _globals->_scenePalette.clearListeners(); + + Common::Point pt(scene->_rocks._position.x, scene->_rocks._position.y - 10); + NpcMover *mover = new NpcMover(); + scene->_probe.addMover(mover, &pt, NULL); + break; + } + case 2: + scene->_probe._percent = 4; + scene->showMessage(SCENE6100_SURPRISE, 13, this); + break; + case 3: + scene->showMessage(SCENE6100_SWEAT, 35, this); + break; + case 4: + scene->showMessage(SCENE6100_VERY_WELL, 13, this); + break; + case 5: + scene->showMessage(NULL, 0, NULL); + _globals->_sceneManager.changeScene(2320); + remove(); + } +} + +void Scene6100::GetBoxAction::dispatch() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + if (!scene->_probe._mover && (scene->_getBoxAction._actionIndex >= 1)) { + if (scene->_getBoxAction._actionIndex == 1) { + scene->_speed = 0; + scene->_getBoxAction.signal(); + } + + if (scene->_probe._percent > 4) + // Handle the probe disappearing into the rocks + scene->_probe._percent = scene->_probe._percent * 7 / 8; + scene->_probe._flags |= OBJFLAG_PANES; + } + + Action::dispatch(); +} + +void Scene6100::Action7::signal() { + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + setDelay(90); + break; + case 2: + _globals->_sceneManager.changeScene(2100); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene6100::ProbeMover::dispatch() { + Scene6100 *scene = (Scene6100 *)_globals->_sceneManager._scene; + + if (!dontMove()) { + if (scene->_speed > 0) { + scene->_action5.dispatch(); + scene->_speed = (scene->_speed * 4) / 5; + } + } + + NpcMover::dispatch(); +} + +/*--------------------------------------------------------------------------*/ + +void Scene6100::Item1::doAction(int action) { + SceneItem::display2(4000, 0); +} + +/*--------------------------------------------------------------------------*/ + +void Scene6100::postInit(SceneObjectList *OwnerList) { + loadScene(6100); + Scene::postInit(); + setZoomPercents(62, 2, 200, 425); + + _globals->_player.disableControl(); + _globals->_events.setCursor(CURSOR_WALK); + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerSL); + + _object1.postInit(); + _object1.setVisage(6100); + _object1._frame = 1; + _object1._strip = 4; + _object1.setPosition(Common::Point(0, 60)); + _object1.setPriority2(1); + + _object2.postInit(); + _object2.setVisage(6100); + _object2._frame = 1; + _object2._strip = 4; + _object2.setPosition(Common::Point(160, 60)); + _object2.setPriority2(1); + + _object3.postInit(); + _object3.setVisage(6100); + _object3._frame = 1; + _object3._strip = 4; + _object3.setPosition(Common::Point(320, 60)); + _object3.setPriority2(1); + + _rocks.postInit(); + _rocks.setVisage(6100); + _rocks._frame = 1; + _rocks._strip = 3; + _rocks.setPosition(Common::Point(320, 0)); + _rocks.setPriority2(2); + _rocks.changeZoom(-1); + _rocks._floats._float1 = 320.0; + _rocks._floats._float2 = 25000.0; + _rocks._floats._float3 = 0.0; + + _probe.postInit(); + _probe._moveDiff = Common::Point(15, 15); + _probe.setVisage(6100); + _probe._frame = 1; + _probe._strip = 5; + _probe.setPosition(Common::Point(160, 260)); + _probe.setPriority2(3); + _probe._floats._float1 = 320.0; + _probe._floats._float2 = 0.0; + _probe._floats._float3 = 0.0; + _probe.hide(); + + _objList[0] = &_sunflower1; + _objList[1] = &_sunflower2; + _objList[2] = &_sunflower3; + _objList[3] = &_rocks; + + int baseVal = 2000; + for (int idx = 0; idx < 3; ++idx) { + _objList[idx]->_floats._float1 = _globals->_randomSource.getRandomNumber(999); + _objList[idx]->_floats._float2 = baseVal; + _objList[idx]->_floats._float3 = 0.0; + baseVal += _globals->_randomSource.getRandomNumber(499); + + _objList[idx]->postInit(); + _objList[idx]->setVisage(6100); + _objList[idx]->_frame = 1; + _objList[idx]->_strip = 2; + + _objList[idx]->setPosition(Common::Point( + _globals->_randomSource.getRandomNumber(319), 60)); + _objList[idx]->setPriority2(1); + _objList[idx]->changeZoom(-1); + } + + _speed = 30; + _fadePercent = 100; + _rocksCheck = false; + _hitCount = 0; + _turnAmount = 0; + _angle = 0; + _msgActive = false; + + setAction(&_action5); + _globals->_scenePalette.addRotation(96, 143, -1); + + if (!_globals->getFlag(76)) + _probe.setAction(&_action4); + + _globals->_soundHandler.startSound(231); +} + +void Scene6100::remove() { + _globals->_player.disableControl(); + _globals->_scenePalette.clearListeners(); + Scene::remove(); +} + +void Scene6100::process(Event &event) { + Scene::process(event); + + if (event.eventType == EVENT_KEYPRESS) { + // Handle incremental turning speeds with arrow keys + if ((event.kbd.keycode == Common::KEYCODE_LEFT) || (event.kbd.keycode == Common::KEYCODE_KP4)) { + _turnAmount = MAX(_turnAmount - 1, -8); + } else if ((event.kbd.keycode == Common::KEYCODE_RIGHT) || (event.kbd.keycode == Common::KEYCODE_KP6)) { + _turnAmount = MIN(_turnAmount + 1, -8); + } + } + + if (_probe._action) + _probe._action->process(event); +} + +void Scene6100::dispatch() { + Scene::dispatch(); + + if (_probe._action) + _probe._action->dispatch(); + + // Handle mouse controlling the turning + int changeAmount = (_globals->_events._mousePos.x - 160) / -20; + _turnAmount += (changeAmount - _turnAmount) / 2; + + if (_fadePercent < 100) { + _fadePercent += 10; + if (_fadePercent >= 100) { + _globals->_scenePalette.addRotation(96, 143, -1); + _fadePercent = 100; + } + + byte adjustData[] = {0xff, 0xff, 0xff, 0}; + _globals->_scenePalette.fade(adjustData, false, _fadePercent); + } + + if (_action != &_action3) { + // Display the distance remaining to the target + int distance = (int)_probe._floats.sqrt(_rocks._floats); + Common::String s = Common::String::format("%06d", distance); + + _sceneText.setPosition(Common::Point(24, 160)); + _sceneText._fontNumber = 0; + _sceneText._colour1 = 35; + _sceneText.setup(s); + } + + if (_rocksCheck && (_action == &_action5)) { + // Check whether the probe is close enough to the rocks + double distance = _probe._floats.sqrt(_rocks._floats); + + if ((distance >= 300.0) && (distance <= 500.0)) + setAction(&_getBoxAction); + } +} + +void Scene6100::showMessage(const Common::String &msg, int colour, Action *action) { + if (_msgActive) { + _msgActive = false; + _speaker1.removeText(); + } + + if (!msg.empty()) { + _msgActive = true; + _speaker1._textPos.x = 20; + _speaker1._textWidth = 280; + _speaker1._colour1 = colour; + _speaker1._action = action; + _speaker1.setText(msg); + } +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes1.h b/engines/tsage/ringworld_scenes1.h new file mode 100644 index 0000000000..b567aeea2d --- /dev/null +++ b/engines/tsage/ringworld_scenes1.h @@ -0,0 +1,557 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES1_H +#define TSAGE_RINGWORLD_SCENES1_H + +#include "common/scummsys.h" +#include "tsage/ringworld_logic.h" +#include "tsage/converse.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +class Scene10 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; +public: + Speaker _speakerSText; + Speaker _speakerQText; + Action1 _action1; + Action2 _action2; + SceneObject _object1, _object2, _object3; + SceneObject _object4, _object5, _object6; + + virtual void stripCallback(int v); + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene15 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + virtual void dispatch(); + }; +public: + Action1 _action1; + SceneObject _object1; + SoundHandler _soundHandler; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene20 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; +public: + SequenceManager _sequenceManager; + SpeakerQText _speakerQText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + SceneObject _sceneObject1, _SceneObjectExt, _sceneObject3, _sceneObject4, _sceneObject5; + SoundHandler _sound; +public: + Scene20(); + virtual ~Scene20() {} + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); +}; + +class Scene30 : public Scene { + /* Scene objects */ + // Doorway beam sensor + class BeamObject : public SceneObject { + public: + virtual void doAction(int action) { + if (action == OBJECT_SCANNER) + display(30, 14, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else if (action == CURSOR_LOOK) + display(30, 2, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else if (action == CURSOR_USE) { + Scene30 *parent = (Scene30 *)_globals->_sceneManager._scene; + parent->setAction(&parent->_beamAction); + } else + SceneObject::doAction(action); + } + }; + + // Doorway object + class DoorObject : public SceneObject { + public: + virtual void doAction(int action) { + if (action == OBJECT_SCANNER) + display(30, 13, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else if (action == CURSOR_LOOK) + display(30, 1, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else if (action == CURSOR_USE) + display(30, 7, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneObject::doAction(action); + } + }; + + // Kzin object + class KzinObject : public SceneObject { + public: + virtual void doAction(int action); + }; + + /* Actions */ + class BeamAction : public Action { + public: + virtual void signal(); + }; + class KzinAction : public Action { + public: + virtual void signal(); + }; + class RingAction : public Action { + public: + virtual void signal(); + }; + class TalkAction : public Action { + public: + virtual void signal(); + }; + +public: + SoundHandler _sound; + DisplayHotspot _groundHotspot, _wallsHotspot, _courtyardHotspot, _treeHotspot; + BeamObject _beam; + DoorObject _door; + KzinObject _kzin; + + BeamAction _beamAction; + KzinAction _kzinAction; + RingAction _ringAction; + TalkAction _talkAction; + SequenceManager _sequenceManager; + + SpeakerSR _speakerSR; + SpeakerQL _speakerQL; + SpeakerSText _speakerSText; + SpeakerQText _speakerQText; +public: + Scene30(); + virtual ~Scene30() {} + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); +}; + +class Scene40 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + + /* Objects */ + class DyingKzin : public SceneObject { + public: + virtual void doAction(int action); + }; + class Assassin : public SceneObject { + public: + virtual void doAction(int action); + }; + + /* Items */ + class Item2 : public SceneItem { + public: + virtual void doAction(int action); + }; + class Item6 : public SceneItem { + public: + virtual void doAction(int action); + }; + class Item8 : public SceneItem { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SpeakerSL _speakerSL; + SpeakerQR _speakerQR; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + SpeakerGameText _speakerGameText; + SoundHandler _soundHandler; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + SceneObject _object1, _object2, _object3; + DyingKzin _dyingKzin; + Assassin _assassin; + SceneObject _doorway, _object7, _object8; + DisplayHotspot _item1; + Item2 _item2; + DisplayHotspot _item3, _item4, _item5; + Item6 _item6; + DisplayHotspot _item7, _item8; + + Scene40(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene50 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + + /* Objects */ + class Object1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object4 : public SceneObject { + public: + virtual void doAction(int action); + }; + +public: + SequenceManager _sequenceManager; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Object1 _object1; + Object2 _object2; + Object3 _object3; + Object4 _object4; + Rect _doorwayRect; + SpeakerSText _speakerSText; + SpeakerQText _speakerQText; + DisplayHotspot _item0, _item1, _item2; + DisplayHotspot _item3, _item4, _item5; + + Scene50(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene60 : public Scene { + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Object2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class SlaveObject : public SceneObjectExt { + public: + virtual void doAction(int action); + }; + class Object8 : public SceneObjectExt { + public: + virtual void doAction(int action); + }; + class Object9 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Item1 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class Item : public SceneHotspot { + public: + int _messageNum, _sceneMode; + + Item(int sceneRegionId, int messageNum, int sceneMode) { + _sceneRegionId = sceneRegionId; + _messageNum = messageNum; + _sceneMode = sceneMode; + } + virtual void doAction(int action); + }; + +public: + GfxButton _gfxButton; + SequenceManager _sequenceManager; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + Action1 _action1; + Action2 _action2; + SceneObject _object1; + Object2 _object2; + Object3 _object3; + Object4 _object4; + Object5 _object5; + Object6 _object6; + SlaveObject _slaveButton; + Object8 _object8; + Object9 _object9; + SceneObject _object10; + Item1 _item1; + Item _item2, _item3, _item4, _item5, _item6; + SoundHandler _soundHandler1; + SoundHandler _soundHandler2; + SoundHandler _soundHandler3; + + Scene60(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); +}; + +class Scene90 : public Scene { + class Action1 : public Action { + public: + virtual void signal(); + }; + class Object1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object2 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SpeakerSText _speakerSText; + SpeakerQText _speakerQText; + SpeakerQL _speakerQL; + SpeakerSR _speakerSR; + SpeakerMText _speakerMText; + Action1 _action1; + Object1 _object1; + Object2 _object2; + DisplayObject _object3, _object4, _object5; + SceneObject _object6; + DisplayHotspot _item1, _item2, _item3; + SoundHandler _soundHandler1, _soundHandler2; + + Scene90(); + + virtual void stripCallback(int v); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); +}; + +class Scene95 : public Scene { + class Action1 : public ActionExt { + public: + virtual void signal(); + }; + +public: + Action1 _action1; + int _field326; + SceneObject _object1, _object2, _object3; + SoundHandler _soundHandler; + + Scene95(); + virtual void postInit(SceneObjectList *OwnerList); +}; + +class Scene6100 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void dispatch(); + }; + class GetBoxAction : public Action { + public: + virtual void signal(); + virtual void dispatch(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + + /* Objects */ + class Object : public SceneObject { + public: + FloatSet _floats; + }; + class ProbeMover : public NpcMover { + public: + virtual void dispatch(); + }; + + /* Items */ + class Item1 : public SceneItem { + public: + virtual void doAction(int action); + }; + +public: + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + GetBoxAction _getBoxAction; + Action7 _action7; + SoundHandler _soundHandler; + Speaker _speaker1; + SpeakerQR _speakerQR; + SpeakerSL _speakerSL; + SceneObject _object1, _object2, _object3; + Object _rocks, _probe; + Object _sunflower1, _sunflower2, _sunflower3; + SceneText _sceneText; + SceneItem _item1; + + int _turnAmount, _angle, _speed, _fadePercent; + int _hitCount; + bool _rocksCheck; + Object *_objList[4]; + bool _msgActive; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void remove(); + virtual void process(Event &event); + virtual void dispatch(); + void showMessage(const Common::String &msg, int colour, Action *action); + +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes10.cpp b/engines/tsage/ringworld_scenes10.cpp new file mode 100644 index 0000000000..30a0ffd34e --- /dev/null +++ b/engines/tsage/ringworld_scenes10.cpp @@ -0,0 +1,2064 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "graphics/cursorman.h" +#include "tsage/ringworld_scenes10.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +Scene2::Scene2() : Scene() { + _sceneState = 0; +} + +/*--------------------------------------------------------------------------*/ + +void Object9350::postInit(SceneObjectList *OwnerList) { + _globals->_sceneManager.postInit(&_globals->_sceneManager._altSceneObjects); +} + +void Object9350::draw() { + reposition(); + Rect destRect = _bounds; + destRect.translate(-_globals->_sceneOffset.x, -_globals->_sceneOffset.y); + Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(_globals->_sceneManager._scene->_stripManager._stripNum); + GfxSurface frame = getFrame(); + _globals->gfxManager().copyFrom(frame, destRect, priorityRegion); +} + +/*-------------------------------------------------------------------------- + * Scene 9100 + * + *--------------------------------------------------------------------------*/ +void Scene9100::SceneHotspot1::doAction(int action) { + Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene; + + if (action == CURSOR_TALK) { + if (_globals->getFlag(23)) { + _globals->_player.disableControl(); + scene->_sceneMode = 9104; + } else { + _globals->setFlag(23); + _globals->_player.disableControl(); + scene->_sceneMode = 9105; + } + scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &_globals->_player, &scene->_object5, &scene->_object6, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9100::dispatch() { + Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene; + + if (!_action) { + if (_globals->_player._position.x < 25) { + if (!_globals->getFlag(11)) { + scene->_sceneMode = 9106; + } else { + scene->_sceneMode = 9108; + _globals->setFlag(11); + } + } else { + scene->_sceneMode = 9106; + } + scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, &_globals->_player, 0); + } else { + Scene::dispatch(); + } +} + +void Scene9100::signal() { + Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene; + + switch (scene->_sceneMode) { + case 9102: + case 9106: + case 9108: + _globals->_sceneManager.changeScene(9150); + break; + case 9105: + _sceneHotspot1.remove(); + // No break on purpose + case 9103: + case 9104: + case 9107: + case 9109: + default: + _globals->_player.enableControl(); + break; + } +} + +void Scene9100::postInit(SceneObjectList *OwnerList) { + Scene9100 *scene = (Scene9100 *)_globals->_sceneManager._scene; + + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + _object1.postInit(); + _object1.setVisage(9100); + _object1._strip = 1; + _object1._numFrames = 6; + _object1.setPosition(Common::Point(297, 132), 0); + _object1.animate(ANIM_MODE_2, 0); + _object1.setPriority2(10); + + _globals->_player.postInit(); + + _object2.postInit(); + _object2.hide(); + + _object3.postInit(); + _object3.hide(); + + _object4.postInit(); + _object4.hide(); + + _object5.postInit(); + _object5.hide(); + + if (!_globals->getFlag(23)) { + _object6.postInit(); + _object6.setVisage(9111); + _object6.setStrip(6); + _object6.setFrame(1); + _object6.setPosition(Common::Point(138, 166), 0); + _sceneHotspot3.setup(145, 125, 166, 156, 9100, 40, 43); + } + _sceneHotspot1.setup(140, 176, 185, 215, 9100, 36, 37); + _sceneHotspot2.setup(161, 138, 182, 175, 9100, 38, 39); + _sceneHotspot4.setup(37, 196, 47, 320, 9100, 44, -1); + _sceneHotspot5.setup(69, 36, 121, 272, 9100, 45, 46); + _sceneHotspot6.setup(127, 0, 200, 52, 9100, 47, 48); + + _globals->_soundHandler.startSound(251, 0, 127); + if (_globals->_sceneManager._previousScene == 9150) { + if (_globals->getFlag(20)) { + _globals->_player.disableControl(); + if (_globals->getFlag(11)) + _sceneMode = 9107; + else + _sceneMode = 9109; + setAction(&scene->_sequenceManager, scene, _sceneMode, &_globals->_player, &_object5, 0); + } else { + _sceneMode = 9103; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager, scene, _sceneMode, &_globals->_player, &_object2, &_object3, &_object4, &_object5, 0); + _globals->setFlag(20); + } + } else { + _sceneMode = 9102; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager, scene, _sceneMode, &_globals->_player, &_object2, &_object3, &_object4, &_object5, 0); + } +} + +/*-------------------------------------------------------------------------- + * Scene 9150 + * + *--------------------------------------------------------------------------*/ +void Scene9150::Object3::signal() { + switch (_signalFlag++) { + case 0: + _timer = 10 + _globals->_randomSource.getRandomNumber(90); + break; + default: + animate(ANIM_MODE_5, this); + _signalFlag = 0; + break; + } +} + +void Scene9150::Object3::dispatch() { + SceneObject::dispatch(); + if ((_timer != 0) && (--_timer == 0)) + signal(); +} + +void Scene9150::signal() { + switch (_sceneMode) { + case 9151: + case 9157: + _globals->_sceneManager.changeScene(9100); + break; + case 9153: + _globals->_sceneManager.changeScene(9300); + break; + case 9152: + case 9155: + case 9156: + _globals->_player.enableControl(); + break; + case 9154: + default: + break; + } +} + +void Scene9150::dispatch() { + + if ((_sceneState != 0) && (_sceneBounds.left == 0)) { + _object3._timer = 0; + _sceneState = 0; + _sceneHotspot3.setAction(&_sequenceManager2, 0, 9154, &_object3, 0); + _sceneHotspot10.remove(); + } + + if (_action) { + _action->dispatch(); + } else { + if (_globals->_player._position.x >= 160) { + if (_globals->_player._position.x > 630) { + _globals->_player.disableControl(); + _sceneMode = 9157; + setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0); + } + } else { + _globals->_player.disableControl(); + if (_globals->getFlag(11)) { + _globals->_soundHandler.startSound(286, 0, 127); + _sceneMode = 9153; + } else { + _sceneMode = 9156; + } + setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0); + } + } +} + +void Scene9150::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + _globals->_player.postInit(); + + _object3.postInit(); + _sceneState = 1; + _object3.setVisage(9151); + _object3._strip = 1; + _object3._frame = 1; + _object3.setPosition(Common::Point(312, 95), 0); + _object3.signal(); + + _sceneHotspot1.setup(0, 0, 200, 94, 9150, 46, -1); + _sceneHotspot2.setup(51, 90, 118, 230, 9150, 47, -1); + _sceneHotspot3.setup(182, 104, 200, 320, 9150, 48, 49); + _sceneHotspot4.setup(103, 292, 152, 314, 9150, 50, 51); + _sceneHotspot5.setup(115, 350, 160, 374, 9150, 52, 53); + _sceneHotspot6.setup(0, 471, 200, 531, 9150, 54, 55); + _sceneHotspot7.setup(170, 320, 185, 640, 9150, 56, -1); + _sceneHotspot9.setup(157, 107, 186, 320, 9150, 56, -1); + _sceneHotspot8.setup(133, 584, 142, 640, 9150, 57, -1); + _sceneHotspot10.setup(83, 304, 103, 323, 9150, 58, 59); + + _globals->_soundHandler.startSound(285, 0, 127); + _globals->_player.disableControl(); + + if (_globals->getFlag(20)) { + // Walking alone + _globals->_scrollFollower = &_globals->_player; + if (_globals->getFlag(11)) + // Hero wearing peasan suit + _sceneMode = 9155; + else + // Hero wearing Purple suit + _sceneMode = 9152; + setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, 0); + } else { + // Walking with the tiger + _sceneMode = 9151; + _object2.postInit(); + _object2.hide(); + _object1.postInit(); + setAction(&_sequenceManager1, this, _sceneMode, &_globals->_player, &_object1, &_object2, 0); + } +} + +/*-------------------------------------------------------------------------- + * Scene 9200 + * + *--------------------------------------------------------------------------*/ +void Scene9200::SceneHotspot1::doAction(int action) { + Scene9200 *scene = (Scene9200 *)_globals->_sceneManager._scene; + + if (action == OBJECT_TUNIC) { + _globals->_player.disableControl(); + if (_globals->getFlag(93)) { + scene->_sceneState = 9214; + setAction(&scene->_sequenceManager, scene, 9214, &_globals->_player, &scene->_object2, 0); + } else { + _globals->setFlag(93); + scene->_sceneState = 9213; + setAction(&scene->_sequenceManager, scene, 9213, &_globals->_player, &scene->_object2, 0); + } + } else if (action <= 100) { + _globals->_player.disableControl(); + scene->_sceneState = 9214; + setAction(&scene->_sequenceManager, scene, 9214, &_globals->_player, &scene->_object2, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9200::signal() { + switch (_sceneState++) { + case 9207: + _globals->_sceneManager.changeScene(9700); + break; + case 9208: + case 9211: + case 9212: + _globals->_sceneManager.changeScene(9500); + break; + case 9209: + _globals->_sceneManager.changeScene(9360); + break; + case 9210: + _hotspot1.remove(); + // No break on purpose + case 9201: + case 9202: + case 9203: + case 9204: + case 9205: + case 9206: + default: + _globals->_player.enableControl(); + break; + } +} + +void Scene9200::process(Event &event) { + Scene::process(event); +} + +void Scene9200::dispatch() { +// Rect rect9200 = Rect(320, 175, 250, 154); + Rect rect9200 = Rect(250, 154, 320, 175); + + if (_action) { + _action->dispatch(); + } else { + if ( (_globals->_player._position.x <= 0) || ((_globals->_player._position.x < 100) && (_globals->_player._position.y > 199))) { + _globals->_player.disableControl(); + _sceneState = 9209; + setAction(&_sequenceManager, this, 9209, &_globals->_player, &_object2, &_object3, 0); + } else { + if (rect9200.contains(_globals->_player._position)) { + if (_globals->getFlag(93)) { + if (_globals->getFlag(86)) { + _sceneState = 9215; + setAction(&_sequenceManager, this, 9215, &_globals->_player, &_object2, &_object3, 0); + } else { + _sceneState = 9208; + setAction(&_sequenceManager, this, 9208, &_globals->_player, &_object2, &_object3, 0); + } + } else { + _globals->_player.disableControl(); + _sceneState = 9204; + setAction(&_sequenceManager, this, 9204, &_globals->_player, &_object2, &_object3, 0); + } + } else { + if (_globals->_player._position.y < 140) { + _globals->_player.disableControl(); + _sceneState = 9207; + setAction(&_sequenceManager, this, 9207, &_globals->_player, &_object2, &_object3, 0); + } + } + } + } +} + +void Scene9200::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(130, 50, 200, 150); + + _globals->_player.postInit(); + _object3.postInit(); + _object3.hide(); + _object1.postInit(); + // Water animation + _object1.setVisage(9200); + _object1._strip = 3; + _object1.animate(ANIM_MODE_2, 0); + _object1.setPosition(Common::Point(132, 114), 0); + _object1.setPriority2(140); + _soundHandler.startSound(297, 0, 127); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerGR); + _stripManager.addSpeaker(&_speakerGText); + + if (!_globals->getFlag(86)) { + _object2.postInit(); + _hotspot1.setup(96, 194, 160, 234, 9200, 29, 31); + } + _hotspot2.setup(164, 0, 200, 282, 9200, 0, 1); + _hotspot3.setup(140, 39, 165, 153, 9200, 2, 3); + _hotspot4.setup(92, 122, 139, 152, 9200, 4, 5); + _hotspot5.setup(33, 20, 142, 115, 9200, 6, 7); + _hotspot6.setup(104, 235, 153, 265, 9200, 8, 9); + _hotspot7.setup(107, 262, 153, 286, 9200, 10, 11); + _hotspot8.setup(69, 276, 164, 320, 9200, 12, 13); + + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.disableControl(); + + switch (_globals->_sceneManager._previousScene) { + case 9500: + if (_globals->getFlag(85)) { + if (_globals->_inventory._helmet._sceneNumber == 1) { + _globals->setFlag(86); + _sceneState = 9210; + setAction(&_sequenceManager, this, 9210, &_globals->_player, &_object2, &_object3, 0); + } else { + _sceneState = 9212; + setAction(&_sequenceManager, this, 9212, &_globals->_player, &_object2, &_object3, 0); + } + } else { + if (_globals->_inventory._helmet._sceneNumber == 1) { + _sceneState = 9211; + setAction(&_sequenceManager, this, 9211, &_globals->_player, &_object2, &_object3, 0); + } else { + _sceneState = 9202; + setAction(&_sequenceManager, this, 9202, &_globals->_player, &_object2, &_object3, 0); + } + } + break; + case 9700: + if (_globals->getFlag(86)) { + _sceneState = 9206; + setAction(&_sequenceManager, this, 9206, &_globals->_player, &_object2, &_object3, 0); + } else { + _sceneState = 9203; + setAction(&_sequenceManager, this, 9203, &_globals->_player, &_object2, &_object3, 0); + } + break; + case 9360: + default: + if (_globals->getFlag(86)) { + _sceneState = 9205; + setAction(&_sequenceManager, this, 9205, &_globals->_player, &_object2, &_object3, 0); + } else { + _sceneState = 9201; + setAction(&_sequenceManager, this, 9201, &_globals->_player, &_object2, &_object3, 0); + } + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 9300 + * + *--------------------------------------------------------------------------*/ +void Scene9300::signal() { + switch (_sceneMode++) { + case 9301: + _globals->setFlag(84); + // No break on purpose + case 9303: + _globals->_soundHandler.startSound(295, 0, 127); + _globals->_sceneManager.changeScene(9350); + break; + case 9302: + _globals->_player.enableControl(); + break; + default: + break; + } +} + +void Scene9300::dispatch() { + if (_action) { + _action->dispatch(); + } else if (_globals->_player._position.y < 145) { + _globals->_player.disableControl(); + _sceneMode = 9303; + setAction(&_sequenceManager, this, 9303, &_globals->_player, &_object1, &_object2, 0); + } +} + +void Scene9300::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(130, 75, 230, 150); + + _sceneMode = 0; + _globals->_player.postInit(); + _globals->_player.changeZoom(-1); + _object1.postInit(); + _object2.postInit(); + _globals->_soundHandler.startSound(289, 0, 127); + + _hotspot1.setup(35, 142, 76, 212, 9300, 0, 1); + _hotspot2.setup(28, 90, 81, 143, 9300, 2, 3); + _hotspot3.setup(78, 142, 146, 216, 9300, 4, 5); + _hotspot4.setup(3, 43, 91, 74, 9300, 6, 7); + _hotspot5.setup(82, 19, 157, 65, 9300, 8, 9); + _hotspot6.setup(5, 218, 84, 274, 9300, 10, 11); + _hotspot7.setup(86, 233, 168, 293, 9300, 12, 13); + _hotspot8.setup(157, 0, 200, 230, 9300, 14, 15); + _hotspot9.setup(169, 227, 200, 320, 9300, 16, 17); + _hotspot10.setup(145, 97, 166, 225, 9300, 18, 19); + _hotspot11.setup(81, 75, 145, 145, 9300, 20, 21); + _hotspot12.setup(0, 0, 94, 35, 9300, 22, 23); + _hotspot13.setup(12, 268, 149, 320, 9300, 24, 25); + + if (_globals->_sceneManager._previousScene == 9350) { + _globals->_player.disableControl(); + _sceneMode = 9302; + setAction(&_sequenceManager, this, 9302, &_globals->_player, &_object1, &_object2, 0); + } else { + _globals->_player.disableControl(); + _sceneMode = 9301; + setAction(&_sequenceManager, this, 9301, &_globals->_player, &_object1, &_object2, 0); + } +} + +/*-------------------------------------------------------------------------- + * Scene 9350 + * + *--------------------------------------------------------------------------*/ + +void Scene9350::signal() { + switch (_sceneState ++) { + case 0: + case 9352: + case 9353: + case 9354: + _globals->_player.enableControl(); + break; + case 9355: + _globals->_sceneManager.changeScene(9300); + break; + case 9356: + _globals->_sceneManager.changeScene(9360); + break; + case 9357: + case 9359: + _globals->_sceneManager.changeScene(9400); + break; + default: + break; + } +} + +void Scene9350::dispatch() { + if (_action == 0) { + if ((_globals->_player._position.x > 300) && (_globals->_player._position.y < 160)) { + _globals->_player.disableControl(); + _sceneState = 9356; + setAction(&_sequenceManager, this, 9356, &_globals->_player, &_object2, 0); + } else if ((_globals->_player._position.x > 110) && (_globals->_player._position.y >= 195)) { + _globals->_player.disableControl(); + _sceneState = 9357; + setAction(&_sequenceManager, this, 9357, &_globals->_player, &_object2, 0); + } else if ((_globals->_player._position.x < 10) || ((_globals->_player._position.x <= 110) && (_globals->_player._position.y >= 195))) { + _globals->_player.disableControl(); + _sceneState = 9355; + setAction(&_sequenceManager, this, 9355, &_globals->_player, &_object2, 0); + } + } else { + Scene::dispatch(); + } +} + +void Scene9350::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(95, 80, 200, 100); + _globals->_player.postInit(); + + _object1.setup(9350, 1, 3, 139, 97, 0); + _sceneHotspot1.setup(42, 0, 97, 60, 9350, 0, -1); + _sceneHotspot2.setup(37, 205, 82, 256, 9350, 0, -1); + _sceneHotspot3.setup(29, 93, 92, 174, 9350, 1, -1); + _sceneHotspot4.setup(0, 308, 109, 320, 9350, 2, -1); + _sceneHotspot5.setup(0, 0, 200, 320, 9350, 3, -1); + + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.disableControl(); + + if (_globals->_sceneManager._previousScene == 9360) { + _globals->_player.disableControl(); + _sceneState = 9352; + setAction(&_sequenceManager, this, 9352, &_globals->_player, &_object2, 0); + } else if (_globals->_sceneManager._previousScene == 9400) { + _globals->_player.disableControl(); + _sceneState = 9353; + setAction(&_sequenceManager, this, 9353, &_globals->_player, &_object2, 0); + } else { + if (!_globals->getFlag(84)) { + _globals->clearFlag(84); + _object2.postInit(); + _globals->_player.disableControl(); + _sceneState = 9359; + setAction(&_sequenceManager, this, 9359, &_globals->_player, &_object2, 0); + } else { + _globals->_player.disableControl(); + _sceneState = 9354; + setAction(&_sequenceManager, this, 9354, &_globals->_player, &_object2, 0); + } + } +} + +/*-------------------------------------------------------------------------- + * Scene 9360 + * + *--------------------------------------------------------------------------*/ + +void Scene9360::signal() { + switch (_sceneState ++) { + case 0: + case 9362: + case 9363: + case 9364: + _globals->_player.enableControl(); + break; + case 9365: + _globals->_sceneManager.changeScene(9350); + break; + case 9366: + _globals->_sceneManager.changeScene(9200); + break; + case 9367: + _globals->_sceneManager.changeScene(9450); + break; + default: + break; + } +} + +void Scene9360::dispatch() { + if (_action == 0) { + if ((_globals->_player._position.x > 300) && (_globals->_player._position.y < 160)) { + _globals->_player.disableControl(); + _sceneState = 9366; + setAction(&_sequenceManager, this, 9366, &_globals->_player, 0); + } else if ((_globals->_player._position.x > 110) && (_globals->_player._position.y >= 195)) { + _globals->_player.disableControl(); + _sceneState = 9367; + setAction(&_sequenceManager, this, 9367, &_globals->_player, 0); + } else if ((_globals->_player._position.x < 10) || ((_globals->_player._position.x <= 110) && (_globals->_player._position.y >= 195))) { + _globals->_player.disableControl(); + _sceneState = 9365; + setAction(&_sequenceManager, this, 9365, &_globals->_player, 0); + } + } else { + Scene::dispatch(); + } +} + +void Scene9360::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(95, 80, 200, 100); + _globals->_player.postInit(); + + _hotspot1.setup(37, 92, 93, 173, 9360, 0, 1); + _hotspot2.setup(42, 0, 100, 63, 9360, 2, -1); + _hotspot3.setup(36, 205, 82, 260, 9360, 3, -1); + _hotspot4.setup(103, 2, 200, 320, 9360, 4, -1); + _hotspot5.setup(0, 0, 37, 320, 9360, 4, -1); + _hotspot6.setup(35, 61, 103, 92, 9360, 4, -1); + _hotspot7.setup(33, 174, 93, 207, 9360, 4, -1); + _hotspot8.setup(28, 257, 149, 320, 9360, 4, -1); + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.disableControl(); + if (_globals->_sceneManager._previousScene == 9350) { + _globals->_player.disableControl(); + _sceneState = 9364; + setAction(&_sequenceManager, this, 9364, &_globals->_player, 0); + } else if (_globals->_sceneManager._previousScene == 9450) { + _globals->_player.disableControl(); + _sceneState = 9363; + setAction(&_sequenceManager, this, 9363, &_globals->_player, 0); + } else { + _globals->_player.disableControl(); + _sceneState = 9362; + setAction(&_sequenceManager, this, 9362, &_globals->_player, 0); + } + _object1.setup(9351, 1, 1, 131, 90, 0); +} + +/*-------------------------------------------------------------------------- + * Scene 9400 + * + *--------------------------------------------------------------------------*/ +Scene9400::Scene9400() { + _field1032 = 0; +} + +void Scene9400::SceneHotspot7::doAction(int action) { + Scene9400 *scene = (Scene9400 *)_globals->_sceneManager._scene; + + if ((action == CURSOR_USE) && (_globals->_inventory._straw._sceneNumber != 1)) { + scene->_sceneState = 1; + scene->setAction(&scene->_sequenceManager, scene, 9408, &_globals->_player, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9400::SceneHotspot8::doAction(int action) { + Scene9400 *scene = (Scene9400 *)_globals->_sceneManager._scene; + + if (action == CURSOR_TALK) { + _globals->_player.disableControl(); + scene->_sceneState = 2; + scene->signal(); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9400::signal() { + switch (_sceneState ++) { + case 0: + _object1._numFrames = 6; + _stripManager.start(9400, this); + break; + case 1: + _object1._numFrames = 6; + _object1.animate(ANIM_MODE_2, 0); + _globals->_player.enableControl(); + break; + case 2: + _object1.animate(ANIM_MODE_5, this); + break; + case 3: + _stripManager.start(9405, this); + break; + case 4: + _object1.animate(ANIM_MODE_2, this); + _globals->_player.enableControl(); + break; + case 9350: + _globals->_sceneManager.changeScene(9350); + break; + default: + break; + } +} + +void Scene9400::dispatch() { + if ((_object1._animateMode == 2) && (_object1._strip == 1) && (_object1._frame == 4)){ + if (_field1032 == 0) { + _soundHandler.startSound(296, 0, 127); + _field1032 = 1; + } + } else { + _field1032 = 0; + } + if (_action == 0) { + if (_globals->_player._position.y < 120) { + _sceneState = 9350; + _globals->_player.disableControl(); + setAction(&_action1); + Common::Point pt(-45, 88); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + } + } else { + Scene::dispatch(); + } +} + +void Scene9400::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + _sceneNumber = 9400; + setZoomPercents(0, 100, 200, 100); + _globals->_player.postInit(); + _object1.postInit(0); + _object3.postInit(0); + _speakerQText._textPos.x = 20; + + _hotspot7.setup(157, 66, 180, 110, 9400, 21, 23); + _hotspot5.setup(130, 133, 152, 198, 9400, 22, -1); + _hotspot1.setup(33, 280, 69, 297, 9400, 1, 2); + _hotspot2.setup(73, 96, 87, 159, 9400, 3, 4); + _hotspot3.setup(89, 253, 111, 305, 9400, 5, 6); + _hotspot4.setup(46, 0, 116, 35, 9400, 7, 8); + _hotspot8.setup(58, 169, 122, 200, 9400, 9, 10); + _hotspot6.setup(0, 0, 199, 319, 9400, 16, 0); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerOR); + _stripManager.addSpeaker(&_speakerOText); + + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.disableControl(); + + // Useless check (skipped) : if (_globals->_sceneManager._previousScene == 9350) + _sceneState = 2; + if (!_globals->getFlag(89)) { + _globals->setFlag(89); + _sceneState = 0; + } + + setAction(&_sequenceManager, this, 9400, &_globals->_player, &_object1, &_object3, 0); +} + +/*-------------------------------------------------------------------------- + * Scene 9450 + * + *--------------------------------------------------------------------------*/ +void Scene9450::Object2::signal() { + Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene; + + this->setAction(&scene->_sequenceManager3, this, 9458, &scene->_object1, 0); +} + +void Scene9450::Object3::dispatch() { + SceneObject::dispatch(); + _percent = (_percent * 20) / 30; +} + +void Scene9450::Hotspot1::doAction(int action) { + Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + if (scene->_object2._action) + scene->_object2._action->remove(); + scene->_sceneMode = 9459; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager1, scene, 9459, &scene->_object2, &scene->_object1, &scene->_object3, &_globals->_player, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9450::Hotspot3::doAction(int action) { + Scene9450 *scene = (Scene9450 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_CLOAK: + case OBJECT_JACKET: + case OBJECT_TUNIC2: + scene->_sceneMode = 9460; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager1, scene, 9460, &_globals->_player, &scene->_object2, &scene->_object1, 0); + break; + case OBJECT_TUNIC: + SceneItem::display(9450, 49, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_WALK: + // nothing + break; + case CURSOR_LOOK: + SceneItem::display(9450, 41, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + case CURSOR_TALK: + if (_globals->_inventory._tunic._sceneNumber == 9450) { + if (scene->_object2._action) + scene->_object2._action->remove(); + scene->_sceneMode = 9459; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager1, scene, 9459, &scene->_object2, &scene->_object1, &scene->_object3, &_globals->_player, 0); + } else if ((_globals->_inventory._cloak._sceneNumber != 1) && (_globals->_inventory._jacket._sceneNumber != 1) && (_globals->_inventory._tunic2._sceneNumber != 1)) { + SceneItem::display(9450, 38, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + scene->_sceneMode = 9460; + _globals->_player.disableControl(); + setAction(&scene->_sequenceManager1, scene, 9460, &_globals->_player, &scene->_object2, &scene->_object1, 0); + } + break; + default: + SceneItem::display(9450, 45, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + } +} + +void Scene9450::signal() { + switch (_sceneMode++) { + case 1002: + case 1004: + // Drink + setAction(&_sequenceManager1, this, 9456, &_object2, &_object1, &_object3, 0); + break; + case 1005: + // Bring me more wine + setAction(&_sequenceManager1, this, 9457, &_object2, &_object1, &_object3, 0); + break; + case 9451: + if (_globals->getFlag(87)) { + _globals->_player.enableControl(); + } else { + _sceneMode = 1001; + if (_object2._action) + _object2._action->remove(); + } + // No break on purpose + case 1001: + case 1003: + // Eat + setAction(&_sequenceManager1, this, 9455, &_object2, &_object1, &_object3, 0); + break; + case 9453: + _globals->_sceneManager.changeScene(9360); + break; + case 9459: + _object2.signal(); + _globals->_events.setCursor(CURSOR_WALK); + _hotspot1.remove(); + break; + case 1006: + _globals->setFlag(87); + // No break on purpose + default: + _globals->_player.enableControl(); + break; + } +} + +void Scene9450::dispatch() { + if (_action) { + _action->dispatch(); + } else { + if ((_globals->_player._position.y < 98) && (_globals->_player._position.x > 241) && (_globals->_player._position.x < 282)) { + _globals->_player.disableControl(); + _sceneMode = 9452; + setAction(&_sequenceManager1, this, 9452, &_globals->_player, 0); + } else if ((_globals->_player._position.y < 99) && (_globals->_player._position.x > 68) && (_globals->_player._position.x < 103)) { + _globals->_player.disableControl(); + _sceneMode = 9453; + setAction(&_sequenceManager1, this, 9453, &_globals->_player, 0); + } + } +} + +void Scene9450::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(84, 75, 167, 150); + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.postInit(); + + _object2.postInit(); + _object1.postInit(); + _object1.hide(); + + _globals->_player.disableControl(); + _sceneMode = 9451; + setAction(&_sequenceManager1, this, 9451, &_globals->_player, 0); + + if (_globals->getFlag(87)) { + if (_globals->_inventory._tunic._sceneNumber == 1) { + _object2.signal(); + } else { + _object2.setPosition(Common::Point(184, 144), 0); + _object2.setVisage(9451); + _object2.setPriority2(250); + _object2._strip = 5; + _object2._frame = 10; + } + } else { + _object3.postInit(); + _object3.hide(); + _object3.setAction(&_sequenceManager2, 0, 9455, &_object2, &_object1, 0); + } + + if (_globals->_inventory._tunic._sceneNumber != 1) + _hotspot1.setup(123, 139, 138, 170, 9450, 37, -1); + + _hotspot2.setup(153, 102, 176, 141, 9450, 39, 40); + _hotspot3.setup(97, 198, 130, 229, 9450, 41, 42); + _hotspot15.setup(131, 190, 145, 212, 9450, 43, 44); + _hotspot4.setup(33, 144, 105, 192, 9450, 0, 1); + _hotspot5.setup(20, 236, 106, 287, 9450, 2, 3); + _hotspot6.setup(137, 119, 195, 320, 9450, 4, 5); + _hotspot7.setup(20, 59, 99, 111, 9450, 6, -1); + _hotspot8.setup(110, 0, 199, 117, 9450, 7, 8); + _hotspot9.setup(101, 104, 130, 174, 9450, 9, 10); + _hotspot10.setup(110, 246, 149, 319, 9450, 11, 12); + _hotspot11.setup(16, 34, 74, 62, 6450, 13, 14); + _hotspot12.setup(19, 108, 72, 134, 9450, 15, 16); + _hotspot13.setup(18, 215, 71, 237, 9450, 17, 18); + _hotspot14.setup(15, 288, 76, 314, 9450, 19, 20); + _hotspot16.setup(0, 0, 200, 320, 9450, 46, -1); +} + +/*-------------------------------------------------------------------------- + * Scene 9500 + * + *--------------------------------------------------------------------------*/ +void Scene9500::Hotspot1::doAction(int action) { + Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene; + + if (action == OBJECT_SWORD) { + scene->_sceneMode = 9510; + _globals->setFlag(92); + _globals->_inventory._sword._sceneNumber = 9500; + _globals->_player.disableControl(); + _globals->_sceneItems.remove(this); + scene->_hotspot2.setup(87, 294, 104, 314, 9400, 17, -1); + scene->setAction(&scene->_sequenceManager, scene, 9510, &_globals->_player, &scene->_object2, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9500::Hotspot2::doAction(int action) { + Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + scene->_sceneMode = 9511; + _globals->_player.disableControl(); + _globals->_sceneItems.remove(this); + scene->setAction(&scene->_sequenceManager, scene, 9511, &_globals->_player, &scene->_object2, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9500::Hotspot3::doAction(int action) { + Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene; + + if ((action == CURSOR_USE) && (_globals->_inventory._candle._sceneNumber != 1)){ + scene->_sceneMode = 9505; + _globals->_player.disableControl(); + _globals->_sceneItems.remove(this); + scene->setAction(&scene->_sequenceManager, scene, 9505, &_globals->_player, &scene->_candle, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9500::Hotspot4::doAction(int action) { + Scene9500 *scene = (Scene9500 *)_globals->_sceneManager._scene; + + if (action == OBJECT_CANDLE) { + _globals->_player.disableControl(); + if (_globals->_inventory._straw._sceneNumber == 9500) { + scene->_sceneMode = 9506; + _globals->_sceneItems.remove(&scene->_hotspot5); + _globals->_sceneItems.remove(this); + scene->setAction(&scene->_sequenceManager, scene, 9506, &_globals->_player, &scene->_object3, 0); + _globals->_inventory._candle._sceneNumber = 9850; + } else { + scene->_sceneMode = 9507; + scene->setAction(&scene->_sequenceManager, scene, 9507, &_globals->_player, &scene->_object3, 0); + } + } else if (action == OBJECT_STRAW) { + scene->_sceneMode = 9512; + _globals->_player.disableControl(); + _globals->_inventory._straw._sceneNumber = 9500; + scene->setAction(&scene->_sequenceManager, scene, 9512, &_globals->_player, &scene->_object3, 0); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9500::signal() { + switch (_sceneMode) { + case 9503: + _globals->_sceneManager.changeScene(9200); + _globals->_soundHandler.startSound(295, 0, 127); + break; + case 9504: + _globals->_sceneManager.changeScene(9850); + break; + case 9505: + _candle.setStrip(2); + _globals->_player.enableControl(); + break; + case 9506: + _globals->setFlag(85); + _globals->_player.enableControl(); + break; + case 9511: + _globals->_player.enableControl(); + if (!_globals->getFlag(51)) { + _globals->setFlag(51); + _globals->_player.disableControl(); + _sceneMode = 9514; + setAction(&_sequenceManager, this, 9514, &_globals->_player, 0, 0, 0, 0); + } + break; + case 0: + case 9514: + default: + _globals->_player.enableControl(); + break; + } +} + +void Scene9500::dispatch() { + if (_action) { + _action->dispatch(); + } else { + if (_globals->_player._position.y >= 199) { + _globals->_player.disableControl(); + _sceneMode = 9503; + setAction(&_sequenceManager, this, 9503, &_globals->_player, 0, 0, 0, 0); + } else if (_globals->_player._position.y < 127) { + _globals->_player.disableControl(); + _sceneMode = 9504; + setAction(&_sequenceManager, this, 9504, &_globals->_player, 0, 0, 0, 0); + } + } + +} + +void Scene9500::process(Event &event) { + Scene::process(event); +} + +void Scene9500::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(110, 75, 200, 150); + + _globals->_player.postInit(); + _globals->_soundHandler.startSound(305, 0, 127); + + _candle.postInit(0); + _candle.setVisage(9500); + _candle.setStrip(1); + _candle.animate(ANIM_MODE_2); + _candle.setPosition(Common::Point(30, 105), 0); + if (_globals->_inventory._candle._sceneNumber != 9500) + _candle.setStrip(2); + + _object3.postInit(0); + _object3.hide(); + _object3.setPriority2(150); + _object3.setPosition(Common::Point(166, 133)); + if (_globals->_inventory._straw._sceneNumber == 9500) { + _object3.show(); + _object3.setVisage(5); + _object3._strip = 2; + _object3._frame = 9; + _object3.setPosition(Common::Point(168, 128)); + if (_globals->getFlag(85)) { + _object3.setVisage(9500); + _object3.setStrip(4); + _object3.animate(ANIM_MODE_8, 0, 0); + _object3.setPosition(Common::Point(166, 133)); + } + } + + _object2.postInit(0); + _object2.hide(); + if (_globals->getFlag(92)) { + _object2.show(); + _object2.setVisage(9501); + _object2.setStrip(1); + _object2.setFrame(_object2.getFrameCount()); + _object2.setPosition(Common::Point(303, 130)); + _object2.setPriority2(132); + if (_globals->_inventory._helmet._sceneNumber == 1) { + _hotspot2.setup(87, 294, 104, 314, 9400, 17, -1); + } else { + _object2.setStrip(2); + _object2.setFrame(1); + } + } else { + _hotspot1.setup(105, 295, 134, 313, 9500, 9, 10); + } + + _hotspot17.setup(101, 293, 135, 315, 9500, 9, 10); + _hotspot3.setup(84, 12, 107, 47, 9500, 15, 15); + _hotspot6.setup(93, 11, 167, 46, 9500, 0, 1); + _hotspot7.setup(100, 70, 125, 139, 9500, 2, 3); + + if (!_globals->getFlag(85)) { + _hotspot5.setup(111, 68, 155, 244, 9500, 17, -1); + _hotspot4.setup(57, 71, 120, 126, 9500, 16, -1); + } + + _hotspot8.setup(60, 24, 90, 53, 9500, 4, 5); + _hotspot9.setup(72, 143, 93, 163, 9500, 4, 5); + _hotspot10.setup(70, 205, 92, 228, 9500, 4, 5); + _hotspot11.setup(66, 291, 90, 317, 9500, 4, 5); + _hotspot12.setup(22, 58, 101, 145, 9500, 6, 7); + _hotspot13.setup(121, 57, 163, 249, 9500, 6, 7); + _hotspot14.setup(115, 133, 135, 252, 9500, 6, 7); + _hotspot15.setup(55, 240, 125, 254, 9500, 6, 7); + _hotspot16.setup(53, 251, 132, 288, 9500, 8, -1); + _hotspot19.setup(101, 207, 120, 225, 9500, 9, 10); + _hotspot18.setup(98, 144, 117, 162, 9500, 9, 10); + _hotspot20.setup(102, 27, 132, 50, 9500, 9, 10); + + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.disableControl(); + + if ((_globals->_sceneManager._previousScene == 9200) || (_globals->_sceneManager._previousScene != 9850)) { + _sceneMode = 0; + if (_globals->_inventory._helmet._sceneNumber != 1) { + setAction(&_sequenceManager, this, 9501, &_globals->_player, &_candle, 0); + } else { + _globals->_inventory._helmet._sceneNumber = 9500; + _hotspot2.setup(87, 294, 104, 314, 9400, 17, -1); + setAction(&_sequenceManager, this, 9513, &_globals->_player, &_object2, 0); + } + } else { + _sceneMode = 0; + setAction(&_sequenceManager, this, 9502, &_globals->_player, &_candle, 0); + } +} + +/*-------------------------------------------------------------------------- + * Scene 9700 + * + *--------------------------------------------------------------------------*/ +void Scene9700::signal() { + switch (_sceneMode ++) { + case 9703: + _globals->setFlag(88); + // No break on purpose + case 9701: + case 9702: + _gfxButton1.setText(EXIT_MSG); + _gfxButton1._bounds.centre(50, 190); + _gfxButton1.draw(); + _gfxButton1._bounds.expandPanes(); + _globals->_player.enableControl(); + _globals->_player._canWalk = 0; + _globals->_events.setCursor(CURSOR_USE); + break; + case 9704: + _globals->_soundHandler.startSound(323, 0, 127); + _globals->_sceneManager.changeScene(9750); + break; + } +} + +void Scene9700::process(Event &event) { + if ((event.eventType == EVENT_BUTTON_DOWN) && (event.kbd.keycode == 0)) { + if (_gfxButton1.process(event)) { + _globals->_sceneManager.changeScene(9200); + } else if (_globals->_events._currentCursor == OBJECT_SCANNER) { + event.handled = true; + if (_globals->_inventory._helmet._sceneNumber == 1) { + _globals->_player.disableControl(); + _sceneMode = 9704; + setAction(&_sequenceManager, this, 9704, &_globals->_player, &_object1, 0); + } else { + _globals->_player.disableControl(); + _sceneMode = 9703; + setAction(&_sequenceManager, this, 9703, &_globals->_player, &_object1, 0); + } + } + } +} + +void Scene9700::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _sceneHotspot1.setup(84, 218, 151, 278, 9700, 14, -1); + _sceneHotspot2.setup(89, 11, 151, 121, 9700, 14, -1); + _sceneHotspot3.setup(69, 119, 138, 218, 9700, 15, 16); + _sceneHotspot4.setup(34, 13, 88, 116, 9700, 17, -1); + _sceneHotspot5.setup(52, 119, 68, 204, 9700, 17, -1); + _sceneHotspot6.setup(0, 22, 56, 275, 9700, 18, -1); + + _object1.postInit(); + _object1.hide(); + _globals->_player.postInit(); + if (_globals->getFlag(97)) { + _globals->_player.disableControl(); + _sceneMode = 9701; + setAction(&_sequenceManager, this, 9701, &_globals->_player, &_object1, 0); + _globals->setFlag(97); + } else { + _globals->_player.disableControl(); + _sceneMode = 9702; + setAction(&_sequenceManager, this, 9702, &_globals->_player, &_object1, 0); + } +} + +/*-------------------------------------------------------------------------- + * Scene 9750 + * + *--------------------------------------------------------------------------*/ +void Scene9750::signal() { + switch (_sceneMode ++) { + case 9751: + _globals->_soundHandler.proc1(this); + break; + case 9752: + _globals->_sceneManager.changeScene(2100); + default: + break; + } +} + +void Scene9750::dispatch() { + Scene::dispatch(); +} + +void Scene9750::postInit(SceneObjectList *OwnerList) { + loadScene(9750); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _globals->_player.postInit(); + _object1.postInit(); + _object1.hide(); + _object2.postInit(); + _object2.hide(); + _globals->_player.disableControl(); + _sceneMode = 9751; + setAction(&_sequenceManager, this, 9751, &_globals->_player, &_object1, &_object2, 0); +} + + +/*-------------------------------------------------------------------------- + * Scene 9850 + * + *--------------------------------------------------------------------------*/ +void Scene9850::Object6::doAction(int action) { + if ((_flags & OBJFLAG_HIDE) == 0) { + if (action == CURSOR_LOOK) { + SceneItem::display(9850, 27, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + _globals->_inventory._scimitar._sceneNumber = 1; + hide(); + } else { + SceneHotspot::doAction(action); + } + } +} +void Scene9850::Object7::doAction(int action) { + if ((_flags & OBJFLAG_HIDE) == 0) { + if (action == CURSOR_LOOK) { + SceneItem::display(9850, 28, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + _globals->_inventory._sword._sceneNumber = 1; + hide(); + } else { + SceneHotspot::doAction(action); + } + } +} + +// Hair covered tunic +void Scene9850::Hotspot12::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + if (_globals->_inventory._tunic2._sceneNumber != 1) { + _globals->_inventory._tunic2._sceneNumber = 1; + _globals->_player.disableControl(); + scene->_sceneMode = 9858; + setAction(&scene->_sequenceManager, scene, 9858, &_globals->_player, &scene->_objTunic2, 0); + } else { + _globals->_inventory._tunic2._sceneNumber = 9850; + _globals->_player.disableControl(); + scene->_sceneMode = 9861; + setAction(&scene->_sequenceManager, scene, 9861, &_globals->_player, &scene->_objTunic2, 0); + } + } else if ((action != CURSOR_LOOK) || (_globals->_inventory._tunic2._sceneNumber != 1)) { + NamedHotspot::doAction(action); + } else { + SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } +} + +void Scene9850::Hotspot14::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + if (_globals->_inventory._jacket._sceneNumber != 1) { + _globals->_inventory._jacket._sceneNumber = 1; + _globals->_player.disableControl(); + scene->_sceneMode = 9857; + setAction(&scene->_sequenceManager, scene, 9857, &_globals->_player, &scene->_objJacket, 0); + } else { + _globals->_inventory._jacket._sceneNumber = 9850; + _globals->_player.disableControl(); + scene->_sceneMode = 9860; + setAction(&scene->_sequenceManager, scene, 9860, &_globals->_player, &scene->_objJacket, 0); + } + } else if ((action != CURSOR_LOOK) || (_globals->_inventory._jacket._sceneNumber != 1)) { + NamedHotspot::doAction(action); + } else { + SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } +} + +void Scene9850::Hotspot16::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + if (_globals->_inventory._cloak._sceneNumber != 1) { + _globals->_inventory._cloak._sceneNumber = 1; + _globals->_player.disableControl(); + scene->_sceneMode = 9862; + setAction(&scene->_sequenceManager, scene, 9862, &_globals->_player, &scene->_objCloak, 0); + } else { + _globals->_inventory._cloak._sceneNumber = 9850; + _globals->_player.disableControl(); + scene->_sceneMode = 9859; + setAction(&scene->_sequenceManager, scene, 9859, &_globals->_player, &scene->_objCloak, 0); + } + } else if ((action != CURSOR_LOOK) || (_globals->_inventory._cloak._sceneNumber != 1)) { + NamedHotspot::doAction(action); + } else { + SceneItem::display(9850, 30, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } +} + +void Scene9850::Hotspot17::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == OBJECT_SCANNER) { + SceneItem::display(9850, 32, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + if (action == CURSOR_USE) + scene->_soundHandler.startSound(306, 0, 127); + NamedHotspot::doAction(action); + } +} + +void Scene9850::Hotspot18::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == OBJECT_SCANNER) { + SceneItem::display(9850, 32, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + if (action == CURSOR_USE) + scene->_soundHandler.startSound(306, 0, 127); + NamedHotspot::doAction(action); + } +} + +void Scene9850::Hotspot19::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == OBJECT_SCANNER) { + SceneItem::display(9850, 31, SET_Y, 20, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + if (action == CURSOR_USE) + scene->_soundHandler.startSound(313, 0, 127); + NamedHotspot::doAction(action); + } +} + +// Arrow on Statue +void Scene9850::Hotspot20::doAction(int action) { + Scene9850 *scene = (Scene9850 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + _globals->_player.disableControl(); + if (scene->_objSword._state == 0) { + if (_globals->_inventory._scimitar._sceneNumber == 9850) + scene->_objScimitar.show(); + if (_globals->_inventory._sword._sceneNumber == 9850) + scene->_objSword.show(); + scene->_sceneMode = 11; + setAction(&scene->_sequenceManager, scene, 9853, &_globals->_player, &scene->_objDoor, &scene->_objLever, 0); + } else { + scene->_sceneMode = 10; + setAction(&scene->_sequenceManager, scene, 9854, &_globals->_player, &scene->_objDoor, &scene->_objLever, 0); + } + scene->_objSword._state ^= 1; + } else { + NamedHotspot::doAction(action); + } +} + +void Scene9850::signal() { + switch (_sceneMode ++) { + case 10: + // Hidden closet closed + if (_globals->_inventory._scimitar._sceneNumber == 9850) + _objScimitar.hide(); + if (_globals->_inventory._sword._sceneNumber == 9850) + _objSword.hide(); + _globals->_sceneItems.remove(&_objScimitar); + _globals->_sceneItems.remove(&_objSword); + _globals->_sceneItems.addItems(&_hotspot19, NULL); + _globals->_player.enableControl(); + break; + case 11: + // Hidden closet opened + if (_globals->_inventory._scimitar._sceneNumber == 9850) + _globals->_sceneItems.addItems(&_objScimitar, NULL); + if (_globals->_inventory._sword._sceneNumber == 9850) + _globals->_sceneItems.addItems(&_objSword, NULL); + _globals->_sceneItems.remove(&_hotspot19); + _globals->_player.enableControl(); + break; + case 9500: + _globals->_sceneManager.changeScene(9500); + break; + case 0: + default: + _globals->_player.enableControl(); + break; + } +} + +void Scene9850::process(Event &event) { + Scene::process(event); + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_4)) { + event.handled = true; + _globals->_player.disableControl(); + if (_objSword._state == 0) { + _sceneMode = 0; + setAction(&_sequenceManager, this, 9853, &_objLever, &_objDoor, &_objScimitar, &_objSword, 0); + } else { + _sceneMode = 10; + setAction(&_sequenceManager, this, 9854, &_objLever, &_objDoor, &_objScimitar, &_objSword, 0); + } + _objSword._state ^= 1; + } +} + +void Scene9850::dispatch() { + if (_action) { + _action->dispatch(); + } else if (_globals->_player._position.y >= 198) { + _globals->_player.disableControl(); + _sceneMode = 9500; + setAction(&_sequenceManager, this, 9852, &_globals->_player, 0); + } +} + +void Scene9850::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + _objSword._state = 0; + + _objDoor.postInit(); + _objDoor.setVisage(9850); + _objDoor.setStrip(1); + _objDoor.setFrame(1); + _objDoor.setPosition(Common::Point(28, 118), 0); + _objDoor.setPriority2(90); + + _objLever.postInit(); + _objLever.setVisage(9850); + _objLever.setStrip(4); + _objLever.setFrame(1); + _objLever.setPosition(Common::Point(256, 35), 0); + + _objCloak.postInit(); + _objCloak.setVisage(9850); + _objCloak.setStrip(5); + _objCloak.setFrame(1); + _objCloak.setPriority2(90); + _objCloak.setPosition(Common::Point(157, 81), 0); + if (_globals->_inventory._cloak._sceneNumber != 9850) + _objCloak.hide(); + + _objJacket.postInit(); + _objJacket.setVisage(9850); + _objJacket.setStrip(5); + _objJacket.setFrame(2); + _objJacket.setPriority2(90); + _objJacket.setPosition(Common::Point(201, 84)); + if (_globals->_inventory._jacket._sceneNumber != 9850) + _objJacket.hide(); + + _objTunic2.postInit(); + _objTunic2.setVisage(9850); + _objTunic2.setStrip(5); + _objTunic2.setFrame(3); + _objTunic2.setPriority2(90); + _objTunic2.setPosition(Common::Point(295, 90)); + if (_globals->_inventory._tunic2._sceneNumber != 9850) + _objTunic2.hide(); + + if (_globals->_inventory._scimitar._sceneNumber == 9850) { + _objScimitar.postInit(); + _objScimitar.setVisage(9850); + _objScimitar.setStrip(2); + _objScimitar.setFrame(1); + _objScimitar.setPosition(Common::Point(55, 83), 0); + _objScimitar.setPriority2(80); + _objScimitar.hide(); + } + + if (_globals->_inventory._sword._sceneNumber == 9850) { + _objSword.postInit(); + _objSword.setVisage(9850); + _objSword.setStrip(3); + _objSword.setFrame(1); + _objSword.setPosition(Common::Point(56, 101), 0); + _objSword.setPriority2(80); + _objSword.hide(); + } + + _spotLever.setup(30, 251, 45, 270, 9850, 26, -1); + _hotspot1.setup(123, 0, 200, 320, 9850, 0, 1); + _hotspot2.setup(107, 87, 133, 308, 9850, 0, 1); + _hotspot3.setup(2, 28, 53, 80, 9850, 2, 3); + _hotspot4.setup(13, 0, 55, 27, 9850, 2, 3); + _hotspot5.setup(8, 74, 27, 91, 9850, 4, 5); + _hotspot17.setup(61, 0, 125, 28, 9850, 6, 7); + _hotspot18.setup(51, 95, 105, 145, 9850, 6, 7); + _hotspot19.setup(56, 28, 115, 97, 9850, 6, 8); + _hotspot6.setup(0, 223, 115, 257, 9850, 9, 10); + _hotspot7.setup(15, 254, 33, 268, 9850, 9, -1); + _hotspot8.setup(17, 218, 37, 233, 9850, 9, 10); + _hotspot9.setup(8, 113, 26, 221, 9850, 11, 12); + _hotspot10.setup(14, 94, 53, 112, 9850, 13, 14); + _hotspot11.setup(5, 269, 29, 303, 9850, 15, 16); + _hotspot12.setup(43, 278, 91, 317, 9850, 17, 18); + _hotspot13.setup(47, 263, 112, 282, 9850, 19, 20); + _hotspot14.setup(43, 188, 86, 224, 9850, 21, 22); + _hotspot15.setup(43, 162, 92, 191, 9850, 23, 24); + _hotspot16.setup(40, 146, 90, 169, 9850, 25, -1); + + _globals->_player.postInit(); + _globals->_player.disableControl(); + _sceneMode = 0; + setAction(&_sequenceManager, this, 9851, &_globals->_player, 0); +} + +/*-------------------------------------------------------------------------- + * Scene 9900 + * + *--------------------------------------------------------------------------*/ +void Scene9900::strAction1::signal() { + RGB8 mask1, mask2; + mask1.r = mask1.g = mask1.b = 0xff; + mask2.r = mask2.g = mask2.b = 0; + + Scene9900 *scene = (Scene9900 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_soundHandler.startSound(351, 0, 127); + _object9.postInit(); + _object9.setVisage(18); + _object9._frame = 1; + _object9._strip = 6; + _object9.setPosition(Common::Point(171, 59)); + _object9.animate(ANIM_MODE_5, 0); + _globals->_scenePalette.addRotation(67, 111, 1, 1, this); + scene->_object2.hide(); + break; + case 1: + _palette1.getPalette(); + _globals->_scenePalette.addUnkPal(&mask1, 1, true /*10*/, this); + break; + case 2: + _object9.remove(); + _globals->_scenePalette.addUnkPal(&mask2, 1, true /*5*/, this); + break; + case 3: + _globals->_soundHandler.startSound(377, 0, 127); + setDelay(120); + break; + case 4: + _globals->_scenePalette.addUnkPal(_palette1._palette, 256, 1, this); + break; + case 5: + remove(); + break; + default: + break; + } +} + +void Scene9900::strAction2::signal() { + switch (_actionIndex++) { + case 0: + var1 = 0; + _txtArray1Index = 0; + _txtArray1[0]._position.y = 200; + _txtArray1[0]._position.y = 300; + _txtArray2[0]._position.y = 400; + _txtArray2[0]._position.y = 500; + var3 = 0; + // No break on purpose + case 1: { + Common::String msg = _vm->_dataManager->getMessage(8030, var1++); + if (!msg.compareTo("LASTCREDIT")) { + if (var3 == 0) { + // Not used? + // int x = _txtArray1[_txtArray1Index].getFrame().getBounds().height(); + _txtArray1[_txtArray1Index]._moveDiff.y = 10; + + NpcMover *mover = new NpcMover(); + Common::Point pt(_txtArray1[_txtArray1Index]._moveDiff.x, -100); + _txtArray1[_txtArray1Index].addMover(mover, &pt, 0); + + // Not used? + // int x = _txtArray2[_txtArray1Index].getFrame().getBounds().height(); + _txtArray2[_txtArray1Index]._moveDiff.y = 10; + _txtArray1Index = (_txtArray1Index + 1) % 2; + } + var3 = 1; + _txtArray1[_txtArray1Index]._textMode = ALIGN_CENTRE; + _txtArray1[_txtArray1Index]._width = 240; + _txtArray1[_txtArray1Index]._fontNumber = 2; + _txtArray1[_txtArray1Index]._colour1 = 7; + _txtArray1[_txtArray1Index].setup(msg); + _txtArray1[_txtArray1Index]._field7A = 20; + _txtArray1[_txtArray1Index]._moveDiff.y = 2; + _txtArray1[_txtArray1Index].setPriority2(255); + int frameWidth = _txtArray1[_txtArray1Index].getFrame().getBounds().width(); + int frameHeight = _txtArray1[_txtArray1Index].getFrame().getBounds().height(); + _txtArray1[_txtArray1Index].setPosition(Common::Point((320 - frameWidth) / 2, 200)); + NpcMover *mover2 = new NpcMover(); + Common::Point pt2(_txtArray1[_txtArray1Index]._position.x, 100); + _txtArray1[_txtArray1Index].addMover(mover2, &pt2, 0); + + _txtArray2[_txtArray1Index]._textMode = ALIGN_CENTRE; + _txtArray2[_txtArray1Index]._width = 240; + _txtArray2[_txtArray1Index]._fontNumber = 2; + _txtArray2[_txtArray1Index]._colour1 = 23; + + msg = _vm->_dataManager->getMessage(8030, var1++); + _txtArray2[_txtArray1Index].setup(msg); + _txtArray2[_txtArray1Index]._field7A = 20; + _txtArray2[_txtArray1Index]._moveDiff.y = 2; + _txtArray2[_txtArray1Index].setPriority2(255); + frameWidth = _txtArray2[_txtArray1Index].getFrame().getBounds().width(); + _txtArray2[_txtArray1Index].setPosition(Common::Point((320 - frameWidth) / 2, 200 + frameHeight)); + } else { + _globals->_player.enableControl(); + _actionIndex = 3; + signal(); + } + break; + } + case 2: + setDelay(60); + _actionIndex = 1; + break; + case 3: + setDelay(7200); + break; + case 4: + _txtArray1[0].remove(); + _txtArray1[1].remove(); + _txtArray2[0].remove(); + _txtArray2[1].remove(); + remove(); + break; + default: + break; + } +} +void Scene9900::strAction2::dispatch() { +// if (this->_txtArray1[0]._textSurface != 0) { + int frameHeight = _txtArray1[0].getFrame().getBounds().height(); + _txtArray2[0]._position.y = frameHeight + _txtArray1[0]._position.y; + _txtArray2[0]._flags |= OBJFLAG_PANES; +// } +// if (this->_txtArray1[1]._textSurface != 0) { + frameHeight = _txtArray1[1].getFrame().getBounds().height(); + _txtArray2[1]._position.y = frameHeight + _txtArray1[1]._position.y; + _txtArray2[1]._flags |= OBJFLAG_PANES; +// } + Action::dispatch(); +} + +void Scene9900::strAction3::signal() { + RGB8 mask3, mask4; + mask3.r = 0xff; mask3.g = mask3.b = 0; + mask4.r = mask4.g = mask4.b = 0; + + switch (_actionIndex++) { + case 0: + _palette2.getPalette(); + _palette3.loadPalette(2003); + _globals->_scenePalette.addUnkPal(_palette3._palette, 256, true /*5*/, this); + break; + case 1: + _globals->_scenePalette.addUnkPal(&mask3, 1, true /*10*/, this); + break; + case 2: + _globals->_scenePalette.addUnkPal(&mask4, 1, true /*1*/, this); + break; + case 3: + _palette2.loadPalette(17); + _globals->_sceneManager._scene->loadScene(17); + _globals->_scenePalette.addUnkPal(_palette2._palette, 256, true /*5*/, this); + break; + case 4: + _globals->_game.endGame(9900, 61); + remove(); + default: + break; + } +} + +void Scene9900::signal() { + if ((_sceneMode != 9913) && (_sceneMode != 9905) && (_sceneMode != 9904) && (_sceneMode != 9912)) { + _object1.hide(); + _object2.hide(); + _object3.hide(); + _object4.hide(); + _object5.hide(); + _object6.hide(); + } + + _object1.animate(ANIM_MODE_NONE, 0); + _object2.animate(ANIM_MODE_NONE, 0); + _object3.animate(ANIM_MODE_NONE, 0); + _object4.animate(ANIM_MODE_NONE, 0); + _object5.animate(ANIM_MODE_NONE, 0); + _object6.animate(ANIM_MODE_NONE, 0); + + _object1.setObjectWrapper(0); + _object2.setObjectWrapper(0); + _object3.setObjectWrapper(0); + _object4.setObjectWrapper(0); + _object5.setObjectWrapper(0); + _object6.setObjectWrapper(0); + + _object1.addMover(0); + _object2.addMover(0); + _object3.addMover(0); + _object4.addMover(0); + _object5.addMover(0); + _object6.addMover(0); + + switch (_sceneMode){ + case 150: + _globals->_soundHandler.startSound(380, 0, 127); + _object8.postInit(0); + _object8.setVisage(2002); + _object8.setStrip(1); + _object8.setFrame(1); + _object8.setPriority2(200); + _object8.setPosition(Common::Point(64, 199)); + _globals->_player.disableControl(); + _sceneMode = 9908; + setAction(&_sequenceManager, this, 9908, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 162: + warning("TBC: shutdown();"); + _globals->_game.quitGame(); + break; + case 9901: + _globals->_player.disableControl(); + _sceneMode = 9906; + setAction(&_sequenceManager, this, 9906, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + break; + case 9902: + _globals->_player.disableControl(); + _sceneMode = 9901; + setAction(&_sequenceManager, this, 9901, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9903: + _globals->_player.disableControl(); + _sceneMode = 9902; + setAction(&_sequenceManager, this, 9902, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9904: + _globals->_soundHandler.startSound(390, 0, 127); + _sceneMode = 9912; + setAction(&_strAction2, this); + break; + case 9905: + _sceneMode = 150; + setAction(&_strAction1, this); + break; + case 9906: + if (_object8._state == 0) { + _globals->_player.disableControl(); + _sceneMode = 9913; + setAction(&_sequenceManager, this, 9913, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + } else { + _globals->_player.disableControl(); + _sceneMode = 9905; + setAction(&_sequenceManager, this, 9905, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + } + break; + case 9907: + _globals->_player.disableControl(); + _sceneMode = 9903; + setAction(&_sequenceManager, this, 9903, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9908: + _object8.remove(); + _globals->_player.disableControl(); + _sceneMode = 9904; + setAction(&_sequenceManager, this, 9904, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9909: + _globals->_soundHandler.startSound(375, 0, 127); + _globals->_player.disableControl(); + _sceneMode = 9907; + setAction(&_sequenceManager, this, 9907, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9910: + _globals->_player.disableControl(); + _sceneMode = 9911; + setAction(&_sequenceManager, this, 9911, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9911: + _globals->_soundHandler.startSound(367, 0, 127); + _globals->_player.disableControl(); + _sceneMode = 9909; + setAction(&_sequenceManager, this, 9909, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + break; + case 9912: + _globals->_player.disableControl(); + _sceneMode = 9912; + setAction(&_sequenceManager, this, 9912, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); + _sceneMode = 162; + _globals->_player.enableControl(); + _globals->_player._canWalk = false; + break; + case 9913: + _sceneMode = 200; + setAction(&_strAction3, this); + break; + default: + break; + } +} + +void Scene9900::process(Event &event) { + if (event.handled) + return; + Scene::process(event); + if (_sceneMode != 9906) { + if ((event.eventType == EVENT_BUTTON_DOWN) && (_globals->_events.getCursor() == OBJECT_ITEMS)) { + _object8._state = 1; + _globals->_inventory._items._sceneNumber = 9900; + _globals->_events.setCursor(CURSOR_USE); + } + } +} + +void Scene9900::dispatch() { + if (_action) + _action->dispatch(); +} + +void Scene9900::postInit(SceneObjectList *OwnerList) { + _object1.postInit(0); + _object1.hide(); + _object2.postInit(0); + _object2.hide(); + _object3.postInit(0); + _object3.hide(); + _object4.postInit(0); + _object4.hide(); + _object5.postInit(0); + _object5.hide(); + _object6.postInit(0); + _object6.hide(); + + _object8._state = 0; + + _globals->_inventory._concentrator._sceneNumber = 9900; + _globals->_inventory._items._rlbNum = 3; + _globals->_inventory._items._cursorNum = 6; + _globals->_inventory._items._description = Common::String("One of the items from the stasis ship. The other is on the Lance's bridge."); + + _stripManager.addSpeaker(&_speakerMR); + _globals->_player.disableControl(); + _sceneMode = 9910; + setAction(&_sequenceManager, this, 9910, &_object1, &_object2, &_object3, &_object4, &_object5, &_object6); +} + +/*-------------------------------------------------------------------------- + * Scene 9999 + * + *--------------------------------------------------------------------------*/ + +void Scene9999::Action1::signal() { + switch (_actionIndex++) { + case 0: + setDelay(600); + break; + case 1: + _globals->_sceneManager.changeScene(3500); + break; + default: + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene9999::Action2::signal() { + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + SceneItem::display(9999, 0, SET_Y, 10, SET_X, 30, SET_FONT, 2, SET_BG_COLOUR, -1, SET_EXT_BGCOLOUR, 23, SET_WIDTH, 260, SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(300); + break; + case 2: + _globals->_stripNum = 3600; + _globals->_sceneManager.changeScene(3600); + default: + break; + } +} + +void Scene9999::postInit(SceneObjectList *OwnerList) { + loadScene(9998); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _object1.postInit(); + _object1.setVisage(1303); + _object1.setStrip2(3); + _object1.setPosition(Common::Point(160, 152), 0); + + _globals->_player.postInit(); + _globals->_player.setVisage(1303); + _globals->_player.setStrip2(1); + _globals->_player.setPriority2(250); + _globals->_player.animate(ANIM_MODE_2, 0); + _globals->_player.setPosition(Common::Point(194, 98), 0); + _globals->_player._numFrames = 20; + _globals->_player.disableControl(); + + _object2.postInit(); + _object2.setVisage(1303); + _object2.setStrip2(2); + _object2.setPriority2(2); + _object2.setPosition(Common::Point(164, 149), 0); + + _object3.postInit(); + _object3.setVisage(1303); + _object3.setStrip2(2); + _object3.setPriority2(2); + _object3.setFrame(2); + _object3.setPosition(Common::Point(292, 149), 0); + _object3.setAction(&_action3); + + if (_globals->_sceneManager._previousScene == 3500) + setAction(&_action2); + else + setAction(&_action1); + + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position.x, _globals->_player._position.y); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + + if (_globals->_sceneManager._previousScene == 3500) + _globals->_stripNum = 2222; + else + _globals->_stripNum = 2121; + + _globals->_soundHandler.startSound(118, 0, 127); + +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes10.h b/engines/tsage/ringworld_scenes10.h new file mode 100644 index 0000000000..a89456e39d --- /dev/null +++ b/engines/tsage/ringworld_scenes10.h @@ -0,0 +1,544 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES10_H +#define TSAGE_RINGWORLD_SCENES10_H + +#include "common/scummsys.h" +#include "tsage/ringworld_logic.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +class SceneObject9150 : public SceneObject { +public: + int _timer, _signalFlag; + + virtual void synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsSint16LE(_timer); + s.syncAsSint16LE(_signalFlag); + } + virtual Common::String getClassName() { return "SceneObject9150"; } +}; + +class Scene2 : public Scene { +public : + int _sceneState; + + Scene2(); + virtual void synchronise(Serialiser &s) { + Scene::synchronise(s); + s.syncAsSint16LE(_sceneState); + } +}; + +class Object9350 : public SceneObject { +public: + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void draw(); +}; + +class Scene9100 : public Scene { + /* Items */ + class SceneHotspot1 : public NamedHotspot { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneHotspot1 _sceneHotspot1; + NamedHotspot _sceneHotspot2; + NamedHotspot _sceneHotspot3; + NamedHotspot _sceneHotspot4; + NamedHotspot _sceneHotspot5; + NamedHotspot _sceneHotspot6; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9150 : public Scene2 { + class Object3 : public SceneObject9150 { + public: + virtual void signal(); + virtual void dispatch(); + }; +public: + SequenceManager _sequenceManager1; + SequenceManager _sequenceManager2; + SceneObject _object1; + SceneObject _object2; + Object3 _object3; + NamedHotspot _sceneHotspot1; + NamedHotspot _sceneHotspot2; + NamedHotspot _sceneHotspot3; + NamedHotspot _sceneHotspot4; + NamedHotspot _sceneHotspot5; + NamedHotspot _sceneHotspot6; + NamedHotspot _sceneHotspot7; + NamedHotspot _sceneHotspot8; + NamedHotspot _sceneHotspot9; + NamedHotspot _sceneHotspot10; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9200 : public Scene2 { + class SceneHotspot1 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + Action _action1; + SpeakerGText _speakerGText; + SpeakerGR _speakerGR; + SpeakerQText _speakerQText; + SoundHandler _soundHandler; + SceneHotspot1 _hotspot1; + NamedHotspot _hotspot2; + NamedHotspot _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); + virtual void process(Event &event); +}; + +class Scene9300 : public Scene { +public: + SequenceManager _sequenceManager; + SceneObject _object1; + SceneObject _object2; + NamedHotspot _hotspot1; + NamedHotspot _hotspot2; + NamedHotspot _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + NamedHotspot _hotspot9; + NamedHotspot _hotspot10; + NamedHotspot _hotspot11; + NamedHotspot _hotspot12; + NamedHotspot _hotspot13; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9350 : public Scene2 { +public: + SequenceManager _sequenceManager; + Object9350 _object1; + SceneObject _object2; + NamedHotspot _sceneHotspot1; + NamedHotspot _sceneHotspot2; + NamedHotspot _sceneHotspot3; + NamedHotspot _sceneHotspot4; + NamedHotspot _sceneHotspot5; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9360 : public Scene2 { +public: + SequenceManager _sequenceManager; + Action _action1; + Object9350 _object1; + NamedHotspot _hotspot1; + NamedHotspot _hotspot2; + NamedHotspot _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9400 : public Scene2 { + class SceneHotspot7 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class SceneHotspot8 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; +public: + Scene9400(); + SequenceManager _sequenceManager; + Action _action1; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SpeakerOText _speakerOText; + SpeakerOR _speakerOR; + SpeakerQText _speakerQText; + NamedHotspot _hotspot1; + NamedHotspot _hotspot2; + NamedHotspot _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + SoundHandler _soundHandler; + int _field1032; + SceneHotspot7 _hotspot7; + SceneHotspot8 _hotspot8; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9450 : public Scene2 { + class Object2 : public SceneObject { + public: + virtual void signal(); + }; + + class Object3 : public SceneObject9150 { + public: + virtual void dispatch(); + }; + + class Hotspot1 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot3 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; +public: + SceneObject _object1; + SequenceManager _sequenceManager1; + SequenceManager _sequenceManager2; + Object2 _object2; + SequenceManager _sequenceManager3; + Object3 _object3; + Hotspot1 _hotspot1; + NamedHotspot _hotspot2; + Hotspot3 _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + NamedHotspot _hotspot9; + NamedHotspot _hotspot10; + NamedHotspot _hotspot11; + NamedHotspot _hotspot12; + NamedHotspot _hotspot13; + NamedHotspot _hotspot14; + NamedHotspot _hotspot15; + NamedHotspot _hotspot16; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9500 : public Scene2 { + class Hotspot1 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot2 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot3 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot4 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + +public: + SequenceManager _sequenceManager; + SceneObject _candle; + SceneObject _object2; + SceneObject _object3; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + Hotspot3 _hotspot3; + Hotspot4 _hotspot4; + Hotspot4 _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + NamedHotspot _hotspot9; + NamedHotspot _hotspot10; + NamedHotspot _hotspot11; + NamedHotspot _hotspot12; + NamedHotspot _hotspot13; + NamedHotspot _hotspot14; + NamedHotspot _hotspot15; + NamedHotspot _hotspot16; + NamedHotspot _hotspot17; + NamedHotspot _hotspot18; + NamedHotspot _hotspot19; + NamedHotspot _hotspot20; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); + virtual void process(Event &event); +}; + +class Scene9700 : public Scene2 { + SequenceManager _sequenceManager; + SceneObject _object1; + NamedHotspot _sceneHotspot1; + NamedHotspot _sceneHotspot2; + NamedHotspot _sceneHotspot3; + NamedHotspot _sceneHotspot4; + NamedHotspot _sceneHotspot5; + NamedHotspot _sceneHotspot6; + GfxButton _gfxButton1; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); +}; + +class Scene9750 : public Scene { +public: + SequenceManager _sequenceManager; + SceneObject _object1; + SceneObject _object2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene9850 : public Scene { + class Object6 : public SceneObject{ + public: + virtual void doAction(int action); + }; + + class Object7 : public SceneObjectExt{ + public: + virtual void doAction(int action); + }; + + class Hotspot12 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot14 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot16 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot17 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot18 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot19 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; + + class Hotspot20 : public NamedHotspot{ + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SceneObject _objDoor; + SceneObject _objCloak; + SceneObject _objJacket; + SceneObject _objTunic2; + SceneObject _objLever; + Object6 _objScimitar; + Object7 _objSword; + SoundHandler _soundHandler; + NamedHotspot _hotspot1; + NamedHotspot _hotspot2; + NamedHotspot _hotspot3; + NamedHotspot _hotspot4; + NamedHotspot _hotspot5; + NamedHotspot _hotspot6; + NamedHotspot _hotspot7; + NamedHotspot _hotspot8; + NamedHotspot _hotspot9; + NamedHotspot _hotspot10; + NamedHotspot _hotspot11; + Hotspot12 _hotspot12; + NamedHotspot _hotspot13; + Hotspot14 _hotspot14; + NamedHotspot _hotspot15; + Hotspot16 _hotspot16; + Hotspot17 _hotspot17; + Hotspot18 _hotspot18; + Hotspot19 _hotspot19; + Hotspot20 _spotLever; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); +}; + +class Scene9900 : public Scene { + class strAction1 : public Action { + public: + SceneObject _object9; + ScenePalette _palette1; + + virtual void signal(); + }; + + class strAction2 : public Action { + public: + SceneText _txtArray1[2]; + SceneText _txtArray2[2]; + int var1, _txtArray1Index, var3; + + virtual void signal(); + virtual void dispatch(); + }; + + class strAction3 : public Action { + public: + SceneObject _object10; + ScenePalette _palette2; + ScenePalette _palette3; + + virtual void signal(); + }; + + class SceneTextArr1 { + public: + SceneText _sceneText[2]; + }; + + class SceneTextArr2 { + public: + SceneText _sceneText[2]; + int _var1, var2, var3; + }; + +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneObject _object7; + SceneObjectExt _object8; + strAction1 _strAction1; + strAction2 _strAction2; + strAction3 _strAction3; + SpeakerMR _speakerMR; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); + virtual void process(Event &event); +}; + +class Scene9999 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + +public: + + Action1 _action1; + Action2 _action2; + Action _action3; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes2.cpp b/engines/tsage/ringworld_scenes2.cpp new file mode 100644 index 0000000000..8d95460615 --- /dev/null +++ b/engines/tsage/ringworld_scenes2.cpp @@ -0,0 +1,929 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/ringworld_scenes2.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 1000 - Title Screen + * + *--------------------------------------------------------------------------*/ + +void Scene1000::Action1::signal() { + Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(10); + break; + case 1: + scene->_object4.postInit(); + scene->_object4.setVisage(1001); + scene->_object4._frame = 1; + scene->_object4.setStrip2(5); + scene->_object4.changeZoom(100); + scene->_object4.animate(ANIM_MODE_2, NULL); + scene->_object4.setPosition(Common::Point(403, 163)); + setDelay(90); + break; + case 2: { + SceneItem::display(0, 0); + scene->_object4.remove(); + scene->_object1.changeZoom(-1); + NpcMover *mover = new NpcMover(); + Common::Point pt(180, 100); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_sceneManager.changeScene(1400); + break; + } + +} + +void Scene1000::Action2::signal() { + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(10); + break; + case 1: + SceneItem::display(1000, 0, SET_Y, 20, SET_FONT, 2, SET_BG_COLOUR, -1, + SET_EXT_BGCOLOUR, 35, SET_WIDTH, 200, SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(180); + break; + case 2: + SceneItem::display(0, 0); + _globals->_sceneManager.changeScene(2000); + break; + default: + break; + } +} + +void Scene1000::Action3::signal() { + Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_sceneManager._scene->loadBackground(0, 0); + setDelay(60); + break; + case 1: { + NpcMover *mover = new NpcMover(); + Common::Point pt(158, 31); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 2: + case 3: + setDelay(60); + break; + case 4: + _globals->_player.show(); + setDelay(240); + break; + case 5: { + // Intro.txt file presence is used to allow user option to skip the introduction + _globals->_player.enableControl(); + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading("Intro.txt"); + if (!in) { + // File not present, so create it + Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving("Intro.txt"); + out->finalize(); + delete out; + setDelay(1); + } else { + delete in; + + // Prompt user for whether to start play or watch introduction + if (MessageDialog::show2(WATCH_INTRO_MSG, START_PLAY_BTN_STRING, INTRODUCTION_BTN_STRING) == 0) { + _actionIndex = 20; + _globals->_soundHandler.proc1(this); + } else { + setDelay(1); + } + + _globals->_player.disableControl(); + } + break; + } + case 6: { + scene->_object3.remove(); + _globals->_player.setStrip2(2); + NpcMover *mover = new NpcMover(); + Common::Point pt(480, 100); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 7: + _globals->_scenePalette.loadPalette(1002); + _globals->_scenePalette.refresh(); + _globals->_scenePalette.addRotation(80, 95, -1); + scene->_object3.postInit(); + scene->_object3.setVisage(1002); + scene->_object3.setStrip(1); + scene->_object3.setPosition(Common::Point(284, 122)); + scene->_object3.changeZoom(1); + + zoom(true); + setDelay(200); + break; + case 8: + zoom(false); + setDelay(10); + break; + case 9: + scene->_object3.setStrip(2); + scene->_object3.setPosition(Common::Point(285, 155)); + + zoom(true); + setDelay(400); + break; + case 10: + zoom(false); + setDelay(10); + break; + case 11: + scene->_object3.setStrip(3); + scene->_object3.setPosition(Common::Point(279, 172)); + + zoom(true); + setDelay(240); + break; + case 12: + zoom(false); + setDelay(10); + break; + case 13: + scene->_object3.setStrip(4); + scene->_object3.setPosition(Common::Point(270, 128)); + + zoom(true); + setDelay(300); + break; + case 14: + zoom(false); + setDelay(10); + break; + case 15: + scene->_object3.setStrip(1); + scene->_object3.setFrame(2); + scene->_object3.setPosition(Common::Point(283, 137)); + + zoom(true); + setDelay(300); + break; + case 16: + zoom(false); + setDelay(10); + break; + case 17: + scene->_object3.setStrip(5); + scene->_object3.setFrame(1); + scene->_object3.setPosition(Common::Point(292, 192)); + + zoom(true); + setDelay(300); + break; + case 18: + zoom(false); + _globals->_scenePalette.clearListeners(); + _globals->_soundHandler.proc1(this); + break; + case 19: + _globals->_sceneManager.changeScene(10); + break; + case 20: + _globals->_sceneManager.changeScene(30); + break; + default: + break; + } +} + +void Scene1000::Action3::zoom(bool up) { + Scene1000 *scene = (Scene1000 *)_globals->_sceneManager._scene; + + if (up) { + while ((scene->_object3._percent < 100) && !_vm->shouldQuit()) { + scene->_object3.changeZoom(MIN(scene->_object3._percent + 5, 100)); + _globals->_sceneObjects->draw(); + _globals->_events.delay(1); + } + } else { + while ((scene->_object3._percent > 0) && !_vm->shouldQuit()) { + scene->_object3.changeZoom(MAX(scene->_object3._percent - 5, 0)); + _globals->_sceneObjects->draw(); + _globals->_events.delay(1); + } + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene1000::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + loadScene(1000); + + if (_globals->_sceneManager._previousScene == 2000) { + setZoomPercents(150, 10, 180, 100); + _object1.postInit(); + _object1.setVisage(1001); + _object1._strip = 7; + _object1.animate(ANIM_MODE_2, 0); + _object1._moveDiff = Common::Point(1, 1); + _object1.setPosition(Common::Point(120, 180)); + + setAction(&_action2); + + _globals->_sceneManager._scene->_sceneBounds.centre(_object1._position.x, _object1._position.y); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + _globals->_soundHandler.startSound(114); + } else if (_globals->_sceneManager._previousScene == 2222) { + setZoomPercents(150, 10, 180, 100); + _object1.postInit(); + _object1.setVisage(1001); + _object1._strip = 7; + _object1.animate(ANIM_MODE_2, 0); + _object1._moveDiff = Common::Point(2, 2); + _object1.setPosition(Common::Point(120, 180)); + + _globals->_sceneManager._scene->_sceneBounds.centre(_object1._position.x, _object1._position.y); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + + setAction(&_action1); + } else { + _globals->_soundHandler.startSound(4); + setZoomPercents(0, 10, 30, 100); + _object3.postInit(); + _object3.setVisage(1050); + _object3.changeZoom(-1); + _object3.setPosition(Common::Point(158, 0)); + + _globals->_player.postInit(); + _globals->_player.setVisage(1050); + _globals->_player.setStrip(3); + _globals->_player.setPosition(Common::Point(160, 191)); + _globals->_player._moveDiff.x = 12; + _globals->_player.hide(); + _globals->_player.disableControl(); + + _globals->_sceneManager._scene->_sceneBounds.centre(_object3._position.x, _object3._position.y); + + setAction(&_action3); + } +} + +/*-------------------------------------------------------------------------- + * Scene 1001 - Fleeing planet cutscene + * + *--------------------------------------------------------------------------*/ + +void Scene1001::Action1::signal() { + Scene1001 *scene = (Scene1001 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 2: { + Common::Point pt(108, 171); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 3: { + Common::Point pt(170, 159); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 4: { + scene->_object2.postInit(); + scene->_object2.setVisage(16); + scene->_object2.setStrip2(4); + scene->_object2.setPosition(Common::Point(61, 177)); + scene->_object2.animate(ANIM_MODE_5, this); + + Common::Point pt(320, 100); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 5: { + Common::Point pt(82, 166); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 6: { + Common::Point pt(64, 149); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 7: { + Common::Point pt(15, 136); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 8: { + Common::Point pt(-5, 120); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 9: { + scene->_object1.postInit(); + scene->_object1.setVisage(16); + scene->_object1.setStrip2(1); + scene->_object1.setFrame(1); + scene->_object1.setPosition(Common::Point(-75, 87)); + scene->_object1.animate(ANIM_MODE_2, NULL); + + Common::Point pt(0, 100); + NpcMover *mover = new NpcMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 10: { + Common::Point pt1(107, 115); + NpcMover *mover1 = new NpcMover(); + scene->_object1.addMover(mover1, &pt1, NULL); + + scene->_object3.setVisage(16); + scene->_object3.setStrip2(5); + scene->_object3.setFrame2(2); + scene->_object3.setPosition(Common::Point(220, 200)); + + Common::Point pt2(187, 181); + NpcMover *mover2 = new NpcMover(); + scene->_object3.addMover(mover2, &pt2, this); + break; + } + case 11: { + scene->_object2.setVisage(16); + scene->_object2.setStrip2(5); + scene->_object2.setFrame2(1); + scene->_object2.setPosition(Common::Point(211, 0)); + + Common::Point pt(189, 30); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 12: + scene->_stripManager.start(100, this); + break; + case 13: { + scene->_object4.postInit(); + scene->_object4.setVisage(16); + scene->_object4.setStrip2(2); + scene->_object4.setFrame(4); + scene->_object4.setPosition(Common::Point(360, 80)); + scene->_object4.animate(ANIM_MODE_2, NULL); + + Common::Point pt(303, 97); + NpcMover *mover = new NpcMover(); + scene->_object4.addMover(mover, &pt, this); + break; + } + case 14: + scene->_stripManager.start(110, this); + break; + case 15: + setDelay(10); + break; + case 16: { + scene->_soundHandler1.startSound(90); + + scene->_object6.postInit(); + scene->_object6.setVisage(16); + scene->_object6.setStrip2(6); + scene->_object6.setFrame2(2); + scene->_object6._moveDiff = Common::Point(20, 20); + scene->_object6.setPriority2(20); + scene->_object6.setPosition(Common::Point(scene->_object2._position.x - 6, scene->_object2._position.y + 7)); + scene->_object6.animate(ANIM_MODE_5, NULL); + + Common::Point pt(scene->_object6._position.x - 70, scene->_object6._position.y + 70); + NpcMover *mover = new NpcMover(); + scene->_object6.addMover(mover, &pt, this); + break; + } + case 17: { + scene->_soundHandler1.startSound(90); + scene->_object6.remove(); + + scene->_object7.postInit(); + scene->_object7.setVisage(16); + scene->_object7.setStrip2(6); + scene->_object7.setFrame2(1); + scene->_object7._moveDiff = Common::Point(20, 20); + scene->_object7.setPosition(Common::Point(scene->_object3._position.x - 28, scene->_object3._position.y - 11)); + scene->_object7.setPriority2(200); + scene->_object7.animate(ANIM_MODE_5, NULL); + + Common::Point pt(scene->_object7._position.x - 70, scene->_object7._position.y - 70); + NpcMover *mover = new NpcMover(); + scene->_object7.addMover(mover, &pt, this); + break; + } + case 18: + scene->_object7.remove(); + + scene->_object5.postInit(); + scene->_object5.setVisage(16); + scene->_object5.setPosition(Common::Point(306, 93)); + scene->_object5._strip = 3; + scene->_object5.setPriority2(200); + scene->_object5.animate(ANIM_MODE_2, NULL); + setDelay(30); + break; + case 19: { + _globals->_soundHandler.startSound(91); + byte adjustData[4] = {0xff, 0xff, 0xff, 0}; + _globals->_scenePalette.fade(adjustData, true, 0); + + scene->_object1._strip = 7; + scene->_object1._frame = 1; + scene->_object1.setPosition(Common::Point(314, 112)); + scene->_object1.addMover(NULL); + setDelay(2); + } + case 20: + _globals->_scenePalette.loadPalette(16); + _globals->_scenePalette.refresh(); + setDelay(6); + break; + case 21: + scene->_object1._numFrames = 15; + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 22: + _globals->_soundHandler.startSound(92); + scene->_stripManager.start(111, this); + break; + case 23: + setDelay(60); + break; + case 24: + _globals->_sceneManager.changeScene(2000); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene1001::postInit(SceneObjectList *OwnerList) { + loadScene(16); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerCText); + _stripManager.addSpeaker(&_speakerCR); + _stripManager.addSpeaker(&_speakerSL); + _speakerQText._colour1 = 11; + + _object3.postInit(); + _object3.setVisage(16); + _object3.setStrip2(4); + _object3.setPosition(Common::Point(61, 177)); + + _globals->_soundHandler.startSound(85); + setAction(&_action1); +} + + +/*-------------------------------------------------------------------------- + * Scene 1250 - + * + *--------------------------------------------------------------------------*/ + +void Scene1250::Action1::signal() { + Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(120) + 60); + break; + case 1: + scene->_object1.animate(ANIM_MODE_5, this); + _actionIndex = 0; + break; + } +} + +void Scene1250::Action2::signal() { + Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + switch (_globals->_randomSource.getRandomNumber(2)) { + case 0: + scene->_object2.setPosition(Common::Point(163, 75)); + break; + case 1: + scene->_object2.setPosition(Common::Point(109, 65)); + break; + case 2: + scene->_object2.setPosition(Common::Point(267, 20)); + break; + } + + setDelay(30); + break; + case 1: + scene->_object2.animate(ANIM_MODE_5, this); + _actionIndex = 0; + break; + } +} + +void Scene1250::Action3::signal() { + Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + scene->_stripManager.start(1251, this); + break; + case 2: + setDelay(6); + break; + case 3: + _globals->_sceneManager.changeScene(1000); + break; + } +} + +void Scene1250::Action4::signal() { + Scene1250 *scene = (Scene1250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + scene->_stripManager.start(1250, this); + break; + case 2: + setDelay(6); + break; + case 3: + _globals->_sceneManager.changeScene(2000); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene1250::postInit(SceneObjectList *OwnerList) { + loadScene(1250); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQText); + _speakerQText._textPos = Common::Point(120, 120); + _speakerQText._textWidth = 180; + + _object1.postInit(); + _object1.setVisage(1250); + _object1.setPosition(Common::Point(126, 69)); + _object1.setStrip2(1); + _object1._frame = 1; + _object1.setAction(&_action1); + + _object2.postInit(); + _object2.setVisage(1250); + _object2.setPosition(Common::Point(126, 69)); + _object2.setStrip2(2); + _object2.setPriority2(255); + _object2._frame = 1; + _object2.setAction(&_action2); + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + + if ((_globals->_sceneManager._previousScene != 2000) || (_globals->_stripNum != 1250)) { + setAction(&_action4); + } else { + setAction(&_action3); + _globals->_soundHandler.startSound(114); + } +} + +/*-------------------------------------------------------------------------- + * Scene 1400 - Ringworld Wall + * + *--------------------------------------------------------------------------*/ + +void Scene1400::Action1::signal() { + Scene1400 *scene = (Scene1400 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: { + SceneItem::display(1400, 0, SET_X, 120, SET_Y, 610, SET_FONT, 2, SET_EXT_BGCOLOUR, 23, SET_KEEP_ONSCREEN, -1, LIST_END); + + Common::Point pt(160, 700); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: { + _globals->_player.setStrip2(3); + _globals->_player.changeZoom(100); + + Common::Point pt(160, 100); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + + SceneItem::display(0, 0); + setDelay(360); + break; + } + case 3: + SceneItem::display(1400, 2, SET_X, 60, SET_Y, _globals->_sceneManager._scene->_sceneBounds.bottom - 80, + SET_FONT, 2, SET_FG_COLOUR, 13, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END); + setDelay(420); + break; + case 4: + SceneItem::display(0, 0); + setDelay(360); + break; + case 5: + SceneItem::display(1400, 3, SET_X, 60, SET_Y, _globals->_sceneManager._scene->_sceneBounds.bottom - 80, + SET_FONT, 2, SET_FG_COLOUR, 23, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END); + setDelay(360); + break; + case 6: + SceneItem::display(0, 0); + break; + case 7: { + _globals->_player._frame = 1; + _globals->_player.setStrip2(1); + _globals->_player._numFrames = 5; + _globals->_player.animate(ANIM_MODE_5, this); + + Common::Point pt(205, 70); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, NULL); + _globals->_sceneManager._fadeMode = FADEMODE_NONE; + + scene->loadScene(1402); + break; + } + case 8: + _globals->_player.setStrip2(2); + _globals->_player._numFrames = 10; + _globals->_player.animate(ANIM_MODE_2, NULL); + + SceneItem::display(1400, 4, SET_X, 30, SET_Y, _globals->_player._position.y + 10, SET_FONT, 2, + SET_FG_COLOUR, 13, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, -1, LIST_END); + setDelay(300); + break; + case 9: { + SceneItem::display(0, 0); + Common::Point pt(450, 45); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 10: + _globals->_sceneManager._scrollerRect = Rect(40, 20, 280, 180); + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_stripNum = 1500; + _globals->_soundHandler.proc3(); + + _globals->_sceneManager.changeScene(1500); + break; + } +} + +void Scene1400::Action1::dispatch() { + Action::dispatch(); + + if ((_actionIndex > 3) && (_actionIndex < 9)) + _globals->_sceneText.setPosition(Common::Point(60, _globals->_sceneManager._scene->_sceneBounds.bottom - 80)); + + if ((_actionIndex <= 2) && (_globals->_player._percent > 22)) + _globals->_player.changeZoom(100 - (800 - _globals->_player._position.y)); + + if ((_actionIndex >= 9) && (_globals->_player._percent > 22)) + _globals->_player.changeZoom(100 - (_globals->_player._position.x - 205)); +} + +/*--------------------------------------------------------------------------*/ + +void Scene1400::postInit(SceneObjectList *OwnerList) { + if (_globals->_stripNum != 1400) { + loadScene(1401); + } else { + loadScene(1402); + } + Scene::postInit(); + + _globals->_sceneManager._scrollerRect = Rect(40, 90, 280, 180); + _globals->_player.postInit(); + _globals->_player.setVisage(1401); + _globals->_player.animate(ANIM_MODE_2, 0); + _globals->_player.setStrip2(4); + _globals->_player.setPriority2(4); + _globals->_player.disableControl(); + + _globals->_player._moveDiff = Common::Point(4, 2); + _globals->_player.setPosition(Common::Point(160, 800)); + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.y = (_globals->_sceneManager._scene->_sceneBounds.top / 100) * 100; + + setAction(&_action1); + _globals->_soundHandler.startSound(118); +} + +/*-------------------------------------------------------------------------- + * Scene 1500 - Ringworld Space-port + * + *--------------------------------------------------------------------------*/ + +void Scene1500::Action1::signal() { + Scene1500 *scene = (Scene1500 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_object1.postInit(); + scene->_object1.setVisage(1501); + scene->_object1._moveDiff = Common::Point(2, 1); + scene->_object1.setPosition(Common::Point(204, 85)); + scene->_object1.animate(ANIM_MODE_2, NULL); + scene->_object1._numFrames = 3; + scene->_object1.changeZoom(-1); + + Common::Point pt(238, 121); + PlayerMover *mover = new PlayerMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 1: { + Common::Point pt(312, 145); + PlayerMover *mover = new PlayerMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object1.setStrip(2); + scene->_object1.setFrame(1); + scene->_object1._moveDiff.y = 2; + scene->_object1._numFrames = 5; + + Common::Point pt(310, 150); + PlayerMover *mover = new PlayerMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 3: { + Common::Point pt(304, 165); + PlayerMover *mover = new PlayerMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 4: { + scene->_object1._numFrames = 3; + scene->_object1.setStrip2(3); + scene->_object1.animate(ANIM_MODE_2, this); + + Common::Point pt(94, 175); + PlayerMover *mover = new PlayerMover(); + scene->_object1.addMover(mover, &pt, this); + break; + } + case 5: + setDelay(30); + break; + case 6: + scene->_soundHandler.startSound(123); + scene->_object1.setStrip2(4); + scene->_object1.setFrame(1); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 7: + scene->_object1.setStrip2(5); + scene->_object1.animate(ANIM_MODE_2, NULL); + scene->_soundHandler.startSound(124, this); + break; + case 8: + _globals->_soundHandler.startSound(126, this); + break; + case 9: + _globals->_soundHandler.startSound(127); + _globals->_sceneManager.changeScene(2000); + break; + } +} + +void Scene1500::Action2::signal() { + Scene1500 *scene = (Scene1500 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: { + scene->_object2.postInit(); + scene->_object2.setVisage(1502); + scene->_object2.setPriority2(255); + scene->_object2.changeZoom(5); + scene->_object2._frame = 1; + scene->_object2._moveDiff = Common::Point(1, 1); + scene->_object2.setPosition(Common::Point(104, 184)); + scene->_object2.animate(ANIM_MODE_2, NULL); + + Common::Point pt(118, 147); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object2._moveDiff.x = 5; + scene->_object2.changeZoom(-1); + Common::Point pt(-55, 200); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 3: + scene->_soundHandler.proc4(); + _globals->_stripNum = 1505; + _globals->_sceneManager.changeScene(1505); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene1500::postInit(SceneObjectList *OwnerList) { + loadScene(1500); + Scene::postInit(); + + if ((_globals->_stripNum == 1500) || ((_globals->_stripNum != 1504) && (_globals->_stripNum != 2751))) { + _globals->_soundHandler.startSound(120); + setZoomPercents(105, 20, 145, 100); + + setAction(&_action1); + } else { + setZoomPercents(150, 5, 200, 100); + + _object1.postInit(); + _object1.setVisage(1501); + _object1.setStrip2(5); + _object1.setPosition(Common::Point(94, 175)); + _object1.animate(ANIM_MODE_2, NULL); + + setAction(&_action2); + } +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes2.h b/engines/tsage/ringworld_scenes2.h new file mode 100644 index 0000000000..75843d3570 --- /dev/null +++ b/engines/tsage/ringworld_scenes2.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES2_H +#define TSAGE_RINGWORLD_SCENES2_H + +#include "common/scummsys.h" +#include "tsage/ringworld_logic.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +class Scene1000 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + private: + void zoom(bool up); + public: + virtual void signal(); + }; + +public: + SceneObject _object1, _object2, _object3, _object4; + Action1 _action1; + Action2 _action2; + Action3 _action3; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene1001 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; +public: + SpeakerQText _speakerQText; + SpeakerSL _speakerSL; + SpeakerCText _speakerCText; + SpeakerCR _speakerCR; + Action1 _action1; + SceneObject _object1, _object2, _object3, _object4; + SceneObject _object5, _object6, _object7; + SoundHandler _soundHandler1, _soundHandler2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene1250 : public Scene { +public: + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; +public: + SpeakerQText _speakerQText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + SceneObject _object1, _object2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene1400 : public Scene { +public: + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + virtual void dispatch(); + }; +public: + Action1 _action1; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + +}; + +class Scene1500 : public Scene { +public: + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; +public: + SoundHandler _soundHandler; + Action1 _action1; + Action2 _action2; + SceneObject _object1, _object2, _object3; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + + + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes3.cpp b/engines/tsage/ringworld_scenes3.cpp new file mode 100644 index 0000000000..b37b156907 --- /dev/null +++ b/engines/tsage/ringworld_scenes3.cpp @@ -0,0 +1,6098 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "tsage/ringworld_scenes3.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 2000 - Cockpit cutscenes + * + *--------------------------------------------------------------------------*/ + +void Scene2000::Action1::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + error("Old stuff"); + break; + case 1: + scene->_stripManager.start(2075, this); + break; + case 2: + setDelay(4); + break; + case 3: + _globals->_stripNum = 0; + _globals->_sceneManager.changeScene(1250); + break; + } +} + +void Scene2000::Action2::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_object2.animate(ANIM_MODE_6, NULL); + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + break; + case 1: + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + if (_globals->_randomSource.getRandomNumber(4) >= 2) + _actionIndex = 0; + break; + case 2: + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + _actionIndex = _globals->_randomSource.getRandomNumber(1); + break; + } +} + +void Scene2000::Action3::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_object6.animate(ANIM_MODE_5, NULL); + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + break; + case 1: + scene->_object6.animate(ANIM_MODE_6, NULL); + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + _actionIndex = 0; + break; + } +} + +void Scene2000::Action4::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_object4.animate(ANIM_MODE_5, NULL); + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + break; + case 1: + scene->_object4.animate(ANIM_MODE_6, NULL); + setDelay(_globals->_randomSource.getRandomNumber(179) + 60); + _actionIndex = 0; + break; + } +} + +void Scene2000::Action5::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_object3.animate(ANIM_MODE_5, NULL); + setDelay(_globals->_randomSource.getRandomNumber(125) + 300); + break; + case 1: + scene->_object3.animate(ANIM_MODE_6, NULL); + setDelay(_globals->_randomSource.getRandomNumber(125) + 300); + _actionIndex = 0; + break; + } +} + +void Scene2000::Action6::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(130); + break; + case 1: + scene->_soundHandler2.startSound(79); + scene->_stripManager.start(2000, this); + break; + case 2: + _globals->_soundHandler.startSound(81); + scene->_object6.postInit(); + scene->_object6.setVisage(2003); + scene->_object6.setAction(NULL); + scene->_object6.setStrip2(2); + scene->_object6.setPosition(Common::Point(184, 137)); + scene->_object6.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_stripManager.start(95, this); + break; + case 4: + scene->_object6.animate(ANIM_MODE_6, this); + break; + case 5: + _globals->_soundHandler.startSound(80); + scene->_object6.remove(); + _globals->_sceneManager.changeScene(1001); + break; + } +} + +void Scene2000::Action7::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + scene->_stripManager.start(2072, this); + break; + case 2: + setDelay(3); + break; + case 3: + _globals->_sceneManager.changeScene(2222); + break; + } +} + +void Scene2000::Action8::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + error("Old stuff"); + break; + case 1: + scene->_stripManager.start(2073, this); + break; + case 2: + setDelay(10); + break; + case 3: + _globals->_stripNum = 2005; + _globals->_sceneManager.changeScene(1000); + break; + } +} + +void Scene2000::Action9::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + error("Old stuff"); + break; + case 1: + scene->_stripManager.start(2074, this); + break; + case 2: + setDelay(3); + break; + case 3: + _globals->_stripNum = 2008; + _globals->_sceneManager.changeScene(9999); + break; + } +} + +void Scene2000::Action10::signal() { + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + error("Old stuff"); + break; + case 2: + SceneItem::display(2000, 17, SET_Y, 20, SET_X, 110, SET_FONT, 2, SET_BG_COLOUR, -1, + SET_FG_COLOUR, 17, SET_WIDTH, 200, SET_POS_MODE, 0, SET_KEEP_ONSCREEN, 1, LIST_END); + break; + case 3: + SceneItem::display(0, 0); + _globals->_stripNum = 0; + _globals->_sceneManager.changeScene(9999); + break; + } +} + +void Scene2000::Action11::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + error("Old stuff"); + break; + case 1: + scene->_stripManager.start(2076, this); + break; + case 2: + scene->_stripManager.start(2077, this); + break; + case 3: + _globals->_stripNum = 0; + _globals->_sceneManager.changeScene(1400); + break; + } +} + +void Scene2000::Action12::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(2020, this); + break; + case 2: + _globals->_player.disableControl(); + setDelay(10); + break; + case 3: + _globals->_sceneManager.changeScene(2300); + break; + } +} + +void Scene2000::Action13::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + scene->_stripManager.start(2078, this); + break; + case 2: + SceneItem::display(0, 0); + _globals->_stripNum = 2751; + _globals->_sceneManager.changeScene(1500); + break; + } +} + +void Scene2000::Action14::signal() { + Scene2000 *scene = (Scene2000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(30); + break; + case 1: + scene->_stripManager.start(2070, this); + break; + case 2: + setDelay(60); + break; + case 3: + _globals->_soundHandler.startSound(99); + scene->_object8.show(); + scene->_object8.animate(ANIM_MODE_5, this); + break; + case 4: + _globals->_soundHandler.startSound(12); + scene->_object8.setStrip(2); + scene->_object8.setFrame(1); + scene->_object9.show(); + scene->_object10.show(); + setDelay(60); + break; + case 5: + scene->_stripManager.start(2001, this, scene); + break; + case 6: + _globals->_soundHandler.proc1(0/* was false */); + scene->_object8.setStrip(1); + scene->_object8.setFrame(scene->_object8.getFrameCount()); + scene->_object8.animate(ANIM_MODE_6, this); + + scene->_object9.remove(); + scene->_object10.remove(); + break; + case 7: + _globals->_soundHandler.startSound(111); + scene->_object8.remove(); + setDelay(5); + break; + case 8: + scene->_stripManager.start(2071, this); + break; + case 9: + _globals->_stripNum = 1250; + _globals->_sceneManager.changeScene(1000); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2000::postInit(SceneObjectList *OwnerList) { + loadScene(2000); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerMR); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + _stripManager.addSpeaker(&_speakerHText); + + _speakerQText._npc = &_object2; + _speakerSText._npc = &_object3; + _speakerMText._npc = &_object6; + _speakerHText._npc = &_object6; + _stripManager.setCallback(this); + + _object3.postInit(); + _object3.setVisage(2002); + _object3.setPosition(Common::Point(65, 199)); + + _object4.postInit(); + _object4.setVisage(2002); + _object4.setStrip(2); + _object4.setPosition(Common::Point(125, 199)); + _object4.setAction(&_action4); + + _object2.postInit(); + _object2.setVisage(2001); + _object2.setPosition(Common::Point(43, 115)); + _object2.setAction(&_action2); + + _globals->_player.disableControl(); + + _object6.postInit(); + _object6.setVisage(2003); + _object6.setPosition(Common::Point(267, 170)); + _object6.setAction(&_action3); + + _object8.postInit(); + _object8.setVisage(2005); + _object8.setPosition(Common::Point(169, 133)); + _object8.setPriority(133); + _object8.hide(); + + _object9.postInit(); + _object9.setVisage(2005); + _object9.setStrip2(3); + _object9.setFrame(4); + _object9.setPosition(Common::Point(136, 86)); + _object9.setPriority2(190); + _object9.hide(); + + _object10.postInit(); + _object10.setVisage(2005); + _object10.setStrip2(5); + _object10.setFrame(4); + _object10.setPosition(Common::Point(202, 86)); + _object10.setPriority2(195); + _object10.hide(); + + switch (_globals->_sceneManager._previousScene) { + case 1000: + setAction(&_action7); + break; + case 1001: + _object6.remove(); + setAction(&_action12); + break; + case 1500: + setAction(&_action13); + break; + case 2200: + _globals->_soundHandler.startSound(111); + setAction(&_action14); + break; + case 2222: + _globals->_soundHandler.startSound(115); + setAction(&_action8); + break; + case 3500: + setAction(&_action11); + break; + default: + _object6.remove(); + _globals->_soundHandler.startSound(80); + setAction(&_action6); + break; + } + + _soundHandler1.startSound(78); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2000::stripCallback(int v) { + switch (v) { + case 0: + _object9.setStrip(3); + _object9.animate(ANIM_MODE_7, NULL); + _object10.setStrip(6); + _object10.setFrame(1); + _object10.animate(ANIM_MODE_5, NULL); + break; + case 1: + _object10.setStrip(5); + _object10.animate(ANIM_MODE_7, NULL); + _object9.setStrip(4); + _object9.setFrame(1); + _object9.animate(ANIM_MODE_5, NULL); + break; + case 2: + _object9.animate(ANIM_MODE_NONE, NULL); + break; + case 3: + _object10.setStrip(6); + _object10.setFrame(1); + _object10.animate(ANIM_MODE_5, NULL); + _object9.setStrip(4); + _object9.setFrame(1); + _object9.animate(ANIM_MODE_5, NULL); + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 2100 - Starcraft Cockpit + * + *--------------------------------------------------------------------------*/ + +void Scene2100::Action1::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + if (!scene->_field1800) + setDelay(1); + else { + setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL); + scene->_field1800 = 0; + } + break; + case 1: { + Common::Point pt(157, 62); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 3: { + Common::Point pt(157, 56); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 4: + _globals->_player._strip = 3; + setDelay(3); + break; + case 5: + _globals->_player.setPriority2(1); + scene->_area1.display(); + scene->_area2.display(); + scene->_area3.display(); + scene->_area4.display(); + + scene->_area1.draw(true); + _state = 0; + _globals->_events.setCursor(CURSOR_USE); + + while (!_state && !_vm->getEventManager()->shouldQuit()) { + // Wait for an event + Event event; + if (!_globals->_events.getEvent(event)) { + g_system->updateScreen(); + g_system->delayMillis(10); + continue; + } + + if (scene->_area1._bounds.contains(event.mousePos)) { + scene->_area1.draw(true); + _state = scene->_area1._actionId; + } + if (scene->_area2._bounds.contains(event.mousePos)) { + scene->_area1.draw(false); + scene->_area2.draw(true); + _state = scene->_area2._actionId; + } + if (scene->_area3._bounds.contains(event.mousePos)) { + scene->_area1.draw(false); + scene->_area3.draw(true); + _state = scene->_area3._actionId; + } + } + + scene->_soundHandler.startSound(161); + scene->_area1.restore(); + scene->_area2.restore(); + scene->_area3.restore(); + scene->_area4.restore(); + + if (_state == 2100) { + setDelay(1); + } else { + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + } + break; + case 6: + if (_state == 2100) { + Common::Point pt(157, 65); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } else { + _globals->_sceneManager.changeScene(_state); + } + break; + case 7: + _globals->_player.setPriority2(-1); + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 8: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2100::Action2::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_object3._numFrames = 5; + setDelay(_globals->_randomSource.getRandomNumber(59)); + break; + case 1: + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 2: + setDelay(_globals->_randomSource.getRandomNumber(59)); + break; + case 3: + scene->_object3.animate(ANIM_MODE_6, this); + _actionIndex = 0; + break; + } +} + +void Scene2100::Action3::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + case 2: + setDelay(_globals->_randomSource.getRandomNumber(119)); + break; + case 1: + scene->_object2.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_object2.animate(ANIM_MODE_6, this); + _actionIndex = 0; + break; + } +} + +void Scene2100::Action4::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + if (!scene->_field1800) + setDelay(1); + else + setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL); + break; + case 1: { + Common::Point pt(80, 66); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_player.setVisage(2109); + _globals->_player._frame = 1; + _globals->_player._strip = 2; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_sceneManager.changeScene(2120); + break; + } +} + +void Scene2100::Action5::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL); + break; + case 2: { + Common::Point pt(272, 127); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_player.checkAngle(&scene->_object3); + setDelay(30); + break; + case 4: + _globals->_sceneManager.changeScene(3700); + break; + } +} + +void Scene2100::Action6::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_object2.setVisage(2806); + scene->_object2.setStrip(1); + scene->_object2.setStrip2(-1); + scene->_object2.changeZoom(-1); + scene->_object2.setPosition(Common::Point(155, 116)); + scene->_object2.setObjectWrapper(new SceneObjectWrapper()); + scene->_object2.setAction(NULL); + scene->_object2.animate(ANIM_MODE_1, NULL); + + Common::Point pt(130, 116); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, NULL); + break; + } + case 1: { + scene->_object2.setPriority2(-1); + Common::Point pt(153, 67); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, NULL); + break; + } + case 2: + remove(); + break; + } +} + +void Scene2100::Action7::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL); + break; + case 2: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, NULL); + break; + case 3: + _globals->_sceneManager.changeScene(8100); + break; + } +} + +void Scene2100::Action8::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL); + break; + case 2: { + Common::Point pt(200, 174); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_player.checkAngle(&scene->_object3); + scene->_stripManager.start((_globals->_inventory._translator._sceneNumber == 1) ? 7720 : 7710, this); + break; + case 4: + if (_globals->_inventory._translator._sceneNumber != 1) + _globals->_sceneManager.changeScene(7600); + else { + _globals->setFlag(24); + _globals->_player.enableControl(); + remove(); + } + break; + } +} + +void Scene2100::Action9::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + scene->_stripManager.start(6050, this); + break; + case 2: + scene->_soundHandler.startSound(99); + scene->_object4.show(); + scene->_object4.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_soundHandler.startSound(12); + scene->_object4.setStrip(2); + scene->_stripManager.start(6051, this, scene); + break; + case 4: + scene->_soundHandler.proc1(0/* was false */); + scene->_object4.setStrip(1); + scene->_object4.setFrame(scene->_object4.getFrameCount()); + scene->_object4.animate(ANIM_MODE_6, this); + break; + case 5: + scene->_object4.hide(); + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(6010, this); + break; + case 6: + if (scene->_stripManager._field2E8 != 165) + setAction(&scene->_action10); + else + setAction(&scene->_action11); + break; + } +} + +void Scene2100::Action10::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL); + break; + case 2: { + _globals->_player.disableControl(); + Common::Point pt(155, 64); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + scene->_object3.setVisage(2105); + scene->_object3.setStrip(2); + scene->_object3.setFrame(1); + scene->_object3._numFrames = 10; + scene->_object3.setAction(NULL); + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 4: { + scene->_object3.setVisage(2705); + scene->_object3.setStrip2(-1); + scene->_object3.changeZoom(-1); + scene->_object3.setPriority2(-1); + scene->_object3.setPosition(Common::Point(260, 156)); + scene->_object3.setObjectWrapper(new SceneObjectWrapper()); + scene->_object3.animate(ANIM_MODE_1, NULL); + + Common::Point pt(166, 64); + PlayerMover *mover = new PlayerMover(); + scene->_object3.addMover(mover, &pt, this); + + setAction(&scene->_action6, NULL); + break; + } + case 5: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 6: { + _globals->_player.setPriority2(1); + Common::Point pt(144, 54); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 7: { + scene->_object3.setPriority2(2); + Common::Point pt1(163, 55); + NpcMover *mover1 = new NpcMover(); + scene->_object3.addMover(mover1, &pt1, NULL); + + scene->_object2.setPriority2(2); + Common::Point pt2(158, 55); + NpcMover *mover2 = new NpcMover(); + scene->_object2.addMover(mover2, &pt2, this); + break; + } + case 8: + _globals->_player.setPriority2(1); + _globals->_player.setStrip(1); + scene->_object3.setPriority2(1); + scene->_object3.setStrip(2); + scene->_object2.setPriority2(2); + scene->_object2.setStrip(3); + + setDelay(45); + break; + case 9: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 10: + _globals->setFlag(70); + _globals->_stripNum = 2101; + _globals->_sceneManager.changeScene(2320); + break; + } +} + +void Scene2100::Action11::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + scene->_object3._numFrames = 10; + scene->_object3.setAction(NULL); + scene->_object3.setVisage(2105); + scene->_object3.setStrip(2); + scene->_object3.setFrame(1); + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 2: { + scene->_object3.setVisage(2705); + scene->_object3.setStrip2(-1); + scene->_object3.changeZoom(-1); + scene->_object3.setPriority2(-1); + scene->_object3.setPosition(Common::Point(260, 156)); + scene->_object3.setObjectWrapper(new SceneObjectWrapper()); + scene->_object3.animate(ANIM_MODE_1, NULL); + + Common::Point pt(158, 62); + PlayerMover *mover = new PlayerMover(); + scene->_object3.addMover(mover, &pt, this); + + setAction(&scene->_action6, NULL); + break; + } + case 3: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 4: { + scene->_object3.setPriority2(1); + Common::Point pt1(163, 55); + NpcMover *mover1 = new NpcMover(); + scene->_object3.addMover(mover1, &pt1, NULL); + + scene->_object2.setPriority2(1); + Common::Point pt2(158, 55); + NpcMover *mover2 = new NpcMover(); + scene->_object2.addMover(mover2, &pt2, this); + break; + } + case 5: + scene->_object3.setStrip(2); + scene->_object2.setStrip(3); + setDelay(45); + break; + case 6: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 7: + scene->_object3.remove(); + scene->_object2.remove(); + _globals->setFlag(70); + _globals->_stripNum = 2102; + _globals->_player.enableControl(); + _globals->_player._canWalk = false; + break; + } +} + +void Scene2100::Action12::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_stripManager.start(6000, this); + break; + case 2: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 3: { + Common::Point pt1(158, 74); + NpcMover *mover1 = new NpcMover(); + _globals->_player.addMover(mover1, &pt1, this); + + Common::Point pt2(158, 68); + NpcMover *mover2 = new NpcMover(); + scene->_object2.addMover(mover2, &pt2, NULL); + break; + } + case 4: { + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, NULL); + + _globals->_player.setPriority2(-1); + Common::Point pt1(277, 84); + PlayerMover *mover1 = new PlayerMover(); + _globals->_player.addMover(mover1, &pt1, this); + + scene->_object2.setPriority2(-1); + Common::Point pt2(255, 76); + PlayerMover *mover2 = new PlayerMover(); + scene->_object2.addMover(mover2, &pt2, this); + break; + } + case 6: + _globals->_player.setStrip(4); + scene->_object2.setStrip(4); + setDelay(60); + break; + case 7: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(6052, this); + break; + case 8: + if (scene->_stripManager._field2E8 == 320) + _globals->setFlag(74); + setDelay(30); + break; + case 9: + _globals->_events.setCursor(OBJECT_STUNNER); + scene->_object2.setAction(&scene->_action13); + setDelay(60); + break; + case 10: + if (_globals->getFlag(74)) + setDelay(1); + break; + case 11: + scene->_stripManager.start(2170, this); + break; + case 12: + setDelay(5); + break; + case 13: + scene->_stripManager.start(_globals->getFlag(74) ? 2172 : 2174, this); + break; + case 14: + if (_globals->getFlag(74)) { + _globals->_stripNum = 6100; + _globals->_sceneManager.changeScene(2320); + } else { + _globals->_sceneManager.changeScene(6100); + } + remove(); + break; + } +} + +void Scene2100::Action13::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: { + scene->_object2.setPriority2(113); + Common::Point pt(178, 116); + PlayerMover *mover = new PlayerMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 2: { + Common::Point pt(150, 116); + NpcMover *mover = new NpcMover(); + scene->_object2.addMover(mover, &pt, this); + break; + } + case 3: + scene->_object2.setVisage(2108); + scene->_object2._strip = 3; + scene->_object2.setPosition(Common::Point(150, 100)); + scene->_object2.animate(ANIM_MODE_NONE, NULL); + scene->_object2.changeZoom(100); + scene->_object2.setAction(&scene->_action3); + setDelay(15); + break; + case 4: + remove(); + break; + } +} + +void Scene2100::Action14::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL); + break; + case 2: + setAction(&scene->_sequenceManager, this, 2101, &_globals->_player, NULL); + break; + case 3: + scene->_stripManager.start(6008, this); + break; + case 4: + scene->_soundHandler.startSound(99); + scene->_object4.show(); + scene->_object4.animate(ANIM_MODE_5, this); + break; + case 5: + scene->_object4.setStrip(2); + scene->_stripManager.start(6009, this, scene); + break; + case 6: + scene->_soundHandler.proc1(0/* was false */); + scene->_object4.setStrip(1); + scene->_object4.setFrame(scene->_object4.getFrameCount()); + scene->_object4.animate(ANIM_MODE_6, this); + break; + case 7: + scene->_stripManager.start(6060, this); + break; + case 8: + scene->_object3._numFrames = 10; + scene->_object3.setAction(NULL); + scene->_object3.setVisage(2105); + scene->_object3.setStrip(2); + scene->_object3.setFrame(1); + scene->_object3.animate(ANIM_MODE_5, this); + break; + case 9: { + scene->_object3.setVisage(2705); + scene->_object3.setStrip2(-1); + scene->_object3.changeZoom(-1); + scene->_object3.setPriority2(-1); + scene->_object3.setPosition(Common::Point(260, 156)); + scene->_object3.setObjectWrapper(new SceneObjectWrapper()); + scene->_object3.animate(ANIM_MODE_1, NULL); + + Common::Point pt(157, 65); + PlayerMover *mover = new PlayerMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 10: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 11: { + Common::Point pt(159, 51); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 12: + scene->_object3.setStrip(2); + setDelay(30); + case 13: + scene->_object3.setPriority2(1); + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 14: + setDelay(90); + break; + case 15: + _globals->_sceneManager.changeScene(7000); + remove(); + break; + } +} + +void Scene2100::Action15::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: + scene->_object3.postInit(); + scene->_object3.setVisage(2705); + scene->_object3.animate(ANIM_MODE_1, NULL); + scene->_object3.setObjectWrapper(new SceneObjectWrapper()); + scene->_object3.setPosition(Common::Point(157, 56)); + scene->_object3.setPriority2(1); + scene->_object3.changeZoom(-1); + + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 2: { + scene->_object3.setPriority2(-1); + Common::Point pt(177, 68); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 3: { + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + + Common::Point pt(272, 140); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 4: { + Common::Point pt(266, 150); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 5: { + scene->_object3.setPriority2(156); + + Common::Point pt(260, 156); + NpcMover *mover = new NpcMover(); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 6: + scene->_object3.setVisage(2105); + scene->_object3._strip = 1; + scene->_object3._frame = 1; + scene->_object3.setPosition(Common::Point(256, 156)); + scene->_object3.animate(ANIM_MODE_5, this); + scene->_object3.changeZoom(100); + + scene->_object3.animate(ANIM_MODE_NONE, NULL); + break; + case 7: + remove(); + break; + } +} + +void Scene2100::Action16::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + case 4: + setDelay(3); + break; + case 1: + scene->_stripManager.start(7001, this); + break; + case 2: + setAction(&scene->_sequenceManager, this, 2102, &_globals->_player, NULL); + break; + case 3: { + _globals->_player.disableControl(); + Common::Point pt(155, 63); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 5: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 6: { + Common::Point pt(160, 54); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 7: + _globals->_player.setPriority2(1); + _globals->_player.setStrip(3); + setDelay(45); + break; + case 8: + scene->_soundHandler.startSound(162); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 9: + _globals->setFlag(15); + _globals->setFlag(36); + _globals->_sceneManager.changeScene(7000); + remove(); + break; + } +} + +void Scene2100::Action17::signal() { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + setAction(&scene->_sequenceManager, this, 2104, &_globals->_player, &scene->_object1, NULL); + break; + case 2: + setAction(&scene->_sequenceManager, this, 2101, &_globals->_player, NULL); + break; + case 3: + scene->_stripManager.start(7070, this); + break; + case 4: + scene->_soundHandler.startSound(99); + scene->_object4.show(); + scene->_object4.animate(ANIM_MODE_5, this); + break; + case 5: + scene->_soundHandler.startSound(12); + scene->_object4.setStrip(2); + scene->_stripManager.start(7071, this, scene); + break; + case 6: + scene->_soundHandler.proc1(NULL); + scene->_object4.setStrip(1); + scene->_object4.setFrame(scene->_object4.getFrameCount()); + scene->_object4.animate(ANIM_MODE_6, this); + break; + case 7: + scene->_stripManager.start(7072, this); + break; + case 8: + _globals->_inventory._stasisNegator._sceneNumber = 1; + _globals->_sceneManager.changeScene(9100); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2100::Hotspot2::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 3); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2100, 29); + else { + _globals->_player.disableControl(); + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Hotspot3::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 4); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2100, 29); + else { + _globals->_player.disableControl(); + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Hotspot4::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 5); + break; + case CURSOR_USE: + SceneItem::display2(2100, 6); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Hotspot8::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 12); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2100, 29); + else { + _globals->_player.disableControl(); + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Hotspot10::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 13); + break; + case CURSOR_USE: + if (scene->_field1800) { + _globals->_player.disableControl(); + scene->_sceneMode = 2102; + scene->setAction(&scene->_sequenceManager, scene, 2102, &_globals->_player, NULL); + } else if (_globals->getFlag(13)) { + SceneItem::display2(2100, 28); + } else { + scene->setAction(&scene->_sequenceManager, scene, 2101, &_globals->_player, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Hotspot14::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(0)) + SceneItem::display2(2100, 19); + else + SceneItem::display2(2100, 18); + break; + case CURSOR_USE: + if (_globals->getFlag(1)) + SceneItem::display2(2100, 21); + else + SceneItem::display2(2100, 20); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Object1::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 1); + break; + case CURSOR_USE: + scene->setAction(&scene->_action1); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Object2::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2100, 30); + break; + case CURSOR_TALK: + if (_globals->getFlag(72)) { + _globals->_player.disableControl(); + if (!_globals->getFlag(52)) + scene->setAction(&scene->_sequenceManager, scene, 2111, NULL); + else { + scene->_sceneMode = _globals->getFlag(53) ? 2112 : 2110; + scene->setAction(&scene->_sequenceManager, scene, scene->_sceneMode, NULL); + } + } else { + if (_globals->getFlag(14)) + SceneItem::display2(2100, 32); + else { + _globals->setFlag(14); + _globals->_player.disableControl(); + scene->_sceneMode = 2108; + scene->setAction(&scene->_sequenceManager, scene, 2109, NULL); + } + } + + scene->setAction(&scene->_action4); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2100::Object3::doAction(int action) { + Scene2100 *scene = (Scene2100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (!_globals->getFlag(59)) + SceneItem::display2(2100, 34); + else + error("***I have no response."); + break; + + case CURSOR_TALK: + if (!_globals->getFlag(59)) { + _globals->_player.disableControl(); + scene->_sceneMode = 2108; + scene->setAction(&scene->_sequenceManager, scene, 2108, NULL); + } else { + error("***I have no response."); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene2100::Scene2100() : + _hotspot1(0, CURSOR_LOOK, 2100, 2, LIST_END), + _hotspot5(0, CURSOR_LOOK, 2100, 9, LIST_END), + _hotspot6(0, CURSOR_LOOK, 2100, 7, CURSOR_USE, 2100, 8, LIST_END), + _hotspot7(0, CURSOR_LOOK, 2100, 7, CURSOR_USE, 2100, 11, LIST_END), + _hotspot9(0, CURSOR_LOOK, 2100, 14, LIST_END), + _hotspot11(0, CURSOR_LOOK, 2100, 15, CURSOR_USE, 2100, 16, LIST_END), + _hotspot12(0, CURSOR_LOOK, 2100, 24, CURSOR_USE, 2100, 25, LIST_END), + _hotspot13(0, CURSOR_LOOK, 2100, 17, LIST_END), + _hotspot15(0, CURSOR_LOOK, 2100, 22, CURSOR_USE, 2100, 23, LIST_END) { +} + +void Scene2100::postInit(SceneObjectList *OwnerList) { + loadScene(2100); + Scene::postInit(); + setZoomPercents(60, 80, 200, 100); + + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerMR); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerSAL); + _stripManager.addSpeaker(&_speakerHText); + _stripManager.addSpeaker(&_speakerGameText); + _speakerMText._npc = &_object3; + _speakerQText._npc = &_globals->_player; + _speakerSText._npc = &_object2; + + _object1.postInit(); + _object1.setVisage(2100); + _object1.animate(ANIM_MODE_NONE, NULL); + _object1.setPosition(Common::Point(157, 57)); + _object1.setPriority(5); + + _hotspot3.postInit(); + _hotspot3.setVisage(2101); + _hotspot3._frame = 1; + _hotspot3.animate(ANIM_MODE_2, NULL); + _hotspot3.setPosition(Common::Point(53, 44)); + _hotspot3.changeZoom(100); + _hotspot3.setPriority2(1); + + _hotspot4.postInit(); + _hotspot4.setVisage(2101); + _hotspot4._frame = 1; + _hotspot4._strip = 3; + _hotspot4.animate(ANIM_MODE_8, 0, NULL); + _hotspot4.setPosition(Common::Point(274, 52)); + _hotspot4.changeZoom(100); + _hotspot4.setPriority2(1); + + _hotspot5.postInit(); + _hotspot5.setVisage(2101); + _hotspot5._frame = 1; + _hotspot5._strip = 4; + _hotspot5.animate(ANIM_MODE_8, 0, NULL); + _hotspot5.setPosition(Common::Point(219, 141)); + _hotspot5.changeZoom(100); + _hotspot5.setPriority2(160); + + _hotspot6.postInit(); + _hotspot6.setVisage(2101); + _hotspot6._frame = 1; + _hotspot6._strip = 5; + _hotspot6.setPriority2(175); + _hotspot6.animate(ANIM_MODE_8, 0, NULL); + _hotspot6.setPosition(Common::Point(97, 142)); + _hotspot6.changeZoom(100); + + _hotspot7.postInit(); + _hotspot7.setVisage(2101); + _hotspot7._frame = 1; + _hotspot7._strip = 6; + _hotspot7.animate(ANIM_MODE_NONE, NULL); + _hotspot7.setPosition(Common::Point(133, 46)); + _hotspot7.changeZoom(100); + _hotspot7.setPriority2(1); + + _hotspot8.postInit(); + _hotspot8.setVisage(2101); + _hotspot8._frame = 1; + _hotspot8._strip = 7; + _hotspot8.animate(ANIM_MODE_8, 0, NULL); + _hotspot8.setPosition(Common::Point(20, 45)); + _hotspot8.changeZoom(100); + _hotspot8.setPriority2(1); + + _hotspot2.postInit(); + _hotspot2.setVisage(2101); + _hotspot2._frame = 1; + _hotspot2._strip = 7; + _hotspot2.animate(ANIM_MODE_8, 0, NULL); + _hotspot2.setPosition(Common::Point(88, 41)); + _hotspot2.changeZoom(100); + _hotspot2.setPriority2(1); + + _hotspot11.setBounds(Rect(139, 74, 173, 96)); + _hotspot10.setBounds(Rect(71, 100, 91, 135)); + _hotspot9.setBounds(Rect(225, 110, 251, 136)); + _hotspot14.setBounds(Rect(100, 97, 216, 130)); + _hotspot13.setBounds(Rect(13, 124, 94, 168)); + _hotspot12.setBounds(Rect(217, 141, 307, 155)); + _hotspot15.setBounds(Rect(14, 90, 46, 107)); + _hotspot1.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + if (!_globals->getFlag(36) && !_globals->getFlag(70) && !_globals->getFlag(43)) { + _object3.postInit(); + _object3.setPosition(Common::Point(246, 156)); + _object3.animate(ANIM_MODE_NONE, NULL); + _object3.changeZoom(100); + _object3.setPriority2(156); + _object3.setVisage(2107); + _object3.setStrip(1); + _object3.setAction(&_action2); + _globals->_sceneItems.push_back(&_object3); + } + + if (!_globals->getFlag(59) && !_globals->getFlag(70) && !_globals->getFlag(37) && !_globals->getFlag(114)) { + _object2.postInit(); + _object2.setVisage(2108); + _object2._strip = 3; + _object2.setPosition(Common::Point(150, 100)); + _object2.animate(ANIM_MODE_NONE, NULL); + _object2.changeZoom(100); + _object2.setPriority2(113); + _object2.setAction(&_action3); + _globals->_sceneItems.push_back(&_object2); + } + + _globals->_sceneItems.addItems(&_hotspot15, &_hotspot11, &_hotspot10, &_hotspot9, &_hotspot14, + &_hotspot13, &_hotspot12, &_hotspot8, &_object1, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, + &_hotspot6, &_hotspot7, &_hotspot1, NULL); + + _area1.setup(2153, 2, 1, 2100); + _area1._pt = Common::Point(200, 31); + _area2.setup(2153, 3, 1, 2150); + _area2._pt = Common::Point(200, 50); + _area3.setup(2153, 4, 1, 2320); + _area3._pt = Common::Point(200, 75); + _area4.setup(2153, 1, 1, OBJECT_TRANSLATOR); + _area4._pt = Common::Point(237, 77); + + _globals->_player.postInit(); + _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._moveDiff.x = 4; + _globals->_player.changeZoom(-1); + _globals->_player.disableControl(); + _field1800 = 0; + + switch (_globals->_sceneManager._previousScene) { + case 2120: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _object1.setPriority2(-1); + _globals->_player.setPriority2(-1); + _globals->_player.setPosition(Common::Point(80, 66)); + _globals->_player.enableControl(); + break; + case 2150: + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(157, 56)); + _sceneMode = 2104; + setAction(&_sequenceManager, this, 2104, &_globals->_player, &_object1, NULL); + break; + case 2222: + if (_globals->_sceneObjects->contains(&_object3)) + _object3.remove(); + + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(144, 55)); + + _object2.setVisage(2806); + _object2.changeZoom(-1); + _object2.setPosition(Common::Point(158, 55)); + _object2.setPriority2(1); + _object2.setAction(NULL); + _object2.setObjectWrapper(new SceneObjectWrapper()); + _object2.animate(ANIM_MODE_1, NULL); + _object2.setStrip(3); + setAction(&_action12); + break; + case 2320: + if (_globals->_stripNum == 2321) { + if (_globals->_sceneObjects->contains(&_object3)) + _object3.remove(); + + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(144, 55)); + + _object2.postInit(); + _object2.setVisage(2806); + _object2.setStrip(1); + _object2.changeZoom(-1); + _object2.setPosition(Common::Point(158, 55)); + _object2.setPriority2(1); + _object2.setAction(NULL); + _object2.setObjectWrapper(new SceneObjectWrapper()); + _object2.animate(ANIM_MODE_1, NULL); + + setAction(&_action12); + } else if (_globals->_stripNum == 6100) { + _globals->_player.setPosition(Common::Point(157, 56)); + _globals->_player.setPriority2(1); + + _object4.postInit(); + _object4.setVisage(2102); + _object4.setPosition(Common::Point(160, 199)); + _object4.hide(); + + setAction(&_action14); + } else { + _globals->_player.disableControl(); + _globals->_player.setPosition(Common::Point(157, 56)); + _sceneMode = 2104; + + setAction(&_sequenceManager, this, 2104, &_globals->_player, &_object1, NULL); + } + break; + case 3700: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + Scene::setZoomPercents(80, 75, 100, 90); + + if (_globals->_sceneObjects->contains(&_object2)) + _object2.remove(); + + _globals->_player._angle = 225; + _globals->_player.setStrip(6); + _globals->_player.setFrame(1); + _globals->_player.setPriority2(-1); + _globals->_player.setPosition(Common::Point(272, 127)); + + _object3.setPosition(Common::Point(246, 156)); + _object3.setPriority2(156); + _sceneMode = 2105; + setAction(&_sequenceManager, this, 2105, &_object3, NULL); + break; + case 4250: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _globals->clearFlag(43); + + _globals->_player.setVisage(2104); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(65, 149)); + _globals->_player.setPriority2(152); + _globals->_player.setStrip(2); + + _object4.postInit(); + _object4.setVisage(2102); + _object4.setPosition(Common::Point(160, 199)); + _object4.hide(); + + _sceneMode = 2107; + setAction(&_sequenceManager, this, 2107, &_object4, NULL); + break; + case 5000: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + if (_globals->_sceneObjects->contains(&_object2)) + _object2.remove(); + + _globals->_player.setStrip(3); + _globals->_player.setFrame(1); + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(157, 56)); + + _object3.setPosition(Common::Point(246, 156)); + _object3.setPriority2(156); + + setAction(&_action5); + break; + case 5100: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _globals->_player.setVisage(2104); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(65, 149)); + _globals->_player.setPriority2(152); + _globals->_player.setStrip(2); + + _field1800 = 1; + + _object4.postInit(); + _object4.setVisage(2102); + _object4.setPosition(Common::Point(160, 199)); + _object4.hide(); + + _globals->_inventory._stasisBox._sceneNumber = 0; + setAction(&_action9); + break; + case 7000: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + if (_globals->_inventory._stasisBox2._sceneNumber == 1) { + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(157, 56)); + + _object4.postInit(); + _object4.setVisage(2102); + _object4.setPosition(Common::Point(160, 199)); + _object4.hide(); + _globals->clearFlag(15); + _globals->clearFlag(109); + _globals->clearFlag(72); + + setAction(&_action17); + } else { + _globals->_player.setVisage(2104); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(65, 149)); + _globals->_player.setPriority2(152); + _globals->_player.setStrip(2); + + _field1800 = 1; + setAction(&_action16); + } + break; + case 7600: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + if (_globals->_sceneObjects->contains(&_object2)) + _object2.remove(); + + _globals->_player.setPriority2(1); + _globals->_player.setPosition(Common::Point(157, 56)); + + setAction(&_action8); + break; + case 8100: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + _globals->_player.setVisage(2104); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(65, 149)); + _globals->_player.setPriority2(152); + _globals->_player.setStrip(2); + + _sceneMode = 2106; + setAction(&_sequenceManager, this, 2106, NULL); + break; + case 9750: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + _globals->_player.setVisage(2104); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(65, 149)); + _globals->_player.setPriority2(152); + _globals->_player.setStrip(2); + + _object4.postInit(); + _object4.setVisage(2102); + _object4.setPosition(Common::Point(160, 199)); + _object4.hide(); + + _sceneMode = 2103; + setAction(&_sequenceManager, this, 2103, &_object4, NULL); + break; + default: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + _globals->_player._uiEnabled = true; + break; + } + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2100::stripCallback(int v) { + switch (v) { + case 1: + _object4._numFrames = 4; + _object4.animate(ANIM_MODE_7, NULL); + break; + case 2: + _object4.animate(ANIM_MODE_NONE, NULL); + break; + } +} + +void Scene2100::signal() { + switch (_sceneMode) { + case 2101: + _field1800 = 1; + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + break; + case 2102: + _field1800 = 0; + _globals->_player.enableControl(); + break; + case 2103: + _globals->_stripNum = 9000; + _globals->_sceneManager.changeScene(4000); + break; + case 2106: + _globals->_sceneManager.changeScene(7000); + break; + case 2107: + _globals->_sceneManager.changeScene(5000); + break; + case 2104: + case 2105: + case 2108: + case 2110: + case 2111: + case 2112: + _globals->_player.enableControl(); + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 2120 - Encyclopedia + * + *--------------------------------------------------------------------------*/ + +Scene2120::Action1::Action1() { + _entries.push_back(Entry(0, 0, 0)); + _entries.push_back(Entry(0, 0, 0)); + _entries.push_back(Entry(4, 1, 2123)); + _entries.push_back(Entry(1, 6, 0)); + _entries.push_back(Entry(2, 8, 0)); + _entries.push_back(Entry(1, 11, 0)); + _entries.push_back(Entry(4, 13, 2131)); + _entries.push_back(Entry(2, 18, 0)); + _entries.push_back(Entry(4, 21, 0)); + _entries.push_back(Entry(7, 26, 2128)); + _entries.push_back(Entry(3, 34, 0)); + _entries.push_back(Entry(0, 38, 0)); + _entries.push_back(Entry(3, 39, 2126)); + _entries.push_back(Entry(3, 43, 0)); + _entries.push_back(Entry(4, 47, 2125)); + _entries.push_back(Entry(3, 52, 0)); + _entries.push_back(Entry(4, 56, 2129)); + _entries.push_back(Entry(7, 61, 0)); + _entries.push_back(Entry(2, 69, 2127)); + _entries.push_back(Entry(7, 72, 2122)); + _entries.push_back(Entry(0, 80, 2124)); + _entries.push_back(Entry(0, 81, 0)); + _entries.push_back(Entry(0, 82, 0)); + _entries.push_back(Entry(1, 83, 0)); + _entries.push_back(Entry(2, 85, 2132)); + _entries.push_back(Entry(1, 88, 2133)); + _entries.push_back(Entry(2, 90, 2136)); + _entries.push_back(Entry(1, 93, 0)); + _entries.push_back(Entry(10, 95, 2135)); + _entries.push_back(Entry(5, 106, 0)); + _entries.push_back(Entry(2, 112, 2134)); + _entries.push_back(Entry(1, 115, 2130)); + _entries.push_back(Entry(0, 117, 0)); +} + +void Scene2120::Action1::signal() { + Scene2120 *scene = (Scene2120 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + _globals->_events.setCursor(CURSOR_WALK); + break; + case 1: + // First page of index + SceneItem::display(2120, 0, SET_X, 120, SET_FONT, 1, SET_EXT_BGCOLOUR, 7, SET_BG_COLOUR, -1, + SET_WIDTH, 200, SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END); + break; + case 2: + // Second page of index + SceneItem::display(2120, 1, SET_X, 120, SET_FONT, 1, SET_EXT_BGCOLOUR, 7, SET_BG_COLOUR, -1, + SET_WIDTH, 200, SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END); + break; + case 3: + // Display an image associated with the encyclopedia entry + SceneItem::display(0, 0); + + scene->_visageHotspot.postInit(); + scene->_visageHotspot.setVisage(_entries[scene->_subjectIndex]._visage); + scene->_visageHotspot.setPosition(Common::Point(129, 180)); + scene->_visageHotspot.animate(ANIM_MODE_NONE, NULL); + scene->_visageVisable = true; + break; + case 4: + // Display page of text + SceneItem::display(2121, _entries[scene->_subjectIndex]._lineNum + scene->_lineOffset, + SET_X, 130, SET_FONT, 1, SET_EXT_BGCOLOUR, 7, SET_BG_COLOUR, -1, SET_WIDTH, 200, + SET_KEEP_ONSCREEN, -1, SET_TEXT_MODE, 0, LIST_END); + _actionIndex = 4; + break; + } +} + +void Scene2120::Action1::dispatch() { + Scene2120 *scene = (Scene2120 *)_globals->_sceneManager._scene; + + Event event; + if (_globals->_events.getEvent(event) && (event.eventType == EVENT_BUTTON_DOWN)) { + if (scene->_listRect.contains(event.mousePos) && (scene->_dbMode != 2)) { + scene->_topicArrowHotspot.setPosition(Common::Point(scene->_topicArrowHotspot._position.x, event.mousePos.y)); + } + + // Subject button handling + if (scene->_subjectButton._bounds.contains(event.mousePos) && (scene->_dbMode != 2)) { + scene->_arrowHotspot.setPosition(Common::Point(291, 34)); + scene->_arrowHotspot._strip = 1; + scene->_arrowHotspot.animate(ANIM_MODE_5, NULL); + + if (scene->_dbMode == 0) + scene->_subjectIndex = (scene->_topicArrowHotspot._position.y - 48) / 8; + else + scene->_subjectIndex = (scene->_topicArrowHotspot._position.y - 44) / 8 + 16; + + if ((scene->_subjectIndex == 27) && _globals->getFlag(70)) + _globals->setFlag(75); + + scene->_topicArrowHotspot.hide(); + scene->_prevDbMode = scene->_dbMode; + scene->_dbMode = 2; + scene->_lineOffset = 0; + + _actionIndex = !_entries[scene->_subjectIndex]._visage ? 4 : 3; + setDelay(30); + scene->_soundHandler.startSound(159); + } + + // Next Page button handling + if (scene->_nextPageButton._bounds.contains(event.mousePos)) { + if (!scene->_dbMode) { + scene->_arrowHotspot._strip = 2; + scene->_arrowHotspot.setPosition(Common::Point(291, 76)); + scene->_arrowHotspot.animate(ANIM_MODE_5, NULL); + scene->_dbMode = 1; + + _actionIndex = 2; + setDelay(30); + } + + if ((scene->_dbMode == 2) && (scene->_lineOffset < _entries[scene->_subjectIndex]._size)) { + if (!scene->_visageVisable) { + ++scene->_lineOffset; + } else { + scene->_visageVisable = false; + scene->_visageHotspot.remove(); + } + setDelay(30); + } + + if ((scene->_subjectIndex == 20) && scene->_visageVisable) { + scene->_visageVisable = false; + scene->_visageHotspot.remove(); + setDelay(30); + } + + scene->_soundHandler.startSound(159); + } + + // Previous Page button handling + if (scene->_previousPageButton._bounds.contains(event.mousePos)) { + switch (scene->_dbMode) { + case 1: + scene->_arrowHotspot._strip = 3; + scene->_arrowHotspot.setPosition(Common::Point(291, 117)); + scene->_arrowHotspot.animate(ANIM_MODE_5, NULL); + + scene->_dbMode = 0; + _actionIndex = 1; + setDelay(30); + break; + case 2: + if (scene->_lineOffset > 0) { + --scene->_lineOffset; + setDelay(20); + } + if ((_entries[scene->_subjectIndex]._visage != 0) && (scene->_lineOffset == 0)) { + _actionIndex = 3; + setDelay(30); + } + break; + } + + scene->_soundHandler.startSound(159); + } + + // Exit button handling + if (scene->_exitButton._bounds.contains(event.mousePos)) { + if (scene->_dbMode != 2) { + // In the index, so return to the previous scene + setAction(NULL); + SceneItem::display(0, 0); + + _globals->_gfxManagerInstance._font.setFontNumber(2); + _globals->_sceneText._fontNumber = 2; + _globals->_sceneManager.changeScene(_globals->_sceneManager._previousScene); + } else { + // Exit out of topic display to index + SceneItem::display(0, 0); + + if (_entries[scene->_subjectIndex]._visage) + scene->_visageHotspot.remove(); + + scene->_arrowHotspot._strip = 4; + scene->_arrowHotspot.setPosition(Common::Point(291, 159)); + scene->_arrowHotspot.animate(ANIM_MODE_5, NULL); + scene->_dbMode = scene->_prevDbMode; + _actionIndex = scene->_prevDbMode + 1; + + scene->_topicArrowHotspot.show(); + setDelay(1); + } + + scene->_soundHandler.startSound(159); + } + } + + Action::dispatch(); +} + +/*--------------------------------------------------------------------------*/ + +void Scene2120::postInit(SceneObjectList *OwnerList) { + loadScene(2120); + setZoomPercents(0, 100, 200, 100); + _globals->_player.disableControl(); + + _listRect = Rect(18, 48, 260, 177); + _subjectButton.setBounds(Rect(266, 13, 320, 56)); + _nextPageButton.setBounds(Rect(266, 56, 320, 98)); + _previousPageButton.setBounds(Rect(266, 98, 320, 140)); + _exitButton.setBounds(Rect(266, 140, 320, 182)); + + _topicArrowHotspot.postInit(); + _topicArrowHotspot.setVisage(2120); + _topicArrowHotspot.animate(ANIM_MODE_NONE, NULL); + _topicArrowHotspot.setPosition(Common::Point(240, 55)); + + _arrowHotspot.postInit(); + _arrowHotspot.setVisage(2121); + _arrowHotspot.animate(ANIM_MODE_NONE, NULL); + _arrowHotspot._frame = 1; + _arrowHotspot.setPosition(Common::Point(400, 200)); + + _dbMode = 0; + _prevDbMode = 0; + _visageVisable = false; + _subjectIndex = 0; + + setAction(&_action1); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2120::synchronise(Serialiser &s) { + Scene::synchronise(s); + + s.syncAsSint16LE(_dbMode); + s.syncAsSint16LE(_prevDbMode); + s.syncAsSint16LE(_visageVisable); + s.syncAsSint16LE(_subjectIndex); + s.syncAsSint16LE(_lineOffset); +} + +/*-------------------------------------------------------------------------- + * Scene 2150 - Starcraft Level 2 + * + *--------------------------------------------------------------------------*/ + +void Scene2150::Action1::signal() { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(158, 103); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler.startSound(162); + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 2: { + _globals->_player.setStrip2(4); + Common::Point pt(158, 95); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_player.setStrip2(-1); + _globals->_player._strip = 3; + setDelay(10); + break; + case 4: + scene->_area1.display(); + scene->_area2.display(); + scene->_area3.display(); + scene->_area4.display(); + + scene->_area2.draw(true); + _state = 0; + _globals->_events.setCursor(CURSOR_USE); + + while (!_state && !_vm->getEventManager()->shouldQuit()) { + // Wait for an event + Event event; + if (!_globals->_events.getEvent(event)) { + g_system->updateScreen(); + g_system->delayMillis(10); + continue; + } + + if (scene->_area1._bounds.contains(event.mousePos)) { + scene->_area2.draw(false); + scene->_area1.draw(true); + _state = scene->_area1._actionId; + } + if (scene->_area2._bounds.contains(event.mousePos)) { + scene->_area2.draw(true); + _state = scene->_area2._actionId; + } + if (scene->_area3._bounds.contains(event.mousePos)) { + scene->_area2.draw(false); + scene->_area3.draw(true); + _state = scene->_area3._actionId; + } + } + + scene->_soundHandler.startSound(161); + scene->_area1.restore(); + scene->_area2.restore(); + scene->_area3.restore(); + scene->_area4.restore(); + + if (_state == 2150) { + setDelay(1); + } else { + scene->_soundHandler.startSound(162); + scene->_hotspot1.animate(ANIM_MODE_6, this); + } + break; + case 5: + if (_state == 2150) { + Common::Point pt(158, 103); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } else { + _globals->_sceneManager.changeScene(_state); + } + break; + case 6: + scene->_soundHandler.startSound(162); + scene->_hotspot1.animate(ANIM_MODE_6, this); + break; + case 7: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2150::Action2::signal() { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(47, 85); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_player.setVisage(2152); + _globals->_player.setFrame(1); + _globals->_player.setStrip(8); + _globals->_player.animate(ANIM_MODE_8, 1, this); + + scene->_soundHandler.startSound(163); + break; + case 2: + scene->_soundHandler.startSound(164); + scene->_hotspot10.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start((_globals->_inventory._ale._sceneNumber == 2150) ? 2151 : 2152, this); + break; + case 4: + scene->_hotspot14.postInit(); + scene->_hotspot14.setVisage(2152); + scene->_hotspot14.setStrip(6); + scene->_hotspot14.setPosition(Common::Point(59, 54)); + + if (scene->_stripManager._field2E8 == 15) { + scene->_hotspot14.setFrame(5); + _globals->_inventory._ale._sceneNumber = 1; + } else { + scene->_hotspot14.setFrame(scene->_stripManager._field2E8 - 5); + } + + _globals->_player.setFrame(1); + _globals->_player.setStrip(7); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 5: + scene->_soundHandler.startSound(164); + scene->_hotspot10.animate(ANIM_MODE_6, NULL); + scene->_hotspot14.remove(); + + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 6: + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.enableControl(); + + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2150::Hotspot1::doAction(int action) { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2150, 0); + break; + case CURSOR_USE: + scene->setAction(&scene->_action1); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2150::Hotspot2::doAction(int action) { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2150, 1); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 2156; + scene->setAction(&scene->_sequenceManager, scene, 2156, &_globals->_player, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2150::Hotspot4::doAction(int action) { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2150, 3); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 2155; + scene->setAction(&scene->_sequenceManager, scene, 2155, &_globals->_player, &scene->_hotspot4, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2150::Hotspot7::doAction(int action) { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2150, 7); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2150, 19); + else { + _globals->_player.disableControl(); + scene->_sceneMode = 2154; + scene->setAction(&scene->_sequenceManager, scene, 2154, &_globals->_player, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2150::Hotspot10::doAction(int action) { + Scene2150 *scene = (Scene2150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2150, 10); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2150, 19); + else + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene2150::Scene2150() : + _hotspot3(18, CURSOR_LOOK, 2150, 2, CURSOR_USE, 2150, 18, LIST_END), + _hotspot5(17, CURSOR_LOOK, 2150, 4, CURSOR_USE, 2150, 18, LIST_END), + _hotspot6(0, CURSOR_LOOK, 2150, 5, CURSOR_USE, 2150, 18, LIST_END), + _hotspot8(16, CURSOR_LOOK, 2150, 8, LIST_END), + _hotspot9(0, CURSOR_LOOK, 2150, 9, CURSOR_USE, 2150, 13, LIST_END), + _hotspot11(0, CURSOR_LOOK, 2150, 12, LIST_END) { +} + +void Scene2150::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(55, 85, 200, 100); + loadScene(2150); + + _stripManager.addSpeaker(&_speakerGameText); + + _hotspot7.postInit(); + _hotspot7.setVisage(2152); + _hotspot7._frame = 1; + _hotspot7._strip = 2; + _hotspot7.animate(ANIM_MODE_8, NULL); + _hotspot7.setPosition(Common::Point(122, 62)); + _hotspot7.changeZoom(100); + _hotspot7.setPriority2(76); + + _hotspot2.postInit(); + _hotspot2.setVisage(2151); + _hotspot2._frame = 1; + _hotspot2._strip = 3; + _hotspot2.animate(ANIM_MODE_NONE, NULL); + _hotspot2.setPosition(Common::Point(257, 67)); + _hotspot2.changeZoom(100); + _hotspot2.setPriority2(60); + + _hotspot1.postInit(); + _hotspot1.setVisage(2151); + _hotspot1._frame = 1; + _hotspot1._strip = 2; + _hotspot1.animate(ANIM_MODE_NONE, NULL); + _hotspot1.setPosition(Common::Point(158, 99)); + _hotspot1.changeZoom(100); + _hotspot1.setPriority2(99); + + _hotspot4.postInit(); + _hotspot4.setVisage(2150); + _hotspot4._frame = 1; + _hotspot4._strip = 2; + _hotspot4.animate(ANIM_MODE_NONE, NULL); + _hotspot4.setPosition(Common::Point(218, 200)); + _hotspot4.changeZoom(100); + _hotspot4.setPriority2(200); + + _hotspot10.postInit(); + _hotspot10.setVisage(2152); + _hotspot10.setStrip(5); + _hotspot10.setPosition(Common::Point(59, 56)); + + _rect1 = Rect(260, 70, 270, 77); + _rect2 = Rect(222, 142, 252, 150); + + _globals->_player.postInit(); + _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPriority2(-1); + _globals->_player.changeZoom(-1); + _globals->_player._moveDiff.y = 3; + + _hotspot8.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot9.setBounds(Rect(133, 0, 198, 91)); + _hotspot11.setBounds(Rect(142, 119, 176, 158)); + + _globals->_sceneItems.addItems(&_hotspot1, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, + &_hotspot6, &_hotspot7, &_hotspot10, &_hotspot9, &_hotspot11, &_hotspot8, NULL); + + _area1.setup(2153, 2, 1, 2100); + _area1._pt = Common::Point(200, 31); + _area2.setup(2153, 3, 1, 2150); + _area2._pt = Common::Point(200, 50); + _area3.setup(2153, 4, 1, 2320); + _area3._pt = Common::Point(200, 75); + _area4.setup(2153, 1, 1, 10); + _area4._pt = Common::Point(237, 77); + + switch (_globals->_sceneManager._previousScene) { + case 2120: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _globals->_player.setPosition(Common::Point(108, 99)); + break; + case 2200: + _globals->_player.disableControl(); + _globals->_player.setPosition(Common::Point(159, 240)); + _sceneMode = 2152; + setAction(&_sequenceManager, this, 2152, &_globals->_player, NULL); + break; + case 2280: + _globals->_player.disableControl(); + _globals->_player._angle = 180; + _globals->_player.setPosition(Common::Point(265, 80)); + + _hotspot2._frame = _hotspot2.getFrameCount(); + _sceneMode = 2157; + setAction(&_sequenceManager, this, 2157, &_hotspot2, NULL); + break; + case 2230: + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player._strip = 4; + _globals->_player.setPosition(Common::Point(229, 139)); + break; + case 2100: + default: + _globals->_player.disableControl(); + _globals->_player.setPosition(Common::Point(158, 95)); + _globals->_player.setStrip(3); + _sceneMode = 2151; + + setAction(&_sequenceManager, this, 2151, &_globals->_player, &_hotspot1, NULL); + break; + } + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2150::synchronise(Serialiser &s) { + Scene::synchronise(s); + _rect1.synchronise(s); + _rect2.synchronise(s); +} + +void Scene2150::signal() { + switch (_sceneMode) { + case 2151: + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.enableControl(); + break; + case 2152: + case 2153: + case 2157: + _globals->_player.enableControl(); + break; + case 2154: + _globals->_sceneManager.changeScene(2120); + break; + case 2155: + _globals->_sceneManager.changeScene(2230); + break; + case 2156: + _globals->_sceneManager.changeScene(2280); + break; + } +} + +void Scene2150::dispatch() { + Scene::dispatch(); + + if (!_action) { + if (_rect1.contains(_globals->_player._position)) { + _globals->_player.disableControl(); + _sceneMode = 2156; + setAction(&_sequenceManager, this, 2156, &_globals->_player, &_hotspot2, NULL); + } + if (_rect2.contains(_globals->_player._position)) { + _globals->_player.disableControl(); + _sceneMode = 2155; + setAction(&_sequenceManager, this, 2155, &_globals->_player, &_hotspot4, NULL); + } + if (_globals->_player._position.y >= 196) { + _globals->_player.disableControl(); + SceneItem::display2(2150, 20); + + _sceneMode = 2153; + setAction(&_sequenceManager, this, 2153, &_globals->_player, NULL); + } + } +} + +/*-------------------------------------------------------------------------- + * Scene 2200 - Starcraft - AutoDoc + * + *--------------------------------------------------------------------------*/ + +void Scene2200::Action1::signal() { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(6); + break; + case 1: + scene->_hotspot4.animate(ANIM_MODE_5, this); + break; + case 2: + SceneItem::display2(2200, 7); + _globals->_sceneManager.changeScene(2150); + remove(); + break; + } +} + +void Scene2200::Action2::signal() { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + setDelay(30); + break; + case 2: + scene->_hotspot4.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_hotspot4.setStrip(4); + setDelay(30); + break; + case 4: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(2040, this, scene); + break; + case 5: + scene->_hotspot4.setStrip(4); + scene->_hotspot4.animate(ANIM_MODE_NONE, NULL); + _globals->_player._uiEnabled = true; + remove(); + break; + } +} + +void Scene2200::Action3::signal() { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_soundHandler2.startSound(103); + + scene->_hotspot4.setStrip(4); + scene->_hotspot4.animate(ANIM_MODE_NONE, NULL); + _globals->_player.disableControl(); + + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(2201); + scene->_hotspot2._strip = 2; + scene->_hotspot2.setPosition(Common::Point(218, 0)); + + Common::Point pt(218, 63); + NpcMover *mover = new NpcMover(); + scene->_hotspot2.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler2.startSound(104); + scene->_hotspot4.setStrip(2); + scene->_hotspot4.setFrame(2); + setDelay(120); + break; + case 2: + if (_globals->getFlag(83)) { + _actionIndex = 8; + setDelay(5); + } else { + for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin(); + i != _globals->_sceneObjects->end(); ++i) { + (*i)->hide(); + } + + _globals->_sceneManager._scene->loadScene(66); + + scene->_hotspot6.postInit(); + scene->_hotspot6.setVisage(66); + scene->_hotspot6.setPosition(Common::Point(160, 197)); + + scene->_hotspot7.postInit(); + scene->_hotspot7.setVisage(65); + scene->_hotspot7.setStrip(4); + scene->_hotspot7.setFrame(1); + scene->_hotspot7.setPosition(Common::Point(145, 165)); + + SceneItem::display(60, 1, SET_Y, 40, SET_X, 25, SET_FONT, 75, SET_BG_COLOUR, -1, SET_FG_COLOUR, 34, + SET_POS_MODE, 0, SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END); + _state = 1; + setDelay(1800); + } + break; + case 3: + case 4: + case 5: + SceneItem::display(60, _actionIndex - 2, SET_Y, 40, SET_X, 25, SET_FONT, 75, SET_BG_COLOUR, -1, SET_FG_COLOUR, 34, + SET_POS_MODE, 0, SET_WIDTH, 280, SET_KEEP_ONSCREEN, 1, LIST_END); + setDelay(1800); + break; + case 6: + scene->_hotspot7.remove(); + SceneItem::display(0, 0); + _state = 0; + setDelay(5); + break; + case 7: + for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneObjects->begin(); + i != _globals->_sceneObjects->end(); ++i) + (*i)->show(); + + scene->_hotspot6.remove(); + _globals->_sceneManager._scene->loadScene(2200); + setDelay(5); + break; + case 8: + scene->_stripManager.start(2060, this, scene); + break; + case 9: + scene->_hotspot4.setStrip(4); + scene->_hotspot4.animate(ANIM_MODE_NONE, NULL); + break; + case 10: + _globals->_sceneManager.changeScene(2000); + remove(); + break; + } +} + +void Scene2200::Action3::process(Event &event) { + if (!event.handled && ((event.eventType == EVENT_KEYPRESS) || (event.eventType == EVENT_BUTTON_DOWN))) { + _state = 0; + event.handled = true; + setDelay(1); + } + + Action::process(event); +} + +void Scene2200::Action4::signal() { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + scene->_stripManager.start(2202, this, scene); + break; + case 2: + scene->_hotspot4.setStrip(4); + scene->_hotspot4.animate(ANIM_MODE_NONE, NULL); + setDelay(10); + break; + case 3: + _globals->_player._uiEnabled = true; + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2200::Hotspot3::doAction(int action) { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2200, 10); + break; + case CURSOR_USE: + SceneItem::display2(2200, 11); + break; + case CURSOR_TALK: + _globals->_player._uiEnabled = false; + scene->setAction(&scene->_action4); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2200::Hotspot5::doAction(int action) { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2200, 8); + break; + case CURSOR_USE: + SceneItem::display2(2200, 9); + break; + case CURSOR_TALK: + scene->_sceneMode = 2201; + _globals->_player._uiEnabled = false; + scene->setAction(&scene->_sequenceManager, scene, 2201, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2200::Hotspot9::doAction(int action) { + Scene2200 *scene = (Scene2200 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2200, _globals->getFlag(8) ? 1 : 0); + break; + case CURSOR_USE: + SceneItem::display2(2200, 3); + break; + case OBJECT_INFODISK: + if (_globals->_sceneManager._previousScene == 2310) { + scene->_soundHandler2.startSound(35); + _globals->_player.disableControl(); + scene->setAction(&scene->_action3); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + + +Scene2200::Scene2200() : + _hotspot1(0, CURSOR_LOOK, 2200, 5, CURSOR_USE, 2200, 6, LIST_END), + _hotspot10(0, CURSOR_LOOK, 2200, 4, LIST_END) { +} + +void Scene2200::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 200, 200, 200); + loadScene(2200); + + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerMR); + _stripManager.addSpeaker(&_speakerGameText); + + _speakerQText._npc = &_globals->_player; + _speakerSText._npc = &_hotspot5; + _speakerMText._npc = &_hotspot3; + + _stripManager.setCallback(this); + + _hotspot5.postInit(); + _hotspot5.setVisage(2840); + _hotspot5.setPosition(Common::Point(50, 235)); + + _hotspot8.postInit(); + _hotspot8.setVisage(2840); + _hotspot8.setStrip(2); + _hotspot8.setPosition(Common::Point(96, 184)); + _hotspot8.setPriority2(236); + + _globals->_player.postInit(); + _globals->_player.setVisage(2640); + _globals->_player.setFrame2(3); + _globals->_player.setPosition(Common::Point(110, 233)); + _globals->_player.disableControl(); + + switch (_globals->_sceneManager._previousScene) { + case 2150: + _hotspot5.remove(); + _hotspot8.remove(); + break; + case 4000: + _globals->_soundHandler.startSound(100); + _globals->_soundHandler.proc5(true); + _globals->_player.remove(); + _hotspot5.remove(); + _hotspot8.remove(); + + _hotspot1.postInit(); + _hotspot1.setVisage(2202); + _hotspot1.setPosition(Common::Point(175, 173)); + _hotspot1.setPriority2(99); + + _hotspot3.postInit(); + _hotspot3.setVisage(2202); + _hotspot3._strip = 2; + _hotspot3.setPosition(Common::Point(152, 76)); + _hotspot3.setPriority2(100); + + _hotspot4.postInit(); + _hotspot4.setVisage(2202); + _hotspot4._strip = 3; + _hotspot4.setPosition(Common::Point(115, 76)); + _hotspot4.setPriority2(200); + + setAction(&_action1); + break; + case 2310: + default: + _globals->_inventory._infoDisk._sceneNumber = 1; + + _hotspot3.postInit(); + _hotspot3.setVisage(2215); + _hotspot3.setPosition(Common::Point(144, 132)); + _globals->_sceneItems.push_back(&_hotspot3); + + _hotspot4.postInit(); + _hotspot4.setVisage(2215); + _hotspot4._strip = 2; + _hotspot4.setPosition(Common::Point(120, 78)); + _hotspot4.setPriority2(255); + _globals->_sceneItems.push_back(&_hotspot4); + + _soundHandler1.startSound(101); + _soundHandler2.startSound(100); + _globals->_soundHandler.proc5(true); + + _globals->_sceneItems.push_back(&_hotspot5); + setAction(&_action2); + break; + } + + _exitRect = Rect(0, 0, 35, SCREEN_HEIGHT); + _hotspot9.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot10.setBounds(Rect(87, 43, 149, 109)); + + _globals->_sceneItems.addItems(&_hotspot10, &_hotspot9, NULL); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2200::stripCallback(int v) { + switch (v) { + case 1: + _hotspot4.setStrip(3); + _hotspot4.animate(ANIM_MODE_7, 0, NULL); + break; + case 2: + _hotspot4.setStrip(4); + _hotspot4.animate(ANIM_MODE_NONE, NULL); + break; + } +} + +void Scene2200::synchronise(Serialiser &s) { + Scene::synchronise(s); + _exitRect.synchronise(s); +} + +void Scene2200::signal() { + if ((_sceneMode == 2201) || (_sceneMode == 2202)) + _globals->_player._uiEnabled = true; +} + +void Scene2200::dispatch() { + Scene::dispatch(); + + if (!_action) { + if (_exitRect.contains(_globals->_player._position)) + _globals->_sceneManager.changeScene(2150); + } +} + +/*-------------------------------------------------------------------------- + * Scene 2222 - Stasis Field Map + * + *--------------------------------------------------------------------------*/ + +void Scene2222::Action1::signal() { + Scene2222 *scene = (Scene2222 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + scene->_stripManager.start(2222, this); + break; + case 2: + setDelay(30); + break; + case 3: + _globals->_sceneManager.changeScene(1000); + break; + } +} + +void Scene2222::Action2::signal() { + Scene2222 *scene = (Scene2222 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + scene->_stripManager.start(5700, this); + break; + case 2: + setDelay(120); + break; + case 3: + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_sceneManager.changeScene(2100); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2222::postInit(SceneObjectList *OwnerList) { + loadScene((_globals->_sceneManager._previousScene == 2000) ? 3400 : 3450); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerML); + + _hotspot1.postInit(); + _hotspot1.setVisage(3401); + _hotspot1.setStrip2(1); + _hotspot1._frame = 1; + _hotspot1.animate(ANIM_MODE_2, 0); + + _hotspot2.postInit(); + _hotspot2.setVisage(3401); + _hotspot2.setStrip2(2); + _hotspot2._frame = 2; + _hotspot2.animate(ANIM_MODE_2, 0); + + _hotspot3.postInit(); + _hotspot3.setVisage(3401); + _hotspot3.setStrip2(2); + _hotspot3._frame = 3; + _hotspot3.animate(ANIM_MODE_2, 0); + + _hotspot4.postInit(); + _hotspot4.setVisage(3401); + _hotspot4.setStrip2(2); + _hotspot4._frame = 4; + _hotspot4.animate(ANIM_MODE_2, 0); + + _hotspot5.postInit(); + _hotspot5.setVisage(3401); + _hotspot5.setStrip2(2); + _hotspot5._frame = 5; + _hotspot5.animate(ANIM_MODE_2, 0); + + if (_globals->_sceneManager._previousScene == 2100) { + _hotspot1.setPosition(Common::Point(61, 101)); + _hotspot2.setPosition(Common::Point(239, 149)); + _hotspot3.setPosition(Common::Point(184, 85)); + _hotspot4.setPosition(Common::Point(105, 165)); + _hotspot5.remove(); + + setAction(&_action2); + } else { + _hotspot1.setPosition(Common::Point(110, 108)); + _hotspot2.setPosition(Common::Point(175, 136)); + _hotspot3.setPosition(Common::Point(162, 96)); + _hotspot4.setPosition(Common::Point(118, 141)); + _hotspot5.setPosition(Common::Point(124, 107)); + + setAction(&_action1); + } + + _soundHandler.startSound(116); + _globals->_sceneManager._scene->_sceneBounds.centre(_hotspot1._position); + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + + +/*-------------------------------------------------------------------------- + * Scene 2230 - Starcraft - Quinn's Room + * + *--------------------------------------------------------------------------*/ + +void Scene2230::Action1::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + switch (scene->_field30A) { + case 1: + scene->setAction(&scene->_action3); + break; + case 2: + scene->setAction(&scene->_action6); + break; + default: + setDelay(10); + break; + } + break; + case 1: { + Common::Point pt(84, 74); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 3: { + Common::Point pt(63, 60); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 4: + scene->_hotspot1.animate(ANIM_MODE_6, this); + break; + case 5: + _globals->_sceneManager.changeScene(2150); + break; + } +} + +void Scene2230::Action2::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + switch (scene->_field30A) { + case 2: + scene->setAction(&scene->_action6, this); + break; + default: + setDelay(10); + break; + } + break; + case 1: { + _globals->_player.disableControl(); + scene->_field30A = 1; + _globals->_player._regionBitList |= ~0x80; + Common::Point pt(160, 96); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_player.setVisage(2235); + _globals->_player.setStrip2(1); + _globals->_player.setPriority2(100); + _globals->_player._frame = 1; + _globals->_player.setPosition(Common::Point(200, 68)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_soundHandler.startSound(157); + _globals->_player._moveDiff = Common::Point(1, 1); + _globals->_player.setAction(&scene->_action4); + _globals->_player._uiEnabled = true; + + _globals->_events.setCursor(CURSOR_USE); + remove(); + break; + } +} + +void Scene2230::Action3::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.setAction(NULL); + _globals->_player._moveDiff = Common::Point(5, 3); + _globals->_player.setStrip2(_globals->_player._strip); + + Common::Point pt(190, 74); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + + scene->_soundHandler.proc3(); + break; + } + case 1: + _globals->_player._strip = 3; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player._regionBitList |= 0x80; + scene->_field30A = 0; + + _globals->_player.setVisage(0); + _globals->_player.setStrip2(-1); + _globals->_player.setPriority2(-1); + _globals->_player.setPosition(Common::Point(164, 96)); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._canWalk = true; + + _globals->_events.setCursor(CURSOR_USE); + remove(); + } +} + +void Scene2230::Action4::signal() { + switch (_actionIndex++) { + case 0: + Common::Point pt(190 + _globals->_randomSource.getRandomNumber(9), 68); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + _actionIndex = 0; + break; + } +} + +void Scene2230::Action5::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + switch (scene->_field30A) { + case 2: + scene->setAction(&scene->_action3, this); + break; + default: + setDelay(10); + break; + } + break; + case 1: { + _globals->_player.disableControl(); + Common::Point pt(209, 124); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_player.setPriority2(1430); + _globals->_player.setVisage(2232); + _globals->_player._strip = 1; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_events.setCursor(CURSOR_USE); + _globals->_player._uiEnabled = true; + scene->_field30A = 2; + remove(); + break; + } +} + +void Scene2230::Action6::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player._strip = 2; + _globals->_player._frame = 1; + _globals->_player.setPriority2(-1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 1: + scene->_field30A = 0; + _globals->_player.setVisage(0); + _globals->_player._strip = 1; + _globals->_player._canWalk = true; + _globals->_player.animate(ANIM_MODE_1, NULL); + remove(); + break; + } +} + +void Scene2230::Action7::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + + switch (scene->_field30A) { + case 1: + scene->setAction(&scene->_action3, this); + break; + case 2: + scene->setAction(&scene->_action6, this); + break; + default: + setDelay(10); + break; + } + break; + case 1: { + Common::Point pt(140, 119); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_soundHandler.startSound(158); + scene->_hotspot8.setStrip2(2); + + Common::Point pt(scene->_hotspot8._position.x, 97); + NpcMover *mover = new NpcMover(); + scene->_hotspot8.addMover(mover, &pt, this); + break; + } + case 3: + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(2231); + scene->_hotspot2._strip = 3; + scene->_hotspot2.setPosition(Common::Point(166, 116)); + scene->_hotspot2.setPriority2(131); + scene->_hotspot2.animate(ANIM_MODE_5, this); + + scene->_hotspot8._frame = 2; + break; + case 4: + _globals->_sceneItems.push_front(&scene->_hotspot10); + _globals->_sceneItems.push_front(&scene->_hotspot11); + _globals->_sceneItems.push_front(&scene->_hotspot12); + + scene->_hotspot2.remove(); + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2230::Action8::signal() { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + + switch (scene->_field30A) { + case 1: + scene->setAction(&scene->_action3, this); + break; + case 2: + scene->setAction(&scene->_action6, this); + break; + default: + setDelay(10); + break; + } + break; + case 1: { + Common::Point pt(140, 119); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: { + _globals->_sceneItems.remove(&scene->_hotspot10); + _globals->_sceneItems.remove(&scene->_hotspot11); + _globals->_sceneItems.remove(&scene->_hotspot12); + + switch (scene->_field30A) { + case 1: + scene->setAction(&scene->_action3, this); + break; + case 2: + scene->setAction(&scene->_action6, this); + break; + default: + setDelay(10); + break; + } + break; + } + case 3: + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(2231); + scene->_hotspot2._strip = 3; + scene->_hotspot2._frame = scene->_hotspot2.getFrameCount(); + scene->_hotspot2.setPosition(Common::Point(166, 116)); + scene->_hotspot2.setPriority2(131); + scene->_hotspot2.animate(ANIM_MODE_6, this); + break; + case 4: { + scene->_soundHandler.startSound(158); + scene->_hotspot2.remove(); + scene->_hotspot8._frame = 1; + + Common::Point pt(scene->_hotspot8._position.x, 133); + NpcMover *mover = new NpcMover(); + scene->_hotspot8.addMover(mover, &pt, this); + break; + } + case 5: + scene->_hotspot8.setStrip2(1); + _globals->_player.enableControl(); + + remove(); + break; + } +} + + +/*--------------------------------------------------------------------------*/ + +void Scene2230::Hotspot1::doAction(int action) { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2230, 0); + break; + case CURSOR_USE: + scene->setAction(&scene->_action1); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot3::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(4)) + SceneItem::display2(2230, 1); + else { + SceneItem::display2(2230, 1); + SceneItem::display2(2230, 2); + SceneItem::display2(2230, 3); + _globals->setFlag(4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot4::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(30)) + SceneItem::display2(2230, 6); + else if (_globals->getFlag(29)) { + SceneItem::display2(2230, 5); + _globals->setFlag(30); + } else { + SceneItem::display2(2230, 4); + _globals->setFlag(29); + } + break; + case CURSOR_USE: + SceneItem::display2(2230, 7); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot5::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(5)) + SceneItem::display2(2230, 9); + else { + _globals->setFlag(5); + SceneItem::display2(2230, 8); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot6::doAction(int action) { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(6)) + SceneItem::display2(2230, 11); + else { + _globals->setFlag(6); + SceneItem::display2(2230, 10); + } + break; + case CURSOR_USE: + if (scene->_field30A == 1) + scene->setAction(&scene->_action3); + else if (_globals->getFlag(13)) + SceneItem::display2(2230, 28); + else + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot7::doAction(int action) { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(7)) + SceneItem::display2(2230, 13); + else { + _globals->setFlag(6); + SceneItem::display2(2230, 12); + } + break; + case CURSOR_USE: + if (scene->_field30A == 2) + scene->setAction(&scene->_action6); + else if (_globals->getFlag(13)) + SceneItem::display2(2230, 29); + else + scene->setAction(&scene->_action5); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot8::doAction(int action) { + Scene2230 *scene = (Scene2230 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (scene->_hotspot8._strip == 1) { + if (_globals->getFlag(22)) + SceneItem::display2(2230, 19); + else { + _globals->setFlag(22); + SceneItem::display2(2230, 14); + } + } else { + if (_globals->getFlag(25)) + SceneItem::display2(2230, 21); + else { + _globals->setFlag(25); + SceneItem::display2(2230, 20); + } + } + break; + case CURSOR_USE: + if (scene->_hotspot8._strip == 1) + scene->setAction(&scene->_action7); + else + scene->setAction(&scene->_action8); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot10::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(26)) + SceneItem::display2(2230, 25); + else { + _globals->setFlag(26); + SceneItem::display2(2230, 24); + } + break; + case CURSOR_USE: + SceneItem::display2(2230, 28); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot11::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(27)) + SceneItem::display2(2230, 23); + else { + _globals->setFlag(27); + SceneItem::display2(2230, 22); + } + break; + case CURSOR_USE: + SceneItem::display2(2230, 28); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2230::Hotspot12::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(28)) + SceneItem::display2(2230, 27); + else { + _globals->setFlag(28); + SceneItem::display2(2230, 26); + } + break; + case CURSOR_USE: + SceneItem::display2(2230, 28); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene2230::Scene2230() : + _hotspot9(0, CURSOR_LOOK, 2230, 16, CURSOR_USE, 2230, 18, LIST_END) { +} + +void Scene2230::postInit(SceneObjectList *OwnerList) { + loadScene(2230); + Scene::postInit(); + setZoomPercents(75, 80, 120, 100); + + _hotspot1.postInit(); + _hotspot1.setVisage(2230); + _hotspot1._frame = 1; + _hotspot1.animate(ANIM_MODE_NONE, 0); + _hotspot1.setPosition(Common::Point(72, 69)); + _hotspot1.changeZoom(100); + + _hotspot8.postInit(); + _hotspot8.setVisage(2231); + _hotspot8._frame = 1; + _hotspot8.animate(ANIM_MODE_NONE, 0); + _hotspot8.setPosition(Common::Point(164, 133)); + _hotspot8.changeZoom(100); + _hotspot8.setPriority2(129); + + _rect1 = Rect(59, 64, 89, 74); + + _globals->_player.postInit(); + _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0); + _globals->_player.animate(ANIM_MODE_1, 0); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(80, 80)); + _globals->_player._moveDiff.y = 3; + _globals->_player._regionBitList |= 0x80; + _globals->_player.changeZoom(-1); + + _field30A = 0; + _globals->_player.enableControl(); + + _hotspot5.setBounds(Rect(108, 34, 142, 76)); + _hotspot4.setBounds(Rect(92, 14, 106, 57)); + _hotspot6.setBounds(Rect(169, 58, 261, 95)); + _hotspot7.setBounds(Rect(111, 117, 222, 158)); + _hotspot3.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot10.setBounds(Rect(170, 96, 176, 106)); + _hotspot11.setBounds(Rect(158, 109, 164, 115)); + _hotspot12.setBounds(Rect(170, 109, 177, 115)); + + _globals->_sceneItems.addItems(&_hotspot8, &_hotspot5, &_hotspot4, &_hotspot6, &_hotspot7, + &_hotspot1, &_hotspot3, NULL); + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2230::synchronise(Serialiser &s) { + Scene::synchronise(s); + _rect1.synchronise(s); + s.syncAsSint16LE(_field30A); +} + +void Scene2230::dispatch() { + Scene::dispatch(); + + if (!_action) { + if (_rect1.contains(_globals->_player._position)) + setAction(&_action1); + } +} + +/*-------------------------------------------------------------------------- + * Scene 2280 - Starcraft - Storage Room + * + *--------------------------------------------------------------------------*/ + +void Scene2280::Action1::signal() { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(192, 97); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler.startSound(162); + scene->_hotspot16.animate(ANIM_MODE_5, this); + break; + case 2: { + Common::Point pt(218, 87); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_player.setStrip(3); + setDelay(10); + break; + case 4: + _globals->_player.setPriority2(1); + scene->_soundHandler.startSound(162); + scene->_hotspot16.animate(ANIM_MODE_6, this); + break; + case 5: + _globals->_sceneManager.changeScene(7000); + break; + } +} + +void Scene2280::Action2::signal() { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(94, 117); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler.startSound(265); + + _globals->_player.setVisage(2162); + _globals->_player._frame = 1; + _globals->_player._strip = 1; + _globals->_player.animate(ANIM_MODE_5, this); + + scene->_hotspot8.remove(); + scene->_hotspot10.remove(); + break; + case 2: + _globals->_player._frame = 1; + _globals->_player._strip = 2; + _globals->_player.animate(ANIM_MODE_4, 3, 1, this); + break; + case 3: + _globals->_player.animate(ANIM_MODE_5, this); + scene->_hotspot12.remove(); + break; + case 4: + scene->_soundHandler.startSound(266); + _globals->_player.setVisage(2170); + _globals->_player._frame = 1; + _globals->_player._strip = 4; + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._moveDiff = Common::Point(4, 1); + + _globals->setFlag(13); + SceneItem::display2(2280, 37); + + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2280::Action3::signal() { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + Common::Point pt(94, 117); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler.startSound(265); + + _globals->_player.setVisage(2162); + _globals->_player._frame = 6; + _globals->_player._strip = 2; + _globals->_player.animate(ANIM_MODE_4, 3, -1, this); + break; + case 2: + scene->_hotspot12.postInit(); + scene->_hotspot12.setVisage(2280); + scene->_hotspot12._strip = 2; + scene->_hotspot12._frame = 3; + scene->_hotspot12.setPosition(Common::Point(88, 76)); + scene->_hotspot12.setPriority2(1); + + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player._strip = 1; + _globals->_player._frame = 12; + + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 4: + scene->_hotspot8.postInit(); + scene->_hotspot8.setVisage(2280); + scene->_hotspot8._strip = 2; + scene->_hotspot8._frame = 1; + scene->_hotspot8.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot8.setPosition(Common::Point(79, 108)); + scene->_hotspot8.changeZoom(100); + scene->_hotspot8.setPriority2(1); + + scene->_hotspot10.postInit(); + scene->_hotspot10.setVisage(2280); + scene->_hotspot10._strip = 2; + scene->_hotspot10._frame = 2; + scene->_hotspot10.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot10.setPosition(Common::Point(79, 104)); + scene->_hotspot10.changeZoom(100); + scene->_hotspot10.setPriority2(1); + + _globals->clearFlag(13); + + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._strip = 4; + _globals->_player._moveDiff = Common::Point(3, 5); + + SceneItem::display2(2280, 38); + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2280::Action4::signal() { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + switch (_state) { + case 1: + case 51: { + Common::Point pt(163, 67); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: + case 50: { + Common::Point pt(173, 63); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + } + break; + } + case 1: + _globals->_player.setVisage(2161); + _globals->_player._strip = 1; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + switch (_state) { + case 1: + scene->_hotspot18.remove(); + _globals->_inventory._scanner._sceneNumber = 1; + break; + case 6: + scene->_hotspot17.remove(); + _globals->_inventory._medkit._sceneNumber = 1; + break; + case 50: + scene->_hotspot17.postInit(); + scene->_hotspot17.setVisage(2161); + scene->_hotspot17._strip = 2; + scene->_hotspot17._frame = 1; + scene->_hotspot17.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot17.setPosition(Common::Point(162, 39)); + scene->_hotspot17.changeZoom(100); + scene->_hotspot17.setPriority2(1); + + _globals->_inventory._medkit._sceneNumber = 2280; + _globals->_sceneItems.push_front(&scene->_hotspot17); + break; + case 51: + scene->_hotspot18.postInit(); + scene->_hotspot18.setVisage(2161); + scene->_hotspot18._strip = 2; + scene->_hotspot18._frame = 2; + scene->_hotspot18.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot18.setPosition(Common::Point(152, 43)); + scene->_hotspot18.changeZoom(100); + scene->_hotspot18.setPriority2(1); + + _globals->_inventory._scanner._sceneNumber = 2280; + _globals->_sceneItems.push_front(&scene->_hotspot18); + break; + } + + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player.enableControl(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._strip = 2; + + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2280::Hotspot1::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(16)) + SceneItem::display2(2280, 22); + else { + _globals->setFlag(16); + SceneItem::display2(2230, 21); + } + break; + case CURSOR_USE: + if (!_globals->getFlag(15)) + SceneItem::display2(2280, 23); + else if (!_globals->getFlag(13)) + SceneItem::display2(2280, 46); + else { + _globals->_player.disableControl(); + scene->setAction(&scene->_action1); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot2::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(2)) + SceneItem::display2(2280, 1); + else { + _globals->setFlag(2); + SceneItem::display2(2280, 0); + } + break; + case CURSOR_USE: + SceneItem::display2(2280, 2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot4::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(21)) + SceneItem::display2(2280, 33); + else { + _globals->setFlag(21); + SceneItem::display2(2280, 32); + } + break; + case CURSOR_USE: + SceneItem::display2(2280, 34); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot7::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2280, 24); + break; + case OBJECT_SCANNER: + if (_globals->getFlag(13)) + SceneItem::display2(2280, 43); + else { + _globals->_player.disableControl(); + scene->_action4._state = 51; + _globals->_events.setCursor(CURSOR_WALK); + _globals->_events._currentCursor = CURSOR_700; + scene->setAction(&scene->_action4); + } + break; + case OBJECT_MEDKIT: + if (_globals->getFlag(13)) + SceneItem::display2(2280, 43); + else { + _globals->_player.disableControl(); + scene->_action4._state = 50; + _globals->_events.setCursor(CURSOR_WALK); + _globals->_events._currentCursor = CURSOR_700; + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot8::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2280, 3); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot10::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2280, 4); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot12::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2280, 11); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot14::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2280, 3); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + if (_globals->getFlag(13)) + scene->setAction(&scene->_action3); + else + scene->setAction(&scene->_action2); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot17::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(18)) + SceneItem::display2(2280, 26); + else { + _globals->setFlag(18); + SceneItem::display2(2280, 25); + } + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2280, 29); + else { + _globals->_player.disableControl(); + scene->_action4._state = 6; + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2280::Hotspot18::doAction(int action) { + Scene2280 *scene = (Scene2280 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(19)) + SceneItem::display2(2280, 28); + else { + _globals->setFlag(19); + SceneItem::display2(2280, 27); + } + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2280, 29); + else { + _globals->_player.disableControl(); + scene->_action4._state = 1; + scene->setAction(&scene->_action4); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene2280::Scene2280() : + _hotspot3(0, CURSOR_LOOK, 2280, 30, CURSOR_USE, 31, 0, LIST_END), + _hotspot5(0, CURSOR_LOOK, 2280, 35, CURSOR_USE, 2280, 36, LIST_END), + _hotspot6(0, CURSOR_LOOK, 2280, 19, CURSOR_USE, 2280, 20, LIST_END), + _hotspot9(0, CURSOR_LOOK, 2280, 5, CURSOR_USE, 2280, 6, LIST_END), + _hotspot11(0, CURSOR_LOOK, 2280, 7, CURSOR_USE, 2280, 8, LIST_END), + _hotspot13(0, CURSOR_LOOK, 2280, 9, CURSOR_USE, 2280, 10, LIST_END), + _hotspot15(0, CURSOR_LOOK, 2280, 45, LIST_END), + _hotspot16(0, CURSOR_LOOK, 2280, 16, CURSOR_USE, 2280, 42, LIST_END) { +} + +void Scene2280::postInit(SceneObjectList *OwnerList) { + loadScene(2280); + Scene::postInit(); + setZoomPercents(0, 70, 200, 100); + + _hotspot16.postInit(); + _hotspot16.setVisage(2281); + _hotspot16.setPosition(Common::Point(208, 90)); + _hotspot16.setPriority2(80); + + if (_globals->_inventory._medkit._sceneNumber == 2280) { + _hotspot17.postInit(); + _hotspot17.setVisage(2161); + _hotspot17._strip = 2; + _hotspot17.setPosition(Common::Point(162, 39)); + _hotspot17.setPriority2(1); + + _globals->_sceneItems.push_back(&_hotspot17); + } + + if (_globals->_inventory._scanner._sceneNumber == 2280) { + _hotspot18.postInit(); + _hotspot18.setVisage(2161); + _hotspot18._strip = 2; + _hotspot18._frame = 2; + _hotspot17.setPosition(Common::Point(152, 43)); + _hotspot17.setPriority2(1); + + _globals->_sceneItems.push_back(&_hotspot17); + } + + if (!_globals->getFlag(13)) { + _hotspot8.postInit(); + _hotspot8.setVisage(2280); + _hotspot8._strip = 2; + _hotspot8.setPosition(Common::Point(79, 108)); + _hotspot8.setPriority2(1); + + _hotspot10.postInit(); + _hotspot10.setVisage(2280); + _hotspot10._strip = 2; + _hotspot10._frame = 2; + _hotspot10.setPosition(Common::Point(79, 104)); + _hotspot10.setPriority2(2); + + _hotspot12.postInit(); + _hotspot12.setVisage(2280); + _hotspot12._strip = 2; + _hotspot12._frame = 3; + _hotspot12.setPosition(Common::Point(88, 76)); + _hotspot12.setPriority2(1); + + _globals->_sceneItems.addItems(&_hotspot8, &_hotspot10, &_hotspot12, NULL); + } + + _hotspot14.setBounds(Rect(70, 50, 90, 104)); + + _hotspot9.postInit(); + _hotspot9.setVisage(2280); + _hotspot9.setPosition(Common::Point(104, 96)); + _hotspot9.setPriority2(1); + + _hotspot11.postInit(); + _hotspot11.setVisage(2280); + _hotspot11._frame = 2; + _hotspot11.setPosition(Common::Point(130, 79)); + _hotspot11.setPriority2(1); + + _hotspot13.postInit(); + _hotspot13.setVisage(2280); + _hotspot13._frame = 3; + _hotspot13.setPosition(Common::Point(113, 63)); + _hotspot13.setPriority2(1); + + _hotspot1.setBounds(Rect(225, 70, 234, 80)); + _hotspot2.setBounds(Rect(44, 78, 56, 105)); + _hotspot3.setBounds(Rect(47, 108, 56, 117)); + _hotspot4.setBounds(Rect(56, 78, 69, 101)); + _hotspot5.setBounds(Rect(56, 108, 66, 113)); + _hotspot6.setBounds(Rect(261, 39, 276, 90)); + _hotspot7.setBounds(Rect(142, 19, 174, 38)); + _hotspot15.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + + _exitRect = Rect(145, 180, 195, 195); + + _globals->_player.postInit(); + _globals->_player.setVisage(_globals->getFlag(13) ? 2170 : 0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(146, 161)); + _globals->_player.changeZoom(-1); + _globals->_player._moveDiff = Common::Point(4, 3); + + if ((_globals->_sceneManager._previousScene != 7300) && (_globals->_sceneManager._previousScene != 7000)) { + _globals->_player.enableControl(); + } else { + _globals->setFlag(109); + _globals->_player.setPriority2(76); + _globals->_player.disableControl(); + + _sceneMode = 2281; + setAction(&_sequenceManager, this, 2281, &_globals->_player, &_hotspot16, NULL); + + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + } + + _globals->_sceneItems.addItems(&_hotspot13, &_hotspot11, &_hotspot9, &_hotspot14, &_hotspot7, + &_hotspot6, &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, &_hotspot1, &_hotspot16, &_hotspot15, NULL); + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; +} + +void Scene2280::signal() { + if (_sceneMode == 2281) { + _globals->_player.setPriority2(-1); + _globals->_player.enableControl(); + } +} + +void Scene2280::dispatch() { + Scene::dispatch(); + if (!_action) { + if (_exitRect.contains(_globals->_player._position)) + _globals->_sceneManager.changeScene(2150); + } +} + +void Scene2280::synchronise(Serialiser &s) { + Scene::synchronise(s); + _exitRect.synchronise(s); +} + +/*-------------------------------------------------------------------------- + * Scene 2300 - Starcraft - Hanger Bay + * + *--------------------------------------------------------------------------*/ + +void Scene2300::Action1::signal() { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: { + Common::Point pt(SCREEN_WIDTH, SCREEN_HEIGHT); + NpcMover *mover = new NpcMover(); + scene->_hotspot2.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_hotspot8.setAction(&scene->_action4); + scene->_soundHandler2.startSound(21); + + Common::Point pt1(95, scene->_hotspot5._position.y); + NpcMover *mover1 = new NpcMover(); + scene->_hotspot5.addMover(mover1, &pt1, this); + + Common::Point pt2(99, scene->_hotspot6._position.y); + NpcMover *mover2 = new NpcMover(); + scene->_hotspot6.addMover(mover2, &pt2, NULL); + break; + } + case 3: + setDelay(2); + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_WALK); + break; + case 4: { + scene->_hotspot5.setVisage(93); + scene->_hotspot6.setVisage(94); + scene->_hotspot5.setStrip(1); + scene->_hotspot6.setStrip(1); + scene->_hotspot5.changeZoom(50); + scene->_hotspot6.changeZoom(50); + scene->_hotspot5._moveDiff.x = 5; + scene->_hotspot6._moveDiff.x = 5; + scene->_hotspot5.animate(ANIM_MODE_1, NULL); + scene->_hotspot6.animate(ANIM_MODE_1, NULL); + + Common::Point pt1(178, 147); + NpcMover *mover1 = new NpcMover(); + scene->_hotspot5.addMover(mover1, &pt1, this); + + Common::Point pt2(170, 145); + NpcMover *mover2 = new NpcMover(); + scene->_hotspot6.addMover(mover2, &pt2, this); + break; + } + case 6: + scene->_soundHandler1.startSound(28); + _globals->_player.disableControl(); + + scene->_hotspot2.setVisage(40); + scene->_hotspot2.setStrip(4); + scene->_hotspot2.setFrame(1); + scene->_hotspot2.animate(ANIM_MODE_5, NULL); + + _globals->_player.setVisage(40); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 7: + _globals->_soundHandler.startSound(77, this); + break; + case 8: + _globals->_game.endGame(2300, 0); + break; + case 9: + if (scene->_hotspot5._mover) + scene->_hotspot5.addMover(NULL); + if (scene->_hotspot6._mover) + scene->_hotspot6.addMover(NULL); + + scene->_hotspot5.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot6.animate(ANIM_MODE_NONE, NULL); + + _globals->_player.disableControl(); + _globals->_player.setVisage(2672); + _globals->_player._strip = 5; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 10: + _globals->_player.setVisage(2674); + _globals->_player._strip = 5; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 11: + scene->_soundHandler1.startSound(28); + + scene->_hotspot5._strip = 2; + scene->_hotspot6._strip = 2; + scene->_hotspot5._frame = 1; + scene->_hotspot6._frame = 1; + scene->_hotspot5.animate(ANIM_MODE_5, NULL); + scene->_hotspot6.animate(ANIM_MODE_5, NULL); + scene->_hotspot5.setPriority2(20); + scene->_hotspot6.setPriority2(20); + + _globals->_player.setVisage(2672); + _globals->_player._strip = 5; + _globals->_player._frame = _globals->_player.getFrameCount(); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 12: + scene->_soundHandler1.startSound(77); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(4); + _globals->_player._uiEnabled = false; + setDelay(60); + break; + case 13: + scene->_stripManager.start(2300, this); + break; + case 14: + setDelay(5); + _actionIndex = 16; + break; + case 15: { + Common::Point pt1(101, 148); + PlayerMover *mover1 = new PlayerMover(); + _globals->_player.addMover(mover1, &pt1, this); + + Common::Point pt2(scene->_hotspot5._position.x + 5, scene->_hotspot5._position.y + 5); + NpcMover *mover2 = new NpcMover(); + scene->_hotspot2.addMover(mover2, &pt2, NULL); + break; + } + case 16: + _globals->_sceneManager.changeScene(2000); + remove(); + break; + } +} + +void Scene2300::Action2::signal() { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(30); + break; + case 1: { + Common::Point pt(153, 135); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(2030, this); + break; + case 3: + _globals->_player.enableControl(); + setDelay(600); + break; + case 4: { + _globals->_player.disableControl(); + + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(2801); + scene->_hotspot2.setPosition(Common::Point(109, 145)); + scene->_hotspot2.changeZoom(50); + scene->_hotspot2.animate(ANIM_MODE_1, NULL); + scene->_hotspot2.setObjectWrapper(new SceneObjectWrapper()); + + Common::Point pt(160, 145); + NpcMover *mover = new NpcMover(); + scene->_hotspot2.addMover(mover, &pt, this); + break; + } + case 5: + scene->_stripManager.start(2032, this); + break; + case 6: + scene->_hotspot2.setVisage(93); + scene->_hotspot2.setStrip(3); + scene->_hotspot2.setFrame(1); + scene->_hotspot2.animate(ANIM_MODE_5, this); + + scene->_soundHandler1.startSound(28); + scene->_soundHandler2.startSound(97); + break; + case 7: + scene->_hotspot7._strip = 2; + scene->_hotspot7._frame = 1; + scene->_hotspot7.animate(ANIM_MODE_7, this); + break; + case 8: + scene->_hotspot2.animate(ANIM_MODE_6, this); + break; + case 9: + scene->_stripManager.start(2035, this); + break; + case 10: + _globals->_sceneManager.changeScene(2310); + break; + } +} + +void Scene2300::Action3::signal() { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + Common::Point pt(153, 135); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + _globals->_player.disableControl(); + _globals->_player.setVisage(2672); + _globals->_player._strip = 2; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player.setVisage(2674); + _globals->_player._strip = 2; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_soundHandler1.startSound(97); + scene->_soundHandler2.startSound(28); + + scene->_hotspot7._strip = 2; + scene->_hotspot7._frame = 1; + scene->_hotspot7.animate(ANIM_MODE_5, this); + + _globals->_player.setVisage(2672); + _globals->_player._strip = 2; + _globals->_player._frame = _globals->_player.getFrameCount(); + _globals->_player.animate(ANIM_MODE_6, NULL); + break; + case 4: + scene->_soundHandler2.startSound(97); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(1); + scene->_stripManager.start(2034, this); + break; + case 5: + setDelay(10); + break; + case 6: + _globals->_sceneManager.changeScene(2310); + break; + } +} + +void Scene2300::Action4::signal() { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_hotspot8.animate(ANIM_MODE_5, this); + scene->_soundHandler1.startSound(11); + break; + case 1: + scene->_hotspot9.postInit(); + scene->_hotspot9.setVisage(2301); + scene->_hotspot9.setStrip2(2); + scene->_hotspot9.setFrame(3); + scene->_hotspot9.setPosition(Common::Point(273, 199)); + scene->_hotspot9.setPriority2(19); + scene->_hotspot9.animate(ANIM_MODE_5, this); + scene->_soundHandler1.startSound(11); + break; + case 2: + scene->_hotspot8.remove(); + + scene->_hotspot10.postInit(); + scene->_hotspot10.setVisage(2301); + scene->_hotspot10.setStrip(3); + scene->_hotspot10.setFrame(4); + scene->_hotspot10.setPosition(Common::Point(292, 113)); + scene->_hotspot10.animate(ANIM_MODE_5, this); + scene->_soundHandler1.startSound(11); + break; + case 3: + scene->_soundHandler1.startSound(13); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2300::Hotspot5::doAction(int action) { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + _globals->_player.disableControl(); + _globals->_player.addMover(NULL); + scene->_action1.setActionIndex(9); + scene->_action1.setDelay(1); + break; + case CURSOR_LOOK: + SceneItem::display2(2300, 3); + break; + case CURSOR_USE: + SceneItem::display2(2300, 4); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2300::Hotspot6::doAction(int action) { + Scene2300 *scene = (Scene2300 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + scene->setAction(&scene->_action3); + break; + case CURSOR_LOOK: + SceneItem::display2(2300, 2); + break; + case CURSOR_USE: + SceneItem::display2(2300, 21); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene2300::Scene2300() : + _hotspot11(0, CURSOR_LOOK, 2300, 6, CURSOR_USE, 2300, 14, LIST_END), + _hotspot12(0, CURSOR_LOOK, 2300, 5, CURSOR_USE, 2300, 13, LIST_END), + _hotspot13(0, CURSOR_LOOK, 2300, 9, CURSOR_USE, 2300, 20, LIST_END), + _hotspot14(0, CURSOR_LOOK, 2300, 7, CURSOR_USE, 2300, 15, LIST_END), + _hotspot15(0, CURSOR_LOOK, 2300, 1, LIST_END) { +} + +void Scene2300::postInit(SceneObjectList *OwnerList) { + loadScene(2300); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerML); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + + _globals->_inventory._stunner._sceneNumber = 1; + _globals->_inventory._infoDisk._sceneNumber = 1; + + _hotspot8.postInit(); + _hotspot8.setVisage(2301); + _hotspot8.setPosition(Common::Point(288, 74)); + + _globals->_soundHandler.startSound(96); + if (_globals->_sceneManager._previousScene == 2000) { + _hotspot8.remove(); + + _hotspot9.postInit(); + _hotspot9.setVisage(2301); + _hotspot9.setStrip2(2); + _hotspot9._frame = _hotspot9.getFrameCount(); + _hotspot9.setPosition(Common::Point(273, 199)); + _hotspot9.setPriority2(1); + + _hotspot10.postInit(); + _hotspot10.setVisage(2301); + _hotspot10.setStrip(3); + _hotspot10._frame = _hotspot10.getFrameCount(); + _hotspot10.setPosition(Common::Point(292, 113)); + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.setPosition(Common::Point(109, 139)); + _globals->_player.changeZoom(40); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.disableControl(); + + _hotspot7.postInit(); + _hotspot7.setVisage(2302); + _hotspot7.animate(ANIM_MODE_2, NULL); + _hotspot7.setPosition(Common::Point(229, 125)); + _hotspot7._numFrames = 5; + + _soundHandler1.startSound(95); + _soundHandler2.startSound(96); + _globals->_sceneItems.push_back(&_hotspot7); + + setAction(&_action2); + } else { + _hotspot8._numFrames = 3; + + _hotspot3.postInit(); + _hotspot3.setVisage(2331); + _hotspot3.setStrip(7); + _hotspot3.setPosition(Common::Point(231, 190)); + _hotspot3.changeZoom(40); + + _hotspot2.postInit(); + _hotspot2.setVisage(2801); + _hotspot2.setPosition(Common::Point(269, 195)); + _hotspot2.changeZoom(50); + _hotspot2.animate(ANIM_MODE_1, NULL); + _hotspot2.setObjectWrapper(new SceneObjectWrapper()); + + _hotspot1.postInit(); + _hotspot1.setVisage(2331); + _hotspot1.setStrip(7); + _hotspot1.setPosition(Common::Point(255, 190)); + _hotspot1.changeZoom(40); + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.setPosition(Common::Point(203, 191)); + _globals->_player.changeZoom(40); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.disableControl(); + + _hotspot5.postInit(); + _hotspot5.setVisage(91); + _hotspot5.setPosition(Common::Point(343, 145)); + _hotspot5._moveDiff = Common::Point(35, 35); + _hotspot5.changeZoom(40); + _hotspot5.setObjectWrapper(new SceneObjectWrapper()); + + _hotspot6.postInit(); + _hotspot6.setVisage(92); + _hotspot6.setPosition(Common::Point(343, 130)); + _hotspot6._moveDiff = Common::Point(35, 35); + _hotspot6.changeZoom(40); + _hotspot6.setObjectWrapper(new SceneObjectWrapper()); + + _globals->_sceneItems.push_back(&_hotspot5); + setAction(&_action1); + } + + _hotspot12._sceneRegionId = 8; + _hotspot11._sceneRegionId = 9; + _hotspot13._sceneRegionId = 10; + _hotspot14._sceneRegionId = 11; + + _hotspot15.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _globals->_sceneItems.addItems(&_hotspot12, &_hotspot11, &_hotspot13, &_hotspot14, &_hotspot15, NULL); +} + +/*-------------------------------------------------------------------------- + * Scene 2310 - Starcraft - Copy Protection Screen + * + *--------------------------------------------------------------------------*/ + +Scene2310::Scene2310() { + _pageList[0].set(0, 0, 0, 0, 0, 0); + _pageList[1].set(1, 0, 3, 2, 1, 4); + _pageList[2].set(2, 1, 4, 3, 2, 0); + _pageList[3].set(3, 2, 0, 4, 3, 1); + _pageList[4].set(4, 3, 1, 0, 2, 4); + _pageList[5].set(5, 4, 2, 1, 3, 0); + _pageList[6].set(6, 0, 4, 2, 3, 1); + _pageList[7].set(7, 1, 0, 2, 4, 3); + _pageList[8].set(8, 2, 1, 3, 0, 4); + _pageList[9].set(9, 3, 2, 4, 1, 0); + _pageList[10].set(10, 4, 1, 2, 0, 3); + _pageList[11].set(11, 0, 2, 3, 4, 1); + _pageList[12].set(12, 1, 2, 0, 4, 3); + _pageList[13].set(13, 2, 4, 0, 3, 1); + _pageList[14].set(14, 3, 4, 1, 0, 2); + _pageList[15].set(15, 4, 3, 1, 2, 0); + _pageList[16].set(16, 0, 1, 4, 2, 3); + _pageList[17].set(17, 1, 3, 4, 0, 2); + _pageList[18].set(18, 2, 3, 0, 1, 4); + _pageList[19].set(19, 3, 0, 1, 4, 2); + _pageList[20].set(20, 4, 0, 3, 1, 2); +} + +void Scene2310::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + loadScene(2301); + Common::Point pointList[5] = { Common::Point(142, 82), Common::Point(158, 82), Common::Point(174, 82), + Common::Point(190, 82), Common::Point(205, 82) }; + + for (int idx = 0; idx < 5; ++idx) { + _wireList[idx].postInit(); + _wireList[idx].setVisage(2300); + _wireList[idx]._strip = idx + 1; + _wireList[idx]._frame = 1; + _wireList[idx].setPosition(pointList[idx]); + } + + _rectList[0].set(135, 70, 151, 140); + _rectList[1].set(151, 70, 167, 140); + _rectList[2].set(167, 70, 183, 140); + _rectList[3].set(183, 70, 199, 140); + _rectList[4].set(199, 70, 215, 140); + + _globals->_player.disableControl(); + _globals->_events.setCursor(CURSOR_WALK); + + _wireIndex = 5; + _pageIndex = _globals->_randomSource.getRandomNumber(19) + 1; + signal(); +} + +void Scene2310::signal() { + switch (_sceneMode++) { + case 0: { + Common::String fmtString = _vm->_dataManager->getMessage(2300, 22); + Common::String msg = Common::String::format(fmtString.c_str(), _pageList[_pageIndex]._pageNumber); + + _sceneText._width = 280; + _sceneText._textMode = ALIGN_CENTRE; + _sceneText._colour1 = 35; + _sceneText._fontNumber = 2; + _sceneText.setup(msg); + _sceneText.setPriority2(255); + _sceneText.setPosition(Common::Point(30, 20)); + break; + } + case 1: { + Common::String msg = _vm->_dataManager->getMessage(2300, 23); + _sceneText.setup(msg); + _sceneText.setPriority2(255); + _sceneText.setPosition(Common::Point(30, 170)); + + _globals->_sceneObjects->draw(); + _globals->_events.waitForPress(); + + _sceneText.hide(); + _globals->_sceneObjects->draw(); + + _globals->_sceneManager.changeScene(2200); + break; + } + } +} + +void Scene2310::synchronise(Serialiser &s) { + Scene::synchronise(s); + + s.syncAsSint16LE(_wireIndex); + s.syncAsSint16LE(_pageIndex); +} + +void Scene2310::process(Event &event) { + int frameNum = 0; + + if (!event.handled && (event.eventType == EVENT_BUTTON_DOWN)) { + int idx = 0; + while (idx < 5) { + if (_rectList[idx].contains(event.mousePos)) + break; + ++idx; + } + + if (idx < 5) { + // In handled rectangle area + if (_wireIndex == 5) { + // No wire is currently active, so start moving designated wire + _wireIndex = idx; + frameNum = idx + 2; + + if (event.mousePos.y > 105) + idx = findObject(idx); + + if (idx != 5) { + _wireList[idx].hide(); + _globals->_sceneObjects->draw(); + _wireList[idx].setFrame(frameNum); + + _wireList[idx].show(); + _globals->_sceneObjects->draw(); + } + } else { + // End the moving of the currently active wire + _wireList[_wireIndex].setFrame(idx + 2); + _wireIndex = 5; + + // Check if solution has been reached + int idx2 = 0; + do { + int objIndex = findObject(idx2); + if (_pageList[_pageIndex]._connectionList[idx2] != objIndex) + // Mismatch + break; + } while (++idx2 < 5); + + if (idx2 == 5) + // All the entries are correct + signal(); + } + + event.handled = true; + } else if (_wireIndex != 5) { + // Reset the active wire back to unplugged + _wireList[_wireIndex].setFrame(1); + _wireIndex = 5; + } + } +} + +void Scene2310::dispatch() { + if ((_vm->getFeatures() & GF_CD) && !ConfMan.getBool("copy_protection")) { + // CD version of Ringworld has the copy protection disabled + signal(); + } else if (_wireIndex != 5) { + for (int idx = 0; idx < 5; ++idx) { + if (_rectList[idx].contains(_globals->_events._mousePos)) { + _wireList[_wireIndex].setFrame(idx + 2); + return; + } + } + + _wireList[_wireIndex].setFrame(1); + } +} + +int Scene2310::findObject(int objIndex) { + for (int idx = 0; idx < 5; ++idx) { + if (_wireList[idx]._frame == (objIndex + 2)) + return idx; + } + + return 5; +} + +/*-------------------------------------------------------------------------- + * Scene 2320 - Starcraft - Lander Bay + * + *--------------------------------------------------------------------------*/ + +void Scene2320::Action1::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + if (_globals->_sceneManager._previousScene == 2120) + _actionIndex = 3; + break; + case 1: { + Common::Point pt(513, 144); + NpcMover *mover = new NpcMover(); + scene->_hotspot11.addMover(mover, &pt, this); + break; + } + case 2: { + Common::Point pt(510, 164); + NpcMover *mover = new NpcMover(); + scene->_hotspot11.addMover(mover, &pt, this); + break; + } + case 3: + setAction(&scene->_sequenceManager2, this, 2328, &scene->_hotspot11, NULL); + break; + case 4: + scene->_hotspot11.animate(ANIM_MODE_NONE); + setDelay(120); + _actionIndex = 3; + break; + } +} + +void Scene2320::Action2::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_soundHandler.startSound(253); + scene->_hotspot13.setPriority2(99); + + Common::Point pt(scene->_hotspot13._position.x, 200); + NpcMover *mover = new NpcMover(); + scene->_hotspot13.addMover(mover, &pt, this); + break; + } + case 1: + scene->_hotspot13.hide(); + remove(); + break; + } +} + +void Scene2320::Action3::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + Common::Point pt(320, 86); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 1: + scene->_soundHandler.startSound(162); + scene->_hotspot6.animate(ANIM_MODE_5, this); + break; + case 2: { + Common::Point pt(320, 79); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + scene->_hotspot6.setPriority2(scene->_hotspot6._priority - 1); + _globals->_player._strip = 3; + setDelay(10); + break; + case 4: + scene->_area1.display(); + scene->_area2.display(); + scene->_area3.display(); + scene->_area4.display(); + + scene->_area3.draw(true); + _state = 0; + _globals->_events.setCursor(CURSOR_USE); + + while (!_state && !_vm->getEventManager()->shouldQuit()) { + // Wait for an event + Event event; + if (!_globals->_events.getEvent(event)) { + g_system->updateScreen(); + g_system->delayMillis(10); + continue; + } + + if (scene->_area1._bounds.contains(event.mousePos)) { + scene->_area1.draw(true); + scene->_area3.draw(false); + _state = scene->_area1._actionId; + } + if (scene->_area2._bounds.contains(event.mousePos)) { + scene->_area3.draw(false); + scene->_area2.draw(true); + _state = scene->_area2._actionId; + } + if (scene->_area3._bounds.contains(event.mousePos)) { + scene->_area3.draw(true); + _state = scene->_area3._actionId; + } + } + + scene->_soundHandler.startSound(161); + scene->_area1.restore(); + scene->_area2.restore(); + scene->_area3.restore(); + scene->_area4.restore(); + + if (_state == 2320) { + setDelay(10); + } else { + scene->_soundHandler.startSound(162); + scene->_hotspot6.animate(ANIM_MODE_6, this); + } + break; + case 5: { + if (_state == 2320) + _globals->_player.setPriority2(-1); + else + _globals->_sceneManager.changeScene(_state); + + Common::Point pt(320, 86); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: + scene->_soundHandler.startSound(162); + scene->_hotspot6.animate(ANIM_MODE_6, this); + break; + case 7: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2320::Action4::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: { + Common::Point pt(213, 84); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + case 16: + _globals->_player.setVisage(2109); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_player.animate(ANIM_MODE_6, NULL); + scene->setAction(&scene->_action2); + break; + case 4: { + scene->_hotspot16.postInit(); + scene->_hotspot16.setVisage(2331); + scene->_hotspot16.setStrip(3); + scene->_hotspot16.setPriority2(149); + scene->_hotspot16.setPosition(Common::Point(320, 202)); + scene->_hotspot16.show(); + + Common::Point pt(320, 121); + NpcMover *mover = new NpcMover(); + scene->_hotspot16.addMover(mover, &pt, this); + break; + } + case 5: { + scene->_hotspot16.setPriority2(200); + Common::Point pt(320, 180); + NpcMover *mover = new NpcMover(); + scene->_hotspot16.addMover(mover, &pt, this); + break; + } + case 6: { + scene->_hotspot16.setPriority2(-1); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + + Common::Point pt(233, 176); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 7: { + Common::Point pt(291, 194); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 8: + _globals->_player.setStrip(5); + _globals->_player.setFrame(1); + setDelay(13); + break; + case 9: + if (!_globals->getFlag(109)) { + SceneItem::display2(2320, 19); + } else { + _globals->_sceneManager.changeScene(7600); + } + break; + case 10: + if (_globals->getFlag(109)) { + _globals->_soundHandler.startSound(40); + _globals->_soundHandler.proc5(true); + + Common::Point pt(303, 240); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + } else { + setDelay(3); + } + break; + case 11: + if (_globals->getFlag(109)) { + _globals->_sceneManager.changeScene(7600); + } else { + SceneItem::display2(2320, 19); + setDelay(3); + } + break; + case 12: + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 13: + _globals->_player.setVisage(0); + _globals->_player.setPosition(Common::Point(291, 194)); + _globals->_player.setStrip(5); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_1, NULL); + + scene->_hotspot16.show(); + setDelay(3); + break; + case 14: { + Common::Point pt(233, 176); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 15: { + Common::Point pt(213, 85); + PlayerMover *mover = new PlayerMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 17: { + _globals->_player.animate(ANIM_MODE_6, NULL); + scene->_hotspot16.setPriority2(160); + + Common::Point pt(320, 121); + NpcMover *mover = new NpcMover(); + scene->_hotspot16.addMover(mover, &pt, this); + break; + } + case 18: { + Common::Point pt(320, 202); + PlayerMover *mover = new PlayerMover(); + scene->_hotspot16.addMover(mover, &pt, this); + break; + } + case 19: { + scene->_hotspot16.remove(); + scene->_soundHandler.startSound(253); + + scene->_hotspot13.show(); + Common::Point pt(319, 157); + NpcMover *mover = new NpcMover(); + scene->_hotspot13.addMover(mover, &pt, this); + break; + } + case 20: + _globals->_player.enableControl(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + + scene->_hotspot13.setPriority2(1); + remove(); + break; + } +} + +void Scene2320::Action5::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_PLAYER_MOVER(163, 126); + break; + case 1: + ADD_PLAYER_MOVER(165, 132); + break; + case 2: + setDelay(2); + break; + case 3: + if (!_globals->getFlag(59)) + setDelay(10); + else + scene->_stripManager.start(2323, this); + break; + case 4: + _globals->_player.setVisage(2347); + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.setPriority2(137); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 5: + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 6: + if (_globals->getFlag(72)) + _globals->_sceneManager.changeScene(7000); + else if (_globals->getFlag(59)) + _globals->_sceneManager.changeScene(5000); + else if (!_globals->getFlag(43) || (_globals->_inventory._ale._sceneNumber != 1)) + setDelay(10); + else { + scene->_hotspot11.setAction(NULL); + scene->_hotspot11.setVisage(2705); + scene->_hotspot11.animate(ANIM_MODE_1, NULL); + scene->_hotspot11.setObjectWrapper(new SceneObjectWrapper()); + + Common::Point pt(185, 135); + NpcMover *mover = new NpcMover(); + scene->_hotspot11.addMover(mover, &pt, NULL); + + _globals->clearFlag(53); + scene->_stripManager.start(2325, this); + } + break; + case 7: + setDelay(10); + break; + case 8: + _globals->_sceneManager.changeScene(4000); + break; + } +} + +void Scene2320::Action6::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 2: + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player.setVisage(0); + _globals->_player.setStrip(3); + _globals->_player.setPriority2(-1); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.animate(ANIM_MODE_1, NULL); + + setDelay(60); + break; + case 4: + if ((_globals->_sceneManager._previousScene != 4000) || _globals->getFlag(43)) + setDelay(3); + else if (_globals->getFlag(35)) { + _globals->setFlag(43); + scene->_stripManager.start(4200, this); + _globals->setFlag(69); + } else if (_globals->getFlag(36)) { + setDelay(3); + } else { + _globals->setFlag(43); + scene->_stripManager.start(4210, this); + break; + } + break; + case 5: + if (_globals->_sceneObjects->contains(&scene->_hotspot11)) { + scene->_hotspot11.setAction(&scene->_action1); + + if (_globals->_sceneObjects->contains(&scene->_hotspot10)) { + ADD_MOVER(scene->_hotspot10, 491, 160); + } else { + setDelay(60); + } + + _globals->_sceneItems.push_front(&scene->_hotspot11); + } else { + setDelay(3); + } + break; + case 6: + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene2320::Action7::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + _globals->_soundHandler.startSound(162); + scene->_hotspot6.animate(ANIM_MODE_5, this); + break; + case 2: + scene->_hotspot10.setPriority2(-1); + ADD_MOVER_NULL(scene->_hotspot10, 321, 94); + scene->_hotspot11.setPriority2(-1); + ADD_MOVER_NULL(scene->_hotspot11, 346, 85); + + _globals->_player.setPriority2(-1); + ADD_MOVER(_globals->_player, 297, 89); + break; + case 3: + ADD_PLAYER_MOVER(462, 182); + break; + case 4: + ADD_MOVER(scene->_hotspot11, 391, 88); + break; + case 5: + ADD_MOVER(scene->_hotspot11, 500, 164); + ADD_MOVER(scene->_hotspot10, 382, 93); + _globals->_player.setStrip(3); + break; + case 6: + ADD_MOVER_NULL(scene->_hotspot10, 491, 160); + ADD_MOVER(_globals->_player, 391, 88); + + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 7: + ADD_PLAYER_MOVER(462, 182); + break; + case 8: + _globals->_player.setStrip(7); + setDelay(15); + break; + case 9: + scene->_stripManager.start(6020, this); + break; + case 10: + setDelay(6); + break; + case 11: + scene->_stripManager.start(6022, this); + break; + case 12: + _globals->_player.enableControl(); + _globals->_inventory._stasisBox._sceneNumber = 2320; + break; + } +} + +void Scene2320::Action8::signal() { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + ADD_PLAYER_MOVER(462, 182); + break; + case 2: + _globals->_player.setStrip(7); + setDelay(5); + break; + case 3: + scene->_speakerGameText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 30, 10)); + scene->_stripManager.start(_globals->getFlag(75) ? 6030 : 2320, this); + break; + case 4: + if (_globals->getFlag(75)) + setDelay(3); + else + _globals->_player.enableControl(); + break; + case 5: + _globals->_inventory._stasisBox._sceneNumber = 2320; + scene->_sceneMode = 2326; + scene->_speakerGameText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 30, 10)); + scene->setAction(&scene->_sequenceManager1, scene, 2326, &_globals->_player, &scene->_hotspot11, NULL); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene2320::Hotspot5::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 13); + break; + case CURSOR_USE: + if (_globals->getFlag(70)) + SceneItem::display2(2320, 33); + else if (_globals->getFlag(13)) + SceneItem::display2(2320, 18); + else + scene->setAction(&scene->_action5); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot6::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 2); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot8::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 23); + break; + case CURSOR_USE: + scene->_sceneMode = 2336; + scene->setAction(&scene->_sequenceManager1, scene, 2336, &_globals->_player, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot10::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 26); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->_sceneMode = 2329; + + if (_globals->getFlag(13)) { + scene->_stripManager.start(2337, scene); + } else if (_globals->getFlag(70)) { + scene->setAction(&scene->_action8); + } else if (_globals->getFlag(109)) { + scene->setAction(&scene->_sequenceManager1, scene, 2337, NULL); + } else if (!_state) { + ++_state; + scene->setAction(&scene->_sequenceManager1, scene, 2334, NULL); + } else { + scene->setAction(&scene->_sequenceManager1, scene, 2335, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot11::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 25); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->_sceneMode = 2329; + + if (_globals->getFlag(13)) { + _globals->_player.disableControl(); + scene->_sceneMode = 5000; + scene->_stripManager.start(2336, scene); + } else if (_globals->getFlag(70)) { + scene->setAction(&scene->_action8); + } else { + scene->_sceneMode = 2329; + + if (_globals->_inventory._ale._sceneNumber == 1) { + scene->setAction(&scene->_sequenceManager1, scene, 2329, NULL); + } else if (!_globals->getFlag(110)) { + _globals->setFlag(110); + scene->setAction(&scene->_sequenceManager1, scene, 2330, NULL); + } else if (_globals->_inventory._peg._sceneNumber != 1) { + scene->setAction(&scene->_sequenceManager1, scene, 2331, NULL); + } else if (!_state) { + ++_state; + scene->setAction(&scene->_sequenceManager1, scene, 2332, NULL); + } else { + scene->setAction(&scene->_sequenceManager1, scene, 2333, NULL); + } + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot12::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 5); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2320, 24); + else { + _globals->_player.disableControl(); + scene->_sceneMode = 2322; + scene->setAction(&scene->_sequenceManager1, scene, 2322, &_globals->_player, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot14::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 17); + break; + case CURSOR_USE: + if (_globals->getFlag(24)) { + _globals->clearFlag(24); + _globals->_player.disableControl(); + + scene->_hotspot8.postInit(); + scene->_hotspot8.setVisage(2345); + scene->_hotspot8.setPosition(Common::Point(634, 65)); + scene->_hotspot8.hide(); + + _globals->_sceneItems.push_front(&scene->_hotspot8); + _globals->_inventory._waldos._sceneNumber = 2320; + + scene->_hotspot9.postInit(); + scene->_hotspot9.setVisage(2345); + scene->_hotspot9._strip = 6; + scene->_hotspot9.setPosition(Common::Point(536, 103)); + scene->_hotspot9.setPriority2(200); + scene->_hotspot9.hide(); + + scene->_hotspot16.postInit(); + scene->_hotspot16.setVisage(2345); + scene->_hotspot16.setStrip(8); + scene->_hotspot16.setPosition(Common::Point(536, 103)); + scene->_hotspot16.hide(); + + scene->_sceneMode = 2324; + scene->setAction(&scene->_sequenceManager1, scene, 2324, &_globals->_player, &scene->_hotspot7, + &scene->_hotspot8, &scene->_hotspot9, &scene->_hotspot16, NULL); + } else if (_globals->getFlag(13)) { + SceneItem::display2(2320, 24); + } else if (!_globals->getFlag(76)) { + SceneItem::display2(2320, 28); + } else if (!_globals->_inventory._waldos._sceneNumber) { + SceneItem::display2(2320, 27); + } else { + SceneItem::display2(2320, 29); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene2320::Hotspot15::doAction(int action) { + Scene2320 *scene = (Scene2320 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(2320, 16); + break; + case CURSOR_USE: + if (_globals->getFlag(13)) + SceneItem::display2(2320, 24); + else + scene->setAction(&scene->_action4); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + + +/*--------------------------------------------------------------------------*/ + +Scene2320::Scene2320() : + _hotspot1(0, CURSOR_LOOK, 2320, 0, LIST_END), + _hotspot2(0, CURSOR_LOOK, 2320, 1, LIST_END), + _hotspot3(0, CURSOR_LOOK, 2320, 11, LIST_END), + _hotspot4(0, CURSOR_LOOK, 2320, 14, LIST_END), + _hotspot13(0, CURSOR_LOOK, 2320, 12, LIST_END) +{ +} + +void Scene2320::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(60, 75, 100, 100); + + _stripManager.addSpeaker(&_speakerMR); + _stripManager.addSpeaker(&_speakerML); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerSAL); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + + _speakerMText._npc = &_hotspot11; + _speakerQText._npc = &_globals->_player; + _hotspotPtr = &_hotspot10; + + _hotspot6.postInit(); + _hotspot6.setVisage(2321); + _hotspot6.setPosition(Common::Point(320, 67)); + + _hotspot7.postInit(); + _hotspot7.setVisage(2344); + _hotspot7.setPosition(Common::Point(604, 92)); + + _hotspot13.postInit(); + _hotspot13.setVisage(2323); + _hotspot13.setPosition(Common::Point(319, 157)); + _hotspot13.setPriority2(1); + + _hotspot12.postInit(); + _hotspot12.setVisage(2321); + _hotspot12._strip = 4; + _hotspot12.animate(ANIM_MODE_8, 0, NULL); + _hotspot12.setPosition(Common::Point(412, 46)); + + if (_globals->_inventory._waldos._sceneNumber == 2320) { + _hotspot8.postInit(); + _hotspot8.setVisage(2345); + _hotspot8.setStrip(5); + _hotspot8.setFrame(8); + _hotspot8.setPosition(Common::Point(541, 103)); + _hotspot8.setPriority2(201); + + _globals->_sceneItems.push_back(&_hotspot8); + } + + _area1.setup(2100, 2, 1, 2150); + _area1._pt = Common::Point(200, 31); + _area2.setup(2153, 3, 1, 2150); + _area2._pt = Common::Point(200, 50); + _area3.setup(2153, 4, 1, 2320); + _area3._pt = Common::Point(200, 75); + _area4.setup(2153, 1, 1, 10); + _area4._pt = Common::Point(237, 77); + + if (_globals->getFlag(43)) { + _hotspot11.postInit(); + _hotspot11.setVisage(2705); + _hotspot11._strip = 3; + _hotspot11.setPosition(Common::Point(510, 156)); + _hotspot11._state = 0; + _hotspot11.setAction(&_action1); + + _globals->_sceneItems.push_back(&_hotspot11); + } + + _globals->_player.postInit(); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(320, 79)); + _globals->_player.setPriority2(10); + _globals->_player.changeZoom(-1); + _globals->_player._moveDiff.y = 3; + _globals->_player.disableControl(); + + if (_globals->getFlag(114)) { + _hotspot10.postInit(); + _hotspot10.setVisage(2806); + _hotspot10.setPosition(Common::Point(481, 162)); + _hotspot10.changeZoom(-1); + _hotspot10.setStrip(5); + _hotspot10._state = 0; + + _globals->_sceneItems.push_back(&_hotspot10); + } + + if (_globals->getFlag(70)) { + _hotspot11.postInit(); + _hotspot11.setVisage(2705); + _hotspot11.setPosition(Common::Point(500, 164)); + + _hotspot10.postInit(); + _hotspot10.setVisage(2806); + _hotspot10.setPosition(Common::Point(481, 162)); + _hotspot10.changeZoom(-1); + _hotspot10.setStrip(5); + + _globals->_sceneItems.addItems(&_hotspot11, &_hotspot10, NULL); + } + + switch (_globals->_sceneManager._previousScene) { + case 2120: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + _globals->_player.setPriority2(-1); + _globals->_player.setPosition(Common::Point(389, 72)); + _globals->_player.enableControl(); + break; + case 4000: + if (!_globals->getFlag(36) && !_globals->getFlag(43)) { + _hotspot11.postInit(); + _hotspot11.setVisage(2705); + _hotspot11.setPosition(Common::Point(178, 118)); + _hotspot11.animate(ANIM_MODE_1, NULL); + } + // Deliberate fall-through + case 4250: + case 5000: + case 7000: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + if ((_globals->_sceneManager._previousScene == 7000) && !_globals->getFlag(80)) + _globals->setFlag(36); + + _globals->_player.disableControl(); + _globals->_player.animate(ANIM_MODE_NONE, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setVisage(2347); + _globals->_player.setStrip(2); + _globals->_player.setFrame(5); + _globals->_player.setPriority2(137); + _globals->_player.setPosition(Common::Point(165, 132)); + + setAction(&_action6); + break; + case 6100: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + + _hotspot8.postInit(); + _hotspot8.setVisage(2345); + _hotspot8.setPosition(Common::Point(634, 65)); + _hotspot8.hide(); + + _sceneMode = 2325; + setAction(&_sequenceManager1, this, 2325, &_globals->_player, &_hotspot6, &_hotspot8, &_hotspot7, NULL); + break; + case 7600: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _soundHandler.startSound(21); + + _globals->_player.setVisage(2323); + _globals->_player.setStrip(2); + _globals->_player.setFrame(_globals->_player.getFrameCount()); + _globals->_player.setPosition(Common::Point(303, 176)); + _globals->_player.setPriority2(-1); + _globals->_player.disableControl(); + + _hotspot13.setPosition(Common::Point(319, 199)); + + _hotspot16.postInit(); + _hotspot16.setVisage(2331); + _hotspot16._strip = 3; + _hotspot16.setPriority2(160); + _hotspot16.setPosition(Common::Point(320, 202)); + _hotspot16.hide(); + + _sceneMode = 2338; + setAction(&_sequenceManager1, this, 2338, &_globals->_player, &_hotspot16, &_hotspot13, NULL); + break; + default: + switch (_globals->_stripNum) { + case 2101: + _globals->_player.disableControl(); + _globals->_player.setStrip(3); + _globals->_player.setPosition(Common::Point(307, 84)); + + _hotspot11.postInit(); + _hotspot11.setVisage(2705); + _hotspot11._strip = 2; + _hotspot11.setPriority2(10); + _hotspot11.setPosition(Common::Point(322, 80)); + _hotspot11.setObjectWrapper(new SceneObjectWrapper()); + _hotspot11.animate(ANIM_MODE_1, NULL); + + _hotspot10.postInit(); + _hotspot10.setVisage(2806); + _hotspot10.setObjectWrapper(new SceneObjectWrapper()); + _hotspot10.changeZoom(-1); + _hotspot10.setPriority2(10); + _hotspot10.setPosition(Common::Point(318, 89)); + _hotspot10._strip = 3; + _hotspot10.animate(ANIM_MODE_1, NULL); + + setAction(&_action7); + break; + case 6100: + _hotspot8.postInit(); + _hotspot8.setVisage(2345); + _hotspot8.setPosition(Common::Point(634, 65)); + _hotspot8.hide(); + + _sceneMode = 2325; + setAction(&_sequenceManager1, this, 2325, &_globals->_player, &_hotspot6, &_hotspot8, &_hotspot7, NULL); + break; + default: + _globals->_soundHandler.startSound(160); + _globals->_soundHandler.proc5(true); + _sceneMode = 2321; + + _globals->_player.setStrip(3); + setAction(&_sequenceManager1, this, 2321, &_globals->_player, &_hotspot6, NULL); + break; + } + } + + _globals->_stripNum = 0; + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position); + loadScene(2320); + + _hotspot14._sceneRegionId = 8; + _hotspot1.setBounds(Rect(0, 0, 640, 200)); + _hotspot2.setBounds(Rect(278, 0, 362, 61)); + _hotspot3.setBounds(Rect(282, 62, 367, 98)); + _hotspot4.setBounds(Rect(67, 38, 112, 113)); + _hotspot5.setBounds(Rect(104, 122, 174, 157)); + _hotspot15.setBounds(Rect(191, 53, 205, 63)); + + _globals->_sceneItems.addItems(&_hotspot14, &_hotspot15, &_hotspot5, &_hotspot6, &_hotspot12, + &_hotspot13, &_hotspot4, &_hotspot3, &_hotspot2, &_hotspot1, NULL); +} + +void Scene2320::synchronise(Serialiser &s) { + Scene::synchronise(s); + SYNC_POINTER(_hotspotPtr); +} + +void Scene2320::signal() { + switch (_sceneMode) { + case 2321: + case 2327: + case 2329: + if (_globals->getFlag(43) && !_hotspot11._action) + _hotspot11.setAction(&_action1); + _globals->_player.enableControl(); + break; + case 2322: + _globals->_sceneManager.changeScene(2120); + break; + case 2323: + _globals->_player.disableControl(); + break; + case 2338: + case 2324: + _hotspot16.remove(); + _globals->_player.enableControl(); + break; + case 2325: + _globals->setFlag(76); + _globals->clearFlag(70); + _globals->_stripNum = 6100; + _globals->_sceneManager.changeScene(2100); + break; + case 2326: + _globals->clearFlag(70); + _globals->_inventory._nullifier._sceneNumber = 1; + _globals->_stripNum = 2321; + _globals->_sceneManager.changeScene(2100); + break; + case 2336: + _globals->setFlag(77); + _globals->_inventory._waldos._sceneNumber = 1; + _hotspot8.remove(); + break; + case 5000: + _globals->_player.enableControl(); + break; + } +} + +/*-------------------------------------------------------------------------- + * Scene 2400 - Descending in Lander + * + *--------------------------------------------------------------------------*/ + +void Scene2400::Action1::signal() { + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + ADD_MOVER(_globals->_player, 160, 71); + break; + case 2: + ADD_MOVER(_globals->_player, 160, 360); + break; + case 3: + _globals->_player._moveDiff = Common::Point(1, 1); + ADD_MOVER(_globals->_player, 140, 375); + break; + case 4: + ADD_MOVER(_globals->_player, 87, 338); + break; + case 5: + _globals->_player.hide(); + setDelay(60); + break; + case 6: + _globals->_sceneManager.changeScene(4000); + break; + } +} + +void Scene2400::Action1::dispatch() { + Action::dispatch(); + if ((_actionIndex == 4) && (_globals->_player._percent > 5)) + _globals->_player.changeZoom(_globals->_player._percent - 2); +} + +/*--------------------------------------------------------------------------*/ + +void Scene2400::postInit(SceneObjectList *OwnerList) { + loadScene(2400); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _globals->_player.postInit(); + _globals->_player.setVisage(2410); + _globals->_player.setPosition(Common::Point(340, -10)); + _globals->_player.animate(ANIM_MODE_2, NULL); + _globals->_player.disableControl(); + + setAction(&_action1); + + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position.x, _globals->_player._position.y); + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.left / 160) * 160; + + _globals->_soundHandler.startSound(153); +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes3.h b/engines/tsage/ringworld_scenes3.h new file mode 100644 index 0000000000..61aac522f2 --- /dev/null +++ b/engines/tsage/ringworld_scenes3.h @@ -0,0 +1,905 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES3_H +#define TSAGE_RINGWORLD_SCENES3_H + +#include "common/scummsys.h" +#include "tsage/core.h" +#include "tsage/converse.h" +#include "tsage/ringworld_logic.h" + +namespace tSage { + +class Scene2000 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + class Action9 : public Action { + public: + virtual void signal(); + }; + class Action10 : public Action { + public: + virtual void signal(); + }; + class Action11 : public Action { + public: + virtual void signal(); + }; + class Action12 : public Action { + public: + virtual void signal(); + }; + class Action13 : public Action { + public: + virtual void signal(); + }; + class Action14 : public Action { + public: + virtual void signal(); + }; + +public: + SpeakerSL _speakerSL; + SpeakerQR _speakerQR; + SpeakerMR _speakerMR; + SpeakerQText _speakerQText; + SpeakerMText _speakerMText; + SpeakerSText _speakerSText; + SpeakerHText _speakerHText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + Action9 _action9; + Action10 _action10; + Action11 _action11; + Action12 _action12; + Action13 _action13; + Action14 _action14; + SceneObject _object1, _object2, _object3, _object4, _object5; + SceneObject _object6, _object7, _object8, _object9, _object10; + SoundHandler _soundHandler1, _soundHandler2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void stripCallback(int v); +}; + +class Scene2100 : public Scene { + /* Actions */ + class Action1 : public ActionExt { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + class Action9 : public Action { + public: + virtual void signal(); + }; + class Action10 : public Action { + public: + virtual void signal(); + }; + class Action11 : public Action { + public: + virtual void signal(); + }; + class Action12 : public Action { + public: + virtual void signal(); + }; + class Action13 : public Action { + public: + virtual void signal(); + }; + class Action14 : public Action { + public: + virtual void signal(); + }; + class Action15 : public Action { + public: + virtual void signal(); + }; + class Action16 : public Action { + public: + virtual void signal(); + }; + class Action17 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; + + /* Objects */ + class Object1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object3 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + SpeakerMText _speakerMText; + SpeakerMR _speakerMR; + SpeakerQL _speakerQL; + SpeakerQR _speakerQR; + SpeakerQText _speakerQText; + SpeakerGameText _speakerGameText; + SpeakerSText _speakerSText; + SpeakerSL _speakerSL; + SpeakerSAL _speakerSAL; + SpeakerHText _speakerHText; + + DisplayHotspot _hotspot1; + Hotspot2 _hotspot2; + Hotspot3 _hotspot3; + Hotspot4 _hotspot4; + DisplayHotspot _hotspot5, _hotspot6, _hotspot7; + Hotspot8 _hotspot8; + DisplayHotspot _hotspot9; + Hotspot10 _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13; + Hotspot14 _hotspot14; + DisplayHotspot _hotspot15; + + Object1 _object1; + Object2 _object2; + Object3 _object3; + SceneObject _object4; + + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + Action9 _action9; + Action10 _action10; + Action11 _action11; + Action12 _action12; + Action13 _action13; + Action14 _action14; + Action15 _action15; + Action16 _action16; + Action17 _action17; + int _field1800; + SceneArea _area1, _area2, _area3, _area4; + + Scene2100(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void stripCallback(int v); + virtual void signal(); +}; + +class Scene2120 : public Scene { + /* Actions */ + class Entry { + public: + int _size; + int _lineNum; + int _visage; + + Entry() { _size = 0; _lineNum = 0; _visage = 0; } + Entry(int size, int lineNum, int visage) { _size = size; _lineNum = lineNum; _visage = visage; } + }; + + class Action1 : public Action { + private: + Common::Array<Entry> _entries; + public: + Action1(); + + virtual void signal(); + virtual void dispatch(); + }; + +public: + SoundHandler _soundHandler; + SceneObject _topicArrowHotspot, _arrowHotspot, _visageHotspot; + SceneObject _subjectButton, _nextPageButton, _previousPageButton, _exitButton; + Action1 _action1; + Rect _listRect; + int _dbMode, _prevDbMode; + bool _visageVisable; + int _subjectIndex; + int _lineOffset; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); +}; + +class Scene2150 : public Scene { + /* Actions */ + class Action1 : public ActionExt { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + SpeakerGameText _speakerGameText; + + Rect _rect1, _rect2; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + DisplayHotspot _hotspot3; + Hotspot4 _hotspot4; + DisplayHotspot _hotspot5, _hotspot6; + Hotspot7 _hotspot7; + DisplayHotspot _hotspot8, _hotspot9; + Hotspot10 _hotspot10; + DisplayHotspot _hotspot11; + SceneObject _hotspot12, _hotspot13, _hotspot14; + SceneArea _area1, _area2, _area3, _area4; + Action1 _action1; + Action2 _action2; + + Scene2150(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene2200 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public ActionExt { + public: + virtual void signal(); + virtual void process(Event &event); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot9 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SpeakerMText _speakerMText; + SpeakerSText _speakerSText; + SpeakerQText _speakerQText; + SpeakerSL _speakerSL; + SpeakerQR _speakerQR; + SpeakerQL _speakerQL; + SpeakerMR _speakerMR; + SpeakerGameText _speakerGameText; + Rect _exitRect; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + DisplayHotspot _hotspot1; + Hotspot3 _hotspot3; + Hotspot5 _hotspot5; + Hotspot9 _hotspot9; + DisplayHotspot _hotspot10; + SceneObject _hotspot2, _hotspot4; + SceneObject _hotspot6, _hotspot7, _hotspot8; + SoundHandler _soundHandler1, _soundHandler2; + + Scene2200(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void stripCallback(int v); + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene2222 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + +public: + SoundHandler _soundHandler; + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SpeakerQText _speakerQText; + SpeakerML _speakerML; + SpeakerSR _speakerSR; + Action1 _action1; + Action2 _action2; + SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene2230 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot11 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot12 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + Hotspot1 _hotspot1; + Hotspot3 _hotspot3; + Hotspot4 _hotspot4; + SceneObject _hotspot2; + Hotspot5 _hotspot5; + Hotspot6 _hotspot6; + Hotspot7 _hotspot7; + Hotspot8 _hotspot8; + DisplayHotspot _hotspot9; + Hotspot10 _hotspot10; + Hotspot11 _hotspot11; + Hotspot12 _hotspot12; + Rect _rect1; + int _field30A; + + Scene2230(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void dispatch(); +}; + +class Scene2280 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public ActionExt { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot12 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot15 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot16 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot17 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot18 : public SceneObject { + public: + virtual void doAction(int action); + }; + +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + Rect _exitRect; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + DisplayHotspot _hotspot3; + Hotspot4 _hotspot4; + DisplayHotspot _hotspot5, _hotspot6; + Hotspot7 _hotspot7; + Hotspot8 _hotspot8; + DisplayHotspot _hotspot9; + Hotspot10 _hotspot10; + DisplayHotspot _hotspot11; + Hotspot12 _hotspot12; + DisplayHotspot _hotspot13; + Hotspot14 _hotspot14; + DisplayHotspot _hotspot15, _hotspot16; + Hotspot17 _hotspot17; + Hotspot18 _hotspot18; + + Scene2280(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene2300 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public ActionExt { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot12 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot13 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler1, _soundHandler2; + SpeakerSL _speakerSL; + SpeakerML _speakerML; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4; + Hotspot5 _hotspot5; + Hotspot6 _hotspot6; + SceneObject _hotspot7, _hotspot8, _hotspot9, _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13, _hotspot14, _hotspot15; + + Scene2300(); + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene2310 : public Scene { +private: + int findObject(int objIndex); + + /* Custom classes */ + class ProtectionEntry { + public: + int _pageNumber; + int _connectionList[5]; + + void set(int pageNumber, int v1, int v2, int v3, int v4, int v5) { + _pageNumber = pageNumber; + _connectionList[0] = v1; _connectionList[1] = v2; _connectionList[2] = v3; + _connectionList[3] = v4; _connectionList[4] = v5; + } + }; + +public: + SequenceManager _sequenceManager; + int _wireIndex, _pageIndex; + SceneObject _wireList[5]; + Rect _rectList[5]; + SceneText _sceneText; + ProtectionEntry _pageList[21]; + + Scene2310(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); +}; + +class Scene2320 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public ActionExt { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObjectExt { + public: + virtual void doAction(int action); + }; + class Hotspot11 : public SceneObjectExt { + public: + virtual void doAction(int action); + }; + class Hotspot12 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot15 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager1, _sequenceManager2; + SpeakerMText _speakerMText; + SpeakerMR _speakerMR; + SpeakerML _speakerML; + SpeakerQText _speakerQText; + SpeakerQL _speakerQL; + SpeakerQR _speakerQR; + SpeakerSAL _speakerSAL; + SpeakerSL _speakerSL; + SpeakerSR _speakerSR; + SpeakerSText _speakerSText; + SpeakerGameText _speakerGameText; + SceneArea _area1, _area2, _area3, _area4; + DisplayHotspot _hotspot1, _hotspot2, _hotspot3, _hotspot4; + Hotspot5 _hotspot5; + Hotspot6 _hotspot6; + SceneObject _hotspot7, _hotspot9; + Hotspot8 _hotspot8; + Hotspot10 _hotspot10; + Hotspot11 _hotspot11; + Hotspot12 _hotspot12; + DisplayHotspot _hotspot13; + Hotspot14 _hotspot14; + Hotspot15 _hotspot15; + SceneObject _hotspot16; + SceneItem *_hotspotPtr; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + + Scene2320(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void signal(); +}; + +class Scene2400 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + virtual void dispatch(); + }; +public: + Action1 _action1; + SceneObject _object; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes4.cpp b/engines/tsage/ringworld_scenes4.cpp new file mode 100644 index 0000000000..89feb223a1 --- /dev/null +++ b/engines/tsage/ringworld_scenes4.cpp @@ -0,0 +1,253 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "tsage/ringworld_scenes4.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 3500 - Ringworld Scan + * + *--------------------------------------------------------------------------*/ + +void Scene3500::Action1::signal() { + Scene3500 *scene = (Scene3500 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_stripManager.start(3500, this); + break; + case 2: + setDelay(3); + break; + case 3: + _globals->_sceneManager.changeScene(9999); + break; + } +} + +void Scene3500::Action2::signal() { + Scene3500 *scene = (Scene3500 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_stripManager.start(3501, this); + break; + case 2: + setDelay(3); + break; + case 3: + _globals->_sceneManager.changeScene(2012); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene3500::postInit(SceneObjectList *OwnerList) { + loadScene((_globals->_stripNum == 3600) ? 3600 : 3500); + Scene::postInit(); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerSText); + + _globals->_sceneManager._scene->_sceneBounds.contain(_globals->_sceneManager._scene->_backgroundBounds); + _globals->_sceneOffset.x = (_globals->_sceneManager._scene->_sceneBounds.top / 160) * 160; + + setAction((_globals->_stripNum == 3600) ? (Action *)&_action2 : (Action *)&_action1); +} + +/*-------------------------------------------------------------------------- + * Scene 3700 - Remote Viewer + * + *--------------------------------------------------------------------------*/ + +#define VIEW_FRAME_DELAY 10 + +Scene3700::Viewer::Viewer() { + _images1.setVisage(3705, 1); + _images2.setVisage(3705, 2); + + _frameList[0] = 1; + for (int idx = 1; idx <= 3; ++idx) + _frameList[idx] = _globals->_randomSource.getRandomNumber(4) + 1; + + _active = true; + _countdownCtr = 0; + _percentList[0] = 120; + _percentList[1] = 50; + _percentList[2] = 75; + _percentList[3] = 114; +} + +void Scene3700::Viewer::synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsByte(_active); + s.syncAsSint16LE(_countdownCtr); + for (int idx = 0; idx < 4; ++idx) { + s.syncAsSint16LE(_frameList[idx]); + s.syncAsSint16LE(_percentList[idx]); + } +} + +void Scene3700::Viewer::dispatch() { + if (_active) { + if (_countdownCtr-- <= 0) { + _countdownCtr = VIEW_FRAME_DELAY; + + for (int idx = 3; idx > 1; --idx) + _frameList[idx] = _frameList[idx - 1]; + + int newFrame; + do { + newFrame = _globals->_randomSource.getRandomNumber(4) + 1; + } while (newFrame == _frameList[2]); + + _frameList[1] = newFrame; + _flags |= OBJFLAG_PANES; + } + } +} + +void Scene3700::Viewer::reposition() { + _bounds = Rect(123, 40, 285, 123); +} + +void Scene3700::Viewer::draw() { + Region *priorityRegion = _globals->_sceneManager._scene->_priorities.find(1); + + for (int idx = 0; idx < 4; ++idx) { + Visage &v = (idx == 0) ? _images1 : _images2; + + GfxSurface img = v.getFrame(_frameList[idx]); + Rect destRect = img.getBounds(); + destRect.resize(img, (_position.x - _globals->_sceneOffset.x), + (_position.y - _globals->_sceneOffset.y - _yDiff), _percentList[idx]); + + destRect.translate(-_globals->_sceneManager._scene->_sceneBounds.left, + -_globals->_sceneManager._scene->_sceneBounds.top); + + _globals->gfxManager().copyFrom(img, destRect, priorityRegion); + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene3700::Action1::signal() { + Scene3700 *scene = (Scene3700 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_stripManager.start(2162, this); + break; + case 2: + scene->_viewer._active = false; + setDelay(90); + break; + case 3: + scene->_soundHandler.startSound(196); + scene->_viewer.hide(); + + scene->_hotspot1.postInit(); + scene->_hotspot1.setVisage(3710); + scene->_hotspot1.setStrip(1); + scene->_hotspot1.setFrame(1); + scene->_hotspot1.setPosition(Common::Point(204, 120)); + + setDelay(90); + break; + case 4: + scene->_soundHandler.startSound(197); + scene->_hotspot1.hide(); + + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(3710); + scene->_hotspot2.setStrip(2); + scene->_hotspot2.setFrame(1); + scene->_hotspot2.setPosition(Common::Point(204, 120)); + + setDelay(30); + break; + case 5: + scene->_soundHandler.startSound(198); + scene->_hotspot2.hide(); + scene->_hotspot1.show(); + setDelay(90); + break; + case 6: + scene->_stripManager.start(2166, this); + break; + case 7: + setDelay(60); + break; + case 8: + scene->_hotspot1.remove(); + scene->_hotspot2.show(); + _globals->setFlag(59); + setDelay(30); + break; + case 9: + _globals->_sceneManager.changeScene(2100); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene3700::postInit(tSage::SceneObjectList *OwnerList) { + Scene::postInit(); + loadScene(3700); + + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerMR); + _speakerSText.setTextPos(Common::Point(20, 15)); + _speakerMText.setTextPos(Common::Point(20, 15)); + + _viewer.postInit(); + _viewer.setVisage(3705); + _viewer.setStrip(1); + _viewer.setFrame(2); + _viewer.setPosition(Common::Point(195, 83)); + + setAction(&_action1); + _globals->_soundHandler.startSound(195); +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes4.h b/engines/tsage/ringworld_scenes4.h new file mode 100644 index 0000000000..f5dac297fc --- /dev/null +++ b/engines/tsage/ringworld_scenes4.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES4_H +#define TSAGE_RINGWORLD_SCENES4_H + +#include "common/scummsys.h" +#include "tsage/core.h" +#include "tsage/converse.h" +#include "tsage/ringworld_logic.h" + +namespace tSage { + +class Scene3500 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; +public: + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SpeakerQText _speakerQText; + Action1 _action1; + Action2 _action2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene3700 : public Scene { + /* Custom classes */ + class Viewer : public SceneObject { + public: + Visage _images1; + Visage _images2; + + int _frameList[4]; + int _percentList[4]; + bool _active; + int _countdownCtr; + + Viewer(); + virtual Common::String getClassName() { return "Viewer"; } + virtual void synchronise(Serialiser &s); + virtual void dispatch(); + virtual void reposition(); + virtual void draw(); + }; + + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; +public: + Viewer _viewer; + Action1 _action1; + SceneObject _hotspot1, _hotspot2; + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SpeakerMR _speakerMR; + SoundHandler _soundHandler; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes5.cpp b/engines/tsage/ringworld_scenes5.cpp new file mode 100644 index 0000000000..de29a1cefc --- /dev/null +++ b/engines/tsage/ringworld_scenes5.cpp @@ -0,0 +1,4356 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "tsage/ringworld_scenes5.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 4000 - Village + * + *--------------------------------------------------------------------------*/ + +void Scene4000::Action1::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + scene->_hotspot5.postInit(); + scene->_hotspot5.setVisage(2870); + scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot5.animate(ANIM_MODE_1, NULL); + scene->_hotspot5.setPosition(Common::Point(116, 160)); + + ADD_PLAYER_MOVER_NULL(scene->_hotspot5, 208, 169); + + _globals->_inventory._ale._sceneNumber = 0; + _globals->clearFlag(42); + _globals->clearFlag(36); + _globals->clearFlag(43); + _globals->clearFlag(37); + break; + } + case 1: { + scene->_hotspot9.postInit(); + scene->_hotspot9.setVisage(4001); + scene->_hotspot9.animate(ANIM_MODE_1, NULL); + scene->_hotspot9.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot9.setPosition(Common::Point(314, 132)); + + ADD_PLAYER_MOVER_NULL(scene->_hotspot9, 288, 167); + + scene->_hotspot4.postInit(); + scene->_hotspot4.setVisage(4006); + scene->_hotspot4.animate(ANIM_MODE_1, NULL); + scene->_hotspot4.setStrip(1); + scene->_hotspot4.setPosition(Common::Point(207, 136)); + + ADD_PLAYER_MOVER_NULL(scene->_hotspot4, 220, 151); + + scene->_hotspot7.postInit(); + scene->_hotspot7.setVisage(2701); + scene->_hotspot7.animate(ANIM_MODE_1, NULL); + scene->_hotspot7.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot7._moveDiff = Common::Point(4, 2); + scene->_hotspot7.setPosition(Common::Point(300, 135)); + + ADD_PLAYER_MOVER_NULL(_globals->_player, 266, 169); + break; + } + case 2: + scene->_stripManager.start(4400, this); + break; + case 3: { + Common::Point pt1(30, 86); + PlayerMover *mover1 = new PlayerMover(); + scene->_hotspot7.addMover(mover1, &pt1, this); + + ADD_PLAYER_MOVER_NULL(scene->_hotspot5, 3, 86); + break; + } + case 4: + ADD_MOVER(scene->_hotspot7, -30, 86); + ADD_MOVER(scene->_hotspot5, -40, 86); + break; + case 5: + _globals->_soundHandler.startSound(155); + _globals->setFlag(43); + _globals->setFlag(114); + scene->_stripManager.start(4430, this); + break; + case 6: + ADD_PLAYER_MOVER_THIS(scene->_hotspot4, 277, 175); + ADD_PLAYER_MOVER_NULL(_globals->_player, 258, 187); + break; + case 7: + scene->_stripManager.start(4440, this); + break; + case 8: + setDelay(30); + break; + case 9: + _globals->setFlag(96); + _globals->_sceneManager.changeScene(4025); + break; + } +} + +void Scene4000::Action2::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL); + + scene->_hotspot5.postInit(); + scene->_hotspot5.setVisage(2801); + scene->_hotspot5.animate(ANIM_MODE_1, NULL); + scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot5._moveDiff.x = 5; + scene->_hotspot5.setPosition(Common::Point(-8, 88)); + + scene->_hotspot3.setAction(&scene->_sequenceManager3, NULL, 4003, &scene->_hotspot5, NULL); + scene->_hotspot7.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_hotspot7, NULL); + break; + case 1: + _globals->_player.disableControl(); + + scene->_hotspot3.remove(); + ADD_MOVER(scene->_hotspot9, scene->_hotspot5._position.x + 30, scene->_hotspot5._position.y - 10); + break; + case 2: + _globals->_player.checkAngle(&scene->_hotspot9); + scene->_hotspot5.checkAngle(&scene->_hotspot9); + scene->_hotspot7.checkAngle(&scene->_hotspot9); + scene->_stripManager.start(4000, this); + break; + case 3: + scene->_hotspot2.setVisage(4017); + scene->_hotspot2.animate(ANIM_MODE_1, NULL); + scene->_hotspot2.setStrip(2); + + ADD_MOVER(scene->_hotspot2, 116, 160); + ADD_MOVER(scene->_hotspot5, 116, 160); + + _globals->setFlag(37); + break; + case 4: + break; + case 5: + scene->_stripManager.start(4010, this); + break; + case 6: + ADD_PLAYER_MOVER_NULL(scene->_hotspot9, 230, 149); + ADD_PLAYER_MOVER(210, 136); + ADD_PLAYER_MOVER_NULL(scene->_hotspot7, 210, 133); + break; + case 7: + _globals->_sceneManager.changeScene(4045); + break; + } +} + +void Scene4000::Action3::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_hotspot8.setVisage(4017); + scene->_hotspot8.setFrame2(-1); + scene->_hotspot8.animate(ANIM_MODE_1, NULL); + scene->_hotspot8.setObjectWrapper(new SceneObjectWrapper()); + ADD_MOVER(scene->_hotspot8, 118, 145); + break; + case 1: + scene->_hotspot8.remove(); + remove(); + break; + } +} + +void Scene4000::Action4::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player._uiEnabled = false; + ADD_MOVER(_globals->_player, 257, 57); + break; + case 1: + _globals->_player.setVisage(4000); + _globals->_player.setPosition(Common::Point(258, 83)); + _globals->_player._frame = 1; + _globals->_player._strip = 3; + _globals->_player.animate(ANIM_MODE_4, 2, 1, this); + break; + case 2: + scene->_hotspot6.postInit(); + scene->_hotspot6.setVisage(4000); + scene->_hotspot6.setStrip(7); + scene->_hotspot6.setFrame(3); + scene->_hotspot6.setPosition(Common::Point(268, 44)); + + _globals->_inventory._rope._sceneNumber = 4000; + _globals->_events.setCursor(CURSOR_USE); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player.setVisage(2602); + _globals->_player.setPosition(Common::Point(257, 57)); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._uiEnabled = true; + + _globals->setFlag(41); + remove(); + break; + } +} + +void Scene4000::Action5::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(15); + break; + case 1: + scene->_stripManager.start(_globals->_stripNum, this); + break; + case 2: + setDelay(10); + break; + case 3: + scene->_hotspot8.setVisage(4017); + scene->_hotspot8.animate(ANIM_MODE_1, NULL); + scene->_hotspot8.setFrame2(-1); + scene->_hotspot8.setAction(&scene->_action3); + + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4000::Action6::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(30); + break; + case 1: + setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL); + + if (!_globals->getFlag(36)) + scene->_hotspot7.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_hotspot7, NULL); + break; + case 2: + _globals->_player.disableControl(); + ADD_MOVER(scene->_hotspot9, _globals->_player._position.x + 30, _globals->_player._position.y - 5); + break; + case 3: + scene->_stripManager.start(_globals->getFlag(35) ? 4500 : 4502, this); + break; + case 4: + _globals->clearFlag(35); + ADD_MOVER_NULL(scene->_hotspot9, 292, 138); + ADD_PLAYER_MOVER(283, 147); + + if (!_globals->getFlag(36)) { + ADD_PLAYER_MOVER_NULL(scene->_hotspot7, 280, 150); + } + break; + case 5: + _globals->_sceneManager.changeScene(4100); + break; + } +} + +void Scene4000::Action7::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + + scene->_hotspot6.setFrame(1); + ADD_MOVER(_globals->_player, 247, 53); + break; + case 1: + _globals->_player.setVisage(4008); + _globals->_player.setStrip(4); + _globals->_player.setFrame(1); + _globals->_player.setPriority2(16); + _globals->_player.setPosition(Common::Point(260, 55)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_sceneManager.changeScene(4050); + break; + } +} + +void Scene4000::Action8::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + if (_globals->getFlag(41)) + scene->_hotspot6.setFrame(2); + + ADD_MOVER(_globals->_player, 289, 53); + break; + case 1: + _globals->_player.setVisage(4008); + _globals->_player.setStrip(5); + _globals->_player.setPriority(16); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(283, 52)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player.remove(); + setDelay(60); + break; + case 3: + _globals->_soundHandler.startSound(170); + scene->_hotspot27.setVisage(4000); + scene->_hotspot27.setStrip(6); + scene->_hotspot27.animate(ANIM_MODE_2, NULL); + setDelay(60); + break; + case 4: + _globals->_soundHandler.startSound(77, this); + break; + case 5: + _globals->_game.endGame(4000, 15); + remove(); + break; + } +} + +void Scene4000::Action9::signal() { + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(119) + 240); + break; + case 1: + static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_8, 1, this); + _actionIndex = 0; + break; + } +} + +void Scene4000::Action10::signal() { + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(119) + 240); + break; + case 1: + static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_8, 1, this); + _actionIndex = 0; + break; + } +} + +void Scene4000::Action11::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_MOVER(scene->_hotspot3, -30, 70); + break; + case 1: + setDelay(60); + break; + case 2: + scene->_hotspot5.postInit(); + scene->_hotspot5.setVisage(2801); + scene->_hotspot5.animate(ANIM_MODE_1, NULL); + scene->_hotspot5.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot5._moveDiff.x = 4; + scene->_hotspot5.setPosition(Common::Point(-8, 88)); + + setAction(&scene->_sequenceManager1, this, 4001, &_globals->_player, NULL); + + scene->_hotspot7.setPosition(Common::Point(-210, 139)); + scene->_hotspot7.setAction(&scene->_sequenceManager2, NULL, 4002, &scene->_hotspot7, NULL); + scene->_hotspot3.setAction(&scene->_sequenceManager3, NULL, 4003, &scene->_hotspot5, NULL); + break; + case 3: + scene->_stripManager.start(8000, this); + break; + case 4: + ADD_MOVER(scene->_hotspot4, 263, 187); + scene->_hotspot4.animate(ANIM_MODE_1, NULL); + break; + case 5: + scene->_soundHandler1.proc3(); + scene->_hotspot11.remove(); + + ADD_MOVER(_globals->_player, 340, 163); + ADD_MOVER_NULL(scene->_hotspot7, 340, 169); + ADD_MOVER_NULL(scene->_hotspot5, 340, 165); + break; + case 6: + _globals->_sceneManager.changeScene(4250); + break; + } +} + +void Scene4000::Action12::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(5); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(4015, this); + break; + case 2: + _globals->setFlag(32); + if (scene->_stripManager._field2E8 == 275) { + _globals->setFlag(82); + ADD_MOVER_NULL(scene->_hotspot9, 292, 138); + ADD_PLAYER_MOVER(283, 147); + } else { + setDelay(30); + } + break; + case 3: + if (scene->_stripManager._field2E8 == 275) { + _globals->_sceneManager.changeScene(4100); + } else { + ADD_PLAYER_MOVER_THIS(scene->_hotspot9, 300, 132); + } + break; + case 4: + scene->_hotspot9.hide(); + scene->_stripManager.start(4020, this); + break; + case 5: + _globals->setFlag(35); + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4000::Action13::signal() { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + scene->_soundHandler2.startSound(151); + scene->_soundHandler2.proc5(true); + ADD_MOVER(scene->_hotspot3, -30, 70); + break; + case 2: + scene->_soundHandler2.proc4(); + _globals->_sceneManager.changeScene(4010); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4000::Hotspot7::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(4000, 31); + break; + case CURSOR_LOOK: + SceneItem::display2(4000, 29); + break; + case CURSOR_TALK: + if (_globals->getFlag(31)) { + if (!_globals->getFlag(111)) { + _globals->setFlag(111); + _globals->_stripNum = 4070; + } else if (!_globals->getFlag(33)) + _globals->_stripNum = 4094; + else if (!_globals->getFlag(112)) { + _globals->setFlag(112); + _globals->_stripNum = 4300; + } else if (!_globals->getFlag(113)) { + _globals->setFlag(113); + _globals->_stripNum = 4093; + } else + _globals->_stripNum = 4094; + } else { + if (!_globals->getFlag(33)) + _globals->_stripNum = 4094; + else if (!_globals->getFlag(112)) { + _globals->setFlag(112); + _globals->_stripNum = 4300; + } else + _globals->_stripNum = 4094; + } + + scene->setAction(&scene->_action5); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot8::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(4000, 26); + break; + case CURSOR_LOOK: + SceneItem::display2(4000, 25); + break; + case CURSOR_TALK: + if (_globals->_inventory._peg._sceneNumber == 1) + SceneItem::display2(4000, 34); + else { + switch (_ctr) { + case 0: + _globals->_stripNum = 4090; + break; + case 1: + _globals->_stripNum = 4091; + break; + case 2: + _globals->_stripNum = 4092; + break; + default: + SceneItem::display2(4000, 34); + break; + } + + if (_globals->_stripNum) { + setAction(NULL); + addMover(NULL); + ++_ctr; + scene->setAction(&scene->_action5); + } + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot9::doAction(int action) { + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(4000, 28); + break; + case CURSOR_LOOK: + SceneItem::display2(4000, 27); + break; + case CURSOR_TALK: + error("*** Do we need dialog."); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot10::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 30); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + if (_globals->getFlag(40)) { + scene->_sceneMode = 4005; + scene->setAction(&scene->_sequenceManager1, scene, 4005, &_globals->_player, NULL); + } else { + scene->_sceneMode = 4004; + scene->setAction(&scene->_sequenceManager1, scene, 4004, &_globals->_player, &scene->_hotspot10, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot12::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 13); + break; + case OBJECT_SCANNER: + SceneItem::display2(4000, 19); + break; + case OBJECT_STUNNER: + SceneItem::display2(4000, 20); + break; + case CURSOR_USE: + if (_globals->getFlag(40)) + SceneItem::display2(4000, 37); + else { + _globals->_player.disableControl(); + if (_globals->_sceneObjects->contains(&scene->_hotspot7)) + _globals->clearFlag(96); + + scene->_sceneMode = 4012; + scene->setAction(&scene->_sequenceManager1, scene, 4012, &_globals->_player, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot13::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 21); + break; + case OBJECT_ROPE: + if (_globals->getFlag(40)) + scene->setAction(&scene->_action4); + else + SceneItem::display2(4000, 22); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 16); + break; + case OBJECT_SCANNER: + SceneItem::display2(4000, 17); + break; + case OBJECT_STUNNER: + SceneItem::display2(4000, 18); + break; + case OBJECT_LADDER: + _globals->_player.disableControl(); + + scene->_hotspot10.postInit(); + scene->_hotspot10.setVisage(4000); + scene->_hotspot10.setStrip(5); + scene->_hotspot10.setPosition(Common::Point(245, 147)); + scene->_hotspot10.hide(); + _globals->_sceneItems.push_front(&scene->_hotspot10); + + if (_globals->_sceneObjects->contains(&scene->_hotspot8)) { + scene->_hotspot8.setAction(NULL); + ADD_MOVER_NULL(scene->_hotspot8, 118, 145); + } + + scene->_sceneMode = 4004; + scene->setAction(&scene->_sequenceManager1, scene, 4011, &_globals->_player, &scene->_hotspot10, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot17::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 23); + break; + case CURSOR_USE: + if (_globals->getFlag(40)) + scene->setAction(&scene->_action7); + else + SceneItem::display2(4000, 24); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot18::doAction(int action) { + Scene4000 *scene = (Scene4000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, 36); + break; + case CURSOR_USE: + if (_globals->getFlag(40)) + scene->setAction(&scene->_action8); + else + SceneItem::display2(4000, 24); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4000::Hotspot23::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4000, _globals->getFlag(31) ? 10 : 9); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4000::Scene4000() : + _hotspot11(0, CURSOR_LOOK, 4000, 14, CURSOR_USE, 4000, 32, OBJECT_STUNNER, 4000, 33, + OBJECT_SCANNER, 4000, 19, LIST_END), + _hotspot19(0, CURSOR_LOOK, 4000, 7, LIST_END), + _hotspot20(0, CURSOR_LOOK, 4000, 3, LIST_END), + _hotspot21(0, CURSOR_LOOK, 4000, 1, LIST_END), + _hotspot22(0, CURSOR_LOOK, 4000, 8, LIST_END), + _hotspot24(0, CURSOR_LOOK, 4000, 11, LIST_END), + _hotspot25(0, CURSOR_LOOK, 4000, 4, LIST_END), + _hotspot26(0, CURSOR_LOOK, 4000, 0, LIST_END) { +} + +void Scene4000::postInit(SceneObjectList *OwnerList) { + loadScene(4000); + Scene::postInit(); + setZoomPercents(0, 20, 70, 50); + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerML); + _stripManager.addSpeaker(&_speakerMR); + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerCHFL); + _stripManager.addSpeaker(&_speakerPL); + _stripManager.addSpeaker(&_speakerPText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerCHFR); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerCHFText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerMText); + + _speakerCHFText._npc = &_hotspot9; + _speakerSText._npc = &_hotspot5; + _speakerMText._npc = &_hotspot7; + _speakerPText._npc = &_hotspot4; + _speakerQText._npc = &_globals->_player; + + _hotspot13.setBounds(Rect(263, 41, 278, 55)); + _hotspot14.setBounds(Rect(140, 177, 140 /*96*/, 204)); + _hotspot15.setBounds(Rect(227, 101, 264, 143)); + _hotspot16.setBounds(Rect(306, 100, 319, 148)); + _hotspot17.setBounds(Rect(231, 53, 254, 60)); + _hotspot18.setBounds(Rect(285, 51, 310, 60)); + _hotspot26.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot21.setBounds(Rect(28, 7, 53, 64)); + _hotspot22.setBounds(Rect(125, 155, 140, 189)); + _hotspot23.setBounds(Rect(205, 102, 220, 142)); + _hotspot24.setBounds(Rect(270, 111, 297, 147)); + + _hotspot19._sceneRegionId = 16; + _hotspot20._sceneRegionId = 18; + _hotspot25._sceneRegionId = 17; + + _hotspot1.postInit(); + _hotspot1.setVisage(4000); + _hotspot1.setPriority2(1); + _hotspot1.setFrame(2); + _hotspot1.setPosition(Common::Point(242, 59)); + _hotspot1.animate(ANIM_MODE_2, NULL); + + _hotspot27.postInit(); + _hotspot27.setVisage(4000); + _hotspot27.setStrip(2); + _hotspot27.setPriority2(1); + _hotspot27.setFrame(2); + _hotspot27.setPosition(Common::Point(299, 59)); + _hotspot27.animate(ANIM_MODE_2, NULL); + + if (_globals->_inventory._ladder._sceneNumber != 4000) { + _hotspot8.postInit(); + _hotspot8.setVisage(4018); + _hotspot8.setObjectWrapper(new SceneObjectWrapper()); + _hotspot8._strip = 2; + _hotspot8._numFrames = 5; + _hotspot8.setPosition(Common::Point(306, 154)); + _hotspot8.setAction(&_action9); + } + + _hotspot12.postInit(); + _hotspot12.setVisage(4000); + _hotspot12.setStrip(3); + _hotspot12.setFrame(3); + _hotspot12.setPriority2(200); + _hotspot12.setPosition(Common::Point(281, 176)); + + if (_globals->getFlag(34)) { + _soundHandler1.startSound(156); + + _hotspot11.postInit(); + _hotspot11.setVisage(4000); + _hotspot11.setStrip(4); + _hotspot11.setPosition(Common::Point(312, 174)); + _hotspot11.setPriority2(200); + _hotspot11.animate(ANIM_MODE_8, 0, NULL); + + _globals->_sceneItems.push_back(&_hotspot11); + } + + _globals->_player.postInit(); + _globals->_player.setVisage(2602); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(-28, 86)); + + if (!_globals->getFlag(36) && !_globals->getFlag(43)) { + _hotspot7.postInit(); + _hotspot7.setVisage(2701); + _hotspot7.animate(ANIM_MODE_1, NULL); + _hotspot7.setObjectWrapper(new SceneObjectWrapper()); + _hotspot7._moveDiff = Common::Point(4, 2); + _hotspot7.setPosition(Common::Point(-210, 139)); + + _globals->_sceneItems.push_back(&_hotspot7); + } + + switch (_globals->_sceneManager._previousScene) { + case 2320: + _globals->_soundHandler.startSound(155); + + if (_globals->_inventory._ale._sceneNumber == 1) { + _hotspot9.postInit(); + _hotspot9.setVisage(4001); + _hotspot9.animate(ANIM_MODE_1, NULL); + _hotspot9.setObjectWrapper(new SceneObjectWrapper()); + _hotspot9.setPosition(Common::Point(314, 132)); + + setAction(&_action6); + } else { + _globals->_player.disableControl(); + _sceneMode = 4001; + setAction(&_sequenceManager1, this, 4001, &_globals->_player, NULL); + + if (!_globals->getFlag(36) && !_globals->getFlag(43)) + _hotspot7.setAction(&_sequenceManager2, NULL, 4002, &_hotspot7, NULL); + } + + if (_globals->getFlag(42)) + _hotspot8.setAction(&_action3); + else if (_globals->getFlag(91)) + _hotspot8.remove(); + break; + + case 4010: + _hotspot7.setPosition(Common::Point(-210, 139)); + + _hotspot9.postInit(); + _hotspot9.setVisage(4001); + _hotspot9.animate(ANIM_MODE_1, NULL); + _hotspot9.setObjectWrapper(new SceneObjectWrapper()); + _hotspot9.setPosition(Common::Point(314, 132)); + + _hotspot2.postInit(); + _hotspot2.setVisage(4018); + _hotspot2._strip = 1; + _hotspot2._numFrames = 5; + _hotspot2.setPosition(Common::Point(182, 146)); + _hotspot2.setAction(&_action10); + + setAction(&_action2); + break; + + case 4025: + if (_globals->_inventory._ladder._sceneNumber != 4000) + _hotspot8.remove(); + + _globals->_player.setPosition(Common::Point(260, 185)); + + if (!_globals->getFlag(36) && !_globals->getFlag(43)) + _hotspot7.setPosition(Common::Point(246, 146)); + + if (_globals->getFlag(96)) { + _hotspot4.postInit(); + _hotspot4.setVisage(4006); + _hotspot4.animate(ANIM_MODE_1, NULL); + _hotspot4.setObjectWrapper(new SceneObjectWrapper()); + _hotspot4.setPosition(Common::Point(290, 163)); + } + + if (_globals->_stripNum == 4025) { + _soundHandler1.startSound(182); + _hotspot11.remove(); + + _hotspot5.postInit(); + _hotspot5.setVisage(2801); + _hotspot5.animate(ANIM_MODE_1, NULL); + _hotspot5.setObjectWrapper(new SceneObjectWrapper()); + _hotspot5._moveDiff.x = 4; + _hotspot5.setPosition(Common::Point(-18, 86)); + + _globals->_player.disableControl(); + + if (!_globals->getFlag(96)) { + _hotspot4.postInit(); + _hotspot4.setVisage(4006); + _hotspot4.animate(ANIM_MODE_1, NULL); + _hotspot4.setObjectWrapper(new SceneObjectWrapper()); + _hotspot4.setPosition(Common::Point(195, 128)); + + Common::Point pt(268, 157); + PlayerMover *mover = new PlayerMover(); + _hotspot4.addMover(mover, &pt, NULL); + } + + _sceneMode = 4003; + setAction(&_sequenceManager1, this, 4003, &_hotspot5, NULL); + } else if (_globals->getFlag(96)) { + _globals->_player.disableControl(); + _sceneMode = 4013; + setAction(&_sequenceManager1, this, 4013, &_hotspot4, NULL); + } + + _globals->clearFlag(96); + break; + + case 4045: + _globals->_player.enableControl(); + + if (_globals->_inventory._ladder._sceneNumber != 4000) { + _hotspot8.postInit(); + _hotspot8.setVisage(4017); + _hotspot8.animate(ANIM_MODE_1, NULL); + _hotspot8.setPosition(Common::Point(199, 188)); + _hotspot8.setAction(&_action3); + } + + _globals->_player.setPosition(Common::Point(208, 153)); + if (!_globals->getFlag(36) && !_globals->getFlag(43)) + _hotspot7.setPosition(Common::Point(246, 146)); + + if (_globals->getFlag(39)) { + _globals->clearFlag(39); + + _hotspot4.postInit(); + _hotspot4.setVisage(4006); + _hotspot4.animate(ANIM_MODE_1, NULL); + _hotspot4.setObjectWrapper(new SceneObjectWrapper()); + _hotspot4.setPosition(Common::Point(219, 150)); + + _globals->_player.disableControl(); + setAction(&_sequenceManager1, this, 4010, &_globals->_player, NULL); + } + + if (_globals->_stripNum == 4000) { + _globals->_stripNum = 0; + + _hotspot9.postInit(); + _hotspot9.setVisage(4001); + _hotspot9.animate(ANIM_MODE_1, NULL); + _hotspot9.setObjectWrapper(new SceneObjectWrapper()); + _hotspot9.setPosition(Common::Point(231, 159)); + _hotspot9.setStrip(4); + + setAction(&_action12); + } + break; + + case 4050: + _globals->_soundHandler.startSound(155); + _globals->_player.disableControl(); + + if (_globals->_stripNum == 4050) { + _globals->_player.setVisage(4008); + _globals->_player.setStrip(4); + _globals->_player.setFrame(_globals->_player.getFrameCount()); + _globals->_player.setPriority2(16); + _globals->_player.setPosition(Common::Point(260, 55)); + + _sceneMode = 4007; + setAction(&_sequenceManager1, this, 4007, &_globals->_player, NULL); + } else { + _globals->_player.setPosition(Common::Point(208, 153)); + _globals->_player.enableControl(); + } + + if (_globals->_inventory._ladder._sceneNumber != 4000) + _hotspot8.remove(); + break; + + case 4100: + _globals->_player.enableControl(); + _globals->_player.setPosition(Common::Point(270, 155)); + + if (_globals->getFlag(42) && (_globals->_inventory._ladder._sceneNumber != 4000)) { + _hotspot8.setVisage(4017); + _hotspot8.animate(ANIM_MODE_1, NULL); + _hotspot8.setPosition(Common::Point(244, 151)); + _hotspot8.setAction(&_action3); + } + + if (!_globals->getFlag(36) && !_globals->getFlag(43)) + _hotspot7.setPosition(Common::Point(246, 146)); + break; + + default: + _globals->_soundHandler.startSound(155); + + _hotspot3.postInit(); + _hotspot3.setVisage(4002); + _hotspot3._moveDiff = Common::Point(10, 10); + _hotspot3.setPosition(Common::Point(-100, 80)); + _hotspot3.changeZoom(-1); + _hotspot3.setPosition(Common::Point(130, -1)); + _hotspot3.animate(ANIM_MODE_2, NULL); + + if (_globals->_stripNum == 9000) { + _hotspot4.postInit(); + _hotspot4.setVisage(4006); + _hotspot4.setPosition(Common::Point(235, 153)); + + _hotspot9.postInit(); + _hotspot9.setVisage(4001); + _hotspot9.setStrip(3); + _hotspot9.setPosition(Common::Point(255, 153)); + + setAction(&_action11); + _globals->_inventory._ladder._sceneNumber = 4100; + _globals->_inventory._rope._sceneNumber = 4150; + + _soundHandler1.startSound(156); + + _hotspot11.postInit(); + _hotspot11.setVisage(4000); + _hotspot11.setStrip(4); + _hotspot11.setPosition(Common::Point(312, 174)); + _hotspot11.setPriority2(200); + _hotspot11.animate(ANIM_MODE_8, 0, NULL); + } else { + if (!_globals->getFlag(37)) { + _hotspot2.postInit(); + _hotspot2.setVisage(4018); + _hotspot2._strip = 1; + _hotspot2._numFrames = 5; + _hotspot2.setPosition(Common::Point(182, 146)); + _hotspot2.setAction(&_action10); + } + + _hotspot7.setPosition(Common::Point(-210, 139)); + setAction(&_action13); + } + break; + } + + if (_globals->_inventory._ladder._sceneNumber == 4000) { + _hotspot10.postInit(); + _hotspot10.setVisage(4000); + _hotspot10.setStrip(5); + _hotspot10.setPosition(Common::Point(245, 147)); + + _globals->_sceneItems.push_back(&_hotspot10); + } + + if (_globals->_inventory._rope._sceneNumber == 4000) { + _hotspot6.postInit(); + _hotspot6.setVisage(4000); + _hotspot6.setStrip(7); + _hotspot6.setPriority2(1); + _hotspot6.setPosition(Common::Point(268, 44)); + } + + _globals->_sceneItems.addItems(&_hotspot8, &_hotspot17, &_hotspot18, &_hotspot14, &_hotspot15, + &_hotspot16, &_hotspot12, &_hotspot13, &_hotspot21, &_hotspot20, &_hotspot22, &_hotspot23, + &_hotspot24, &_hotspot25, &_hotspot19, &_hotspot26, NULL); +} + +void Scene4000::signal() { + switch (_sceneMode) { + case 4001: + _globals->_player.enableControl(); + break; + case 4002: + case 4011: + break; + case 4003: + _sceneMode = 4014; + setAction(&_sequenceManager1, this, 4014, &_globals->_player, &_hotspot5, NULL); + break; + case 4004: + _globals->_inventory._ladder._sceneNumber = 4000; + // Deliberate fall-through + case 4007: + _globals->_events.setCursor(CURSOR_USE); + _globals->setFlag(40); + break; + case 4005: + _globals->_player.enableControl(); + _globals->_events.setCursor(CURSOR_WALK); + _globals->clearFlag(40); + break; + case 4006: + _globals->_sceneManager.changeScene(4045); + break; + case 4008: + _globals->_sceneManager.changeScene(2320); + break; + case 4009: + _globals->_sceneManager.changeScene(2200); + break; + case 4010: + _globals->setFlag(38); + _hotspot4.remove(); + break; + case 4012: + _globals->_player.checkAngle(&_hotspot12); + _globals->_sceneManager.changeScene(4025); + break; + case 4013: + _globals->_player.enableControl(); + _hotspot4.remove(); + break; + case 4014: + _globals->_sceneManager.changeScene(4250); + break; + case 4015: + ADD_MOVER_NULL(_hotspot7, 0, _hotspot7._position.y - 5); + break; + } +} + +void Scene4000::dispatch() { + Scene::dispatch(); + + if ((_globals->_player.getRegionIndex() == 10) || (_globals->_player.getRegionIndex() == 6)) + _globals->_player.setPriority2(200); + if (_globals->_player.getRegionIndex() == 11) + _globals->_player.setPriority2(-1); + if (_globals->_player.getRegionIndex() == 5) + _globals->_player.setPriority2(94); + + if (_globals->_sceneObjects->contains(&_hotspot5)) { + if ((_hotspot5.getRegionIndex() == 10) || (_hotspot5.getRegionIndex() == 6)) + _hotspot5.setPriority2(200); + if (_hotspot5.getRegionIndex() == 11) + _hotspot5.setPriority2(-1); + if (_hotspot5.getRegionIndex() == 5) + _hotspot5.setPriority2(94); + } + + if (_globals->_sceneObjects->contains(&_hotspot7)) { + if (!_hotspot7._mover) + _hotspot7.checkAngle(&_globals->_player); + if (!_action && _globals->_player.getRegionIndex() == 23) { + ADD_MOVER_NULL(_hotspot7, 204, 186); + } + + if ((_hotspot7.getRegionIndex() == 10) || (_hotspot7.getRegionIndex() == 6)) + _hotspot7.setPriority2(200); + if (_hotspot7.getRegionIndex() == 11) + _hotspot7.setPriority2(-1); + if (_hotspot7.getRegionIndex() == 5) + _hotspot7.setPriority2(94); + } + + if (!_action) { + if ((_globals->_inventory._peg._sceneNumber == 1) && _globals->getFlag(34) && + _globals->getFlag(37) && !_globals->getFlag(40)) { + _globals->_player.disableControl(); + _soundHandler1.startSound(177); + _globals->_soundHandler.startSound(178); + + setAction(&_action1); + } + + if (_globals->_player.getRegionIndex() == 2) + _globals->_sceneManager.changeScene(4045); + if (_globals->_player.getRegionIndex() == 15) + _globals->_sceneManager.changeScene(4100); + + if ((_globals->_player._position.x > 5) && (_globals->_player._position.y < 100)) { + _globals->_player.disableControl(); + + if (!_globals->_sceneObjects->contains(&_hotspot7) || (_hotspot7._position.y <= 100)) { + _sceneMode = 4008; + setAction(&_sequenceManager1, this, 4008, &_globals->_player, NULL); + } else { + _sceneMode = 4015; + _globals->_player.addMover(NULL); + setAction(&_sequenceManager1, this, 4015, &_globals->_player, &_hotspot7, NULL); + } + } + } +} + +/*-------------------------------------------------------------------------- + * Scene 4010 - Village - Outside Lander + * + *--------------------------------------------------------------------------*/ + +void Scene4010::postInit(SceneObjectList *OwnerList) { + loadScene(4010); + Scene::postInit(); + setZoomPercents(0, 20, 70, 50); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerMText); + _speakerSText._npc = &_hotspot1; + _speakerMText._npc = &_hotspot2; + _speakerQText._npc = &_globals->_player; + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(-38, 175)); + _globals->_player.changeZoom(75); + + _hotspot2.postInit(); + _hotspot2.setVisage(2705); + _hotspot2.animate(ANIM_MODE_1, NULL); + _hotspot2.setObjectWrapper(new SceneObjectWrapper()); + _hotspot2._moveDiff = Common::Point(4, 2); + _hotspot2.setPosition(Common::Point(-50, 185)); + _hotspot2.changeZoom(75); + + _hotspot1.postInit(); + _hotspot1.setVisage(2806); + _hotspot1.setPosition(Common::Point(-20, 175)); + _hotspot1.changeZoom(75); + _hotspot1.animate(ANIM_MODE_1, NULL); + _hotspot1.setObjectWrapper(new SceneObjectWrapper()); + + _globals->_player.disableControl(); + setAction(&_sequenceManager, this, 4017, &_globals->_player, &_hotspot1, &_hotspot2, NULL); +} + +void Scene4010::signal() { + _globals->_sceneManager.changeScene(4000); +} + +/*-------------------------------------------------------------------------- + * Scene 4025 - Village - Puzzle Board + * + *--------------------------------------------------------------------------*/ + +void Scene4025::Action1::signal() { + Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_armHotspot._strip = scene->_pegPtr->_armStrip; + scene->_armHotspot._frame = 4; + scene->_armHotspot.animate(ANIM_MODE_4, 2, -1, this); + + if (scene->_pegPtr->_armStrip > 3) { + if (scene->_hole1._armStrip == scene->_pegPtr->_armStrip) + scene->_hole1._pegPtr = NULL; + if (scene->_hole2._armStrip == scene->_pegPtr->_armStrip) + scene->_hole2._pegPtr = NULL; + if (scene->_hole3._armStrip == scene->_pegPtr->_armStrip) + scene->_hole3._pegPtr = NULL; + if (scene->_hole4._armStrip == scene->_pegPtr->_armStrip) + scene->_hole4._pegPtr = NULL; + if (scene->_hole5._armStrip == scene->_pegPtr->_armStrip) + scene->_hole5._pegPtr = NULL; + } + break; + case 1: + scene->_pegPtr->hide(); + + if (scene->_pegPtr2) { + if (scene->_pegPtr->_armStrip == 3) + scene->_pegPtr2->_strip = 2; + + scene->_pegPtr2->setPosition(scene->_pegPtr->_position); + scene->_pegPtr2->show(); + scene->_pegPtr2->_armStrip = scene->_pegPtr->_armStrip; + } + + scene->_pegPtr->_armStrip = 0; + scene->_pegPtr->setPosition(Common::Point(-10, -10)); + scene->_pegPtr2 = scene->_pegPtr; + scene->_armHotspot.animate(ANIM_MODE_5, this); + break; + + case 2: + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + remove(); + break; + } +} + +void Scene4025::Action2::signal() { + Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_armHotspot._strip = scene->_holePtr->_armStrip; + scene->_armHotspot.animate(ANIM_MODE_4, 2, -1, this); + break; + case 1: + if (!scene->_pegPtr2) { + // Getting a peg from a hole + scene->_holePtr->_pegPtr->hide(); + scene->_pegPtr = scene->_holePtr->_pegPtr; + scene->_pegPtr->_armStrip = 0; + scene->_pegPtr->setPosition(Common::Point(-10, -10)); + scene->_pegPtr2 = scene->_holePtr->_pegPtr; + scene->_holePtr->_pegPtr = NULL; + } else { + // Placing a peg into a hole + scene->_pegPtr2 = NULL; + if (scene->_holePtr->_pegPtr) { + scene->_holePtr->_pegPtr->hide(); + scene->_pegPtr2 = scene->_holePtr->_pegPtr; + } + + assert(scene->_pegPtr); + scene->_pegPtr->setPosition(scene->_holePtr->_newPosition); + scene->_pegPtr->setStrip(1); + scene->_pegPtr->show(); + scene->_pegPtr->_armStrip = scene->_holePtr->_armStrip; + + scene->_holePtr->_pegPtr = scene->_pegPtr; + scene->_pegPtr = scene->_pegPtr2; + } + scene->_armHotspot.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player._uiEnabled = true; + _globals->_events.setCursor(CURSOR_USE); + remove(); + break; + } +} + +void Scene4025::Action3::signal() { + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + _globals->_scenePalette.addRotation(64, 111, -1); + setDelay(120); + break; + case 1: + _globals->clearFlag(34); + _globals->_stripNum = 4025; + _globals->_sceneManager.changeScene(4000); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4025::Hole::synchronise(Serialiser &s) { + SceneObject::synchronise(s); + SYNC_POINTER(_pegPtr); + s.syncAsSint16LE(_armStrip); + s.syncAsSint16LE(_newPosition.x); + s.syncAsSint16LE(_newPosition.y); +} + +void Scene4025::Hole::doAction(int action) { + Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4025, 3); + break; + case CURSOR_USE: + if (!scene->_pegPtr && !_pegPtr) { + setAction(&scene->_sequenceManager, scene, 4028, NULL); + } else { + _globals->_player.disableControl(); + scene->_holePtr = this; + scene->setAction(&scene->_action2); + } + break; + case OBJECT_PEG: + if (!scene->_pegPtr2) { + _globals->_player.disableControl(); + _globals->_events.setCursor(CURSOR_USE); + _globals->_inventory._peg._sceneNumber = 4025; + + scene->_pegPtr = &scene->_peg5; + scene->_holePtr = this; + scene->_pegPtr->_armStrip = 0; + scene->_pegPtr2 = scene->_pegPtr; + + scene->setAction(&scene->_action2); + } else { + scene->_sceneMode = 4027; + scene->setAction(&scene->_sequenceManager, scene, 4027, NULL); + } + break; + } +} + +void Scene4025::Peg::synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsSint16LE(_field88); + SYNC_POINTER(_armStrip); +} + +void Scene4025::Peg::doAction(int action) { + Scene4025 *scene = (Scene4025 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4025, 1); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_pegPtr = this; + scene->setAction(&scene->_action1); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4025::Scene4025() : Scene() { + _holePtr = NULL; + _pegPtr = _pegPtr2 = NULL; +} + +void Scene4025::postInit(SceneObjectList *OwnerList) { + loadScene(4025); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _globals->_events.setCursor(CURSOR_USE); + _pegPtr = _pegPtr2 = NULL; + + _peg1.postInit(); + _peg1._field88 = 1; + _peg1.setVisage(4025); + _peg1.setStrip(2); + _peg1.setFrame(1); + _peg1.setPosition(Common::Point(203, 61)); + + _peg2.postInit(); + _peg2._field88 = 4; + _peg2.setVisage(4025); + _peg2.setStrip(2); + _peg2.setFrame(2); + _peg2.setPosition(Common::Point(195, 57)); + + _peg3.postInit(); + _peg3._field88 = 0; + _peg3.setVisage(4025); + _peg3.setStrip(2); + _peg3.setFrame(3); + _peg3.setPosition(Common::Point(202, 66)); + + _peg4.postInit(); + _peg4._field88 = 3; + _peg4.setVisage(4025); + _peg4.setStrip(2); + _peg4.setFrame(4); + _peg4.setPosition(Common::Point(194, 68)); + + _peg5.postInit(); + _peg5._field88 = 2; + _peg5.setVisage(4025); + _peg5.setStrip(1); + _peg5.setFrame(5); + _peg5.hide(); + + _hole1.postInit(); + _hole1.setVisage(4025); + _hole1.setStrip(1); + _hole1.setFrame2(6); + _hole1.setPosition(Common::Point(123, 51)); + _hole1._pegPtr = NULL; + _hole1._newPosition = Common::Point(123, 44); + _hole1._armStrip = 8; + + _hole2.postInit(); + _hole2.setVisage(4025); + _hole2.setStrip(1); + _hole2.setFrame2(7); + _hole2.setPosition(Common::Point(167, 51)); + _hole2._pegPtr = NULL; + _hole2._newPosition = Common::Point(166, 44); + _hole2._armStrip = 7; + + _hole3.postInit(); + _hole3.setVisage(4025); + _hole3.setStrip(1); + _hole3.setFrame2(8); + _hole3.setPosition(Common::Point(145, 69)); + _hole3._pegPtr = NULL; + _hole3._newPosition = Common::Point(145, 60); + _hole3._armStrip = 6; + + _hole4.postInit(); + _hole4.setVisage(4025); + _hole4.setStrip(1); + _hole4.setFrame2(6); + _hole4.setPosition(Common::Point(123, 87)); + _hole4._pegPtr = NULL; + _hole4._newPosition = Common::Point(123, 80); + _hole4._armStrip = 5; + + _hole5.postInit(); + _hole5.setVisage(4025); + _hole5.setStrip(1); + _hole5.setFrame2(10); + _hole5.setPosition(Common::Point(167, 87)); + _hole5._pegPtr = NULL; + _hole5._newPosition = Common::Point(166, 80); + _hole5._armStrip = 4; + + _hole1.setPriority2(1); + _hole2.setPriority2(1); + _hole3.setPriority2(1); + _hole4.setPriority2(1); + _hole5.setPriority2(1); + + _armHotspot.postInit(); + _armHotspot.setVisage(4025); + _armHotspot.setPosition(Common::Point(190, 161)); + _armHotspot.setStrip(3); + _armHotspot.setFrame(4); + + _globals->_sceneItems.addItems(&_hole1, &_hole2, &_hole3, &_hole4, &_hole5, + &_peg1, &_peg2, &_peg3, &_peg4, &_peg5, NULL); + + _globals->_player._uiEnabled = true; + _globals->_player.disableControl(); + setAction(&_sequenceManager, this, 4026, NULL); +} + +void Scene4025::synchronise(Serialiser &s) { + Scene::synchronise(s); + SYNC_POINTER(_pegPtr); + SYNC_POINTER(_pegPtr2); + SYNC_POINTER(_holePtr); +} + +void Scene4025::remove() { + _globals->_scenePalette.clearListeners(); + Scene::remove(); +} + +void Scene4025::signal() { + if (_sceneMode != 4027) { + if (_sceneMode != 4028) { + _gfxButton.setText(EXIT_MSG); + _gfxButton._bounds.centre(144, 107); + _gfxButton.draw(); + _gfxButton._bounds.expandPanes(); + } + + _globals->_player._uiEnabled = true; + } + + _globals->_events.setCursor(CURSOR_USE); +} + +void Scene4025::process(Event &event) { + Scene::process(event); + + if (_gfxButton.process(event)) { + if (_globals->_inventory._peg._sceneNumber == 4025) + _globals->_inventory._peg._sceneNumber = 1; + + _globals->_sceneManager.changeScene(4000); + } +} + +void Scene4025::dispatch() { + if (!_action && (_peg1._armStrip == 7) && (_peg2._armStrip == 4) && (_peg3._armStrip == 8) && + (_peg4._armStrip == 5) && (_peg5._armStrip == 6)) + setAction(&_action3); + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 4045 - Village - Temple Antechamber + * + *--------------------------------------------------------------------------*/ + +void Scene4045::Action1::signal() { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(60); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(4040, this, scene); + break; + case 2: + scene->_hotspot5.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot4.animate(ANIM_MODE_5, this); + break; + case 3: + setDelay(60); + break; + case 4: + scene->_hotspot4.animate(ANIM_MODE_6, this); + break; + case 5: + ADD_MOVER(_globals->_player, 150, 300); + break; + case 6: + _globals->_stripNum = 4000; + _globals->_sceneManager.changeScene(4000); + remove(); + break; + } +} + +void Scene4045::Action2::signal() { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(15); + break; + case 1: + scene->_stripManager.start(_globals->_stripNum, this, scene); + break; + case 2: + scene->_hotspot5.animate(ANIM_MODE_NONE, NULL); + setDelay(10); + break; + case 3: + if (_globals->getFlag(38)) { + _globals->_player.enableControl(); + remove(); + } else { + ADD_MOVER(_globals->_player, 150, 300); + } + break; + case 4: + _globals->setFlag(39); + _globals->_sceneManager.changeScene(4000); + break; + } +} + +void Scene4045::Action3::signal() { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + scene->_hotspot4.animate(ANIM_MODE_5, this); + break; + case 1: + scene->_stripManager.start(4504, this, scene); + break; + case 2: + scene->_hotspot4.animate(ANIM_MODE_6, NULL); + scene->_hotspot5.animate(ANIM_MODE_NONE, NULL); + ADD_MOVER(_globals->_player, 91, 1264); + break; + case 3: + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4045::Hotspot1::doAction(int action) { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_STUNNER: + SceneItem::display2(4045, 19); + break; + case CURSOR_LOOK: + SceneItem::display2(4045, (_strip == 1) ? 5 : 14); + break; + case CURSOR_USE: + SceneItem::display2(4045, 18); + break; + case CURSOR_TALK: + if (_strip == 5) { + setStrip(6); + animate(ANIM_MODE_NONE, 0); + } + if (_globals->_player._position.y < 135) { + scene->_sceneMode = 4046; + _numFrames = 10; + _globals->_player.disableControl(); + + scene->setAction(&scene->_sequenceManager, this, 4046, &_globals->_player, this, NULL); + } else { + if (!_globals->getFlag(31)) { + _globals->setFlag(31); + _globals->_stripNum = 4080; + } else if (!_globals->getFlag(38)) + _globals->_stripNum = 4060; + else + _globals->_stripNum = 4503; + + scene->setAction(&scene->_action2); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4045::Hotspot2::doAction(int action) { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4045, 9); + break; + case CURSOR_TALK: + scene->_sceneMode = 4102; + _globals->_player.disableControl(); + scene->setAction(&scene->_sequenceManager, scene, 4104, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4045::Hotspot6::doAction(int action) { + Scene4045 *scene = (Scene4045 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4045, 17); + break; + case CURSOR_USE: + if (_globals->_player._position.y < 135) { + SceneItem::display2(4045, 16); + _globals->_inventory._peg._sceneNumber = 1; + _globals->_events.setCursor(CURSOR_WALK); + remove(); + } else { + scene->_sceneMode = 4047; + _globals->_player.disableControl(); + scene->setAction(&scene->_sequenceManager, scene, 4047, &_globals->_player, &scene->_hotspot1, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4045::Scene4045() : + _hotspot3(0, CURSOR_LOOK, 4045, 1, CURSOR_USE, 4100, 21, LIST_END), + _hotspot7(9, CURSOR_LOOK, 4045, 0, CURSOR_USE, 4045, 15, LIST_END), + _hotspot8(10, CURSOR_LOOK, 4045, 2, LIST_END), + _hotspot9(11, CURSOR_LOOK, 4045, 3, CURSOR_USE, 4045, 15, LIST_END), + _hotspot10(12, CURSOR_LOOK, 4045, 4, CURSOR_USE, 4045, 19, LIST_END), + _hotspot11(13, CURSOR_LOOK, 4045, 6, CURSOR_USE, 4045, 15, LIST_END), + _hotspot12(14, CURSOR_LOOK, 4045, 7, CURSOR_USE, 4045, 29, LIST_END), + _hotspot13(15, CURSOR_LOOK, 4045, 8, CURSOR_USE, 4045, 19, LIST_END), + _hotspot14(0, CURSOR_LOOK, 4045, 10, LIST_END) { + + _hotspot14.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); +} + +void Scene4045::postInit(SceneObjectList *OwnerList) { + loadScene(4045); + Scene::postInit(); + setZoomPercents(100, 60, 200, 100); + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerML); + _stripManager.addSpeaker(&_speakerPR); + _stripManager.addSpeaker(&_speakerPText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.setCallback(this); + + _speakerQText._textPos.y = 140; + + _hotspot3.postInit(); + _hotspot3.setVisage(4045); + _hotspot3.setPosition(Common::Point(47, 111)); + _hotspot3.animate(ANIM_MODE_2, NULL); + _hotspot3.setPriority2(156); + _globals->_sceneItems.push_back(&_hotspot3); + + _globals->_player.postInit(); + _globals->_player.setVisage(4200); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._moveDiff = Common::Point(7, 4); + + _hotspot1.postInit(); + _hotspot1.setVisage(4051); + + _hotspot5.postInit(); + _hotspot5.setVisage(4051); + _hotspot5.setStrip(4); + _hotspot5.setPriority2(152); + + if(_globals->_sceneManager._previousScene == 4050) { + _globals->_soundHandler.startSound(155); + _globals->_player.setPosition(Common::Point(72, 128)); + _globals->_player.enableControl(); + + _hotspot1.setStrip(5); + _hotspot1.setPosition(Common::Point(173, 99)); + _hotspot1._numFrames = 1; + _hotspot1.animate(ANIM_MODE_2, NULL); + + _hotspot5.setPosition(Common::Point(177, 40)); + + if (_globals->_inventory._peg._sceneNumber == 4045) { + _hotspot6.postInit(); + _hotspot6.setVisage(4045); + _hotspot6.setStrip(2); + _hotspot6.setPosition(Common::Point(108, 82)); + _globals->_sceneItems.push_back(&_hotspot6); + } + } else { + _globals->_player.setPosition(Common::Point(108, 192)); + _globals->_player.setStrip(4); + + if (!_globals->getFlag(36) && !_globals->getFlag(43)) { + _hotspot2.postInit(); + _hotspot2.setVisage(4102); + _hotspot2.animate(ANIM_MODE_NONE, NULL); + _hotspot2.setStrip(3); + _hotspot2.changeZoom(-1); + _hotspot2.setPosition(Common::Point(66, 209)); + _globals->_sceneItems.push_back(&_hotspot2); + } + + if (_globals->getFlag(31)) { + _hotspot1.setVisage(4051); + _hotspot1.setStrip(5); + _hotspot1.setPosition(Common::Point(173, 99)); + _hotspot1._numFrames = 1; + _hotspot1.animate(ANIM_MODE_2, NULL); + + _hotspot5.setPosition(Common::Point(177, 40)); + + if (_globals->_inventory._peg._sceneNumber == 4045) { + _hotspot6.postInit(); + _hotspot6.setVisage(4045); + _hotspot6.setStrip(2); + _hotspot6.setPosition(Common::Point(108, 82)); + _globals->_sceneItems.push_back(&_hotspot6); + } + } else { + _hotspot1.setPosition(Common::Point(186, 149)); + + _hotspot4.postInit(); + _hotspot4.setVisage(4051); + _hotspot4.setStrip(2); + _hotspot4.setPriority2(152); + _hotspot4.setPosition(Common::Point(202, 80)); + + _hotspot5.setPosition(Common::Point(192, 77)); + _globals->setFlag(31); + setAction(&_action1); + + _globals->_player.disableControl(); + } + } + + _globals->_sceneItems.addItems(&_hotspot1, &_hotspot7, &_hotspot8, &_hotspot9, &_hotspot10, + &_hotspot13, &_hotspot11, &_hotspot12, &_hotspot14, NULL); +} + +void Scene4045::stripCallback(int v) { + switch (v) { + case 1: + _hotspot5.animate(ANIM_MODE_7, 0, NULL); + break; + case 2: + _hotspot5.animate(ANIM_MODE_NONE, NULL); + break; + } +} + +void Scene4045::signal() { + switch (_sceneMode) { + case 4046: + case 4047: + _hotspot5.animate(ANIM_MODE_NONE, NULL); + break; + case 4050: + _globals->_sceneManager.changeScene(4000); + break; + case 4102: + _globals->_player.enableControl(); + break; + } +} + +void Scene4045::dispatch() { + if (!_action) { + if (_globals->_player.getRegionIndex() == 8) { + _globals->_player.addMover(NULL); + if (_hotspot1._strip == 1) { + _globals->_player.disableControl(); + _sceneMode = 4046; + _hotspot1._numFrames = 10; + setAction(&_sequenceManager, this, 4046, &_globals->_player, &_hotspot1, NULL); + } else { + setAction(&_action3); + } + } + + if (_globals->_player.getRegionIndex() == 10) + _globals->_sceneManager.changeScene(4050); + if (_globals->_player._position.y >= 196) { + _sceneMode = 4050; + _globals->_player.disableControl(); + setAction(&_sequenceManager, this, 4105, &_globals->_player, NULL); + } + } + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 4000 - Village - Temple + * + *--------------------------------------------------------------------------*/ + +void Scene4050::Action1::signal() { + Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + ADD_PLAYER_MOVER(204, 152); + break; + case 2: + _globals->_player.checkAngle(&scene->_hotspot17); + + scene->_hotspot14.postInit(); + scene->_hotspot14.setVisage(4050); + scene->_hotspot14.setStrip(2); + scene->_hotspot14.setPosition(Common::Point(91, 154)); + scene->_hotspot14.setPriority2(200); + break; + case 3: + _globals->_events.waitForPress(); + _globals->setFlag(45); + scene->_hotspot14.remove(); + + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4050::Action2::signal() { + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(120); + break; + case 1: + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player.setVisage(4202); + _globals->_player.changeZoom(100); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(192, 130)); + + ADD_MOVER(_globals->_player, 215, 130); + break; + case 3: + _globals->_player.setVisage(4052); + _globals->_player.setStrip(5); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(236, 130)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 4: + _globals->_player.setVisage(4202); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setPosition(Common::Point(210, 185)); + _globals->_player.setPriority2(-1); + _globals->_player.enableControl(); + + remove(); + break; + } +} + +void Scene4050::Action3::signal() { + switch (_actionIndex++) { + case 0: + ADD_PLAYER_MOVER(210, 185); + break; + case 1: + _globals->_player.setPriority2(200); + _globals->_player.setVisage(4052); + _globals->_player.setStrip(5); + _globals->_player.changeZoom(100); + _globals->_player.setFrame(_globals->_player.getFrameCount()); + _globals->_player.setPosition(Common::Point(236, 130)); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 2: + _globals->_player.setVisage(4202); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(215, 130)); + ADD_MOVER(_globals->_player, 212, 130); + break; + case 3: + _globals->_stripNum = 4050; + _globals->_sceneManager.changeScene(4000); + break; + } +} + +void Scene4050::Action4::signal() { + Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_MOVER(_globals->_player, 189, 135); + _globals->_player.setPriority2(200); + break; + case 1: + _globals->_player._moveDiff.y = 3; + _globals->_player.setStrip2(3); + _globals->_player._frame = 1; + _globals->_player.setPosition(Common::Point(189, 129)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + _globals->_player.setVisage(4202); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(192, 130)); + _globals->_player.changeZoom(100); + ADD_MOVER(_globals->_player, 215, 130); + + scene->_hotspot16.postInit(); + scene->_hotspot16.setVisage(4052); + scene->_hotspot16.animate(ANIM_MODE_1, NULL); + scene->_hotspot16.setStrip2(6); + scene->_hotspot16.setPosition(Common::Point(160, 240)); + ADD_MOVER(scene->_hotspot16, 172, 188); + break; + case 3: + _globals->_player.setVisage(4052); + _globals->_player.setStrip(5); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(238, 130)); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 4: + _globals->_player.setVisage(4052); + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(216, 184)); + _globals->_player.setPriority2(-1); + break; + case 5: + scene->_hotspot16.setStrip2(4); + scene->_hotspot16.setFrame(1); + scene->_hotspot16.animate(ANIM_MODE_4, 4, 1, this);; + break; + case 6: + scene->_hotspot16.animate(ANIM_MODE_5, NULL); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 7: + _globals->_player.setVisage(4202); + _globals->_player.setStrip(6); + _globals->_player.setFrame(1); + + scene->_stripManager.start(4051, this); + break; + case 8: + setDelay(15); + break; + case 9: + _globals->_sceneManager.changeScene(4000); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4050::Hotspot14::doAction(int action) { + Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4050, 14); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4050::Hotspot17::doAction(int action) { + Scene4050 *scene = (Scene4050 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + scene->setAction(&scene->_action1); + break; + case CURSOR_USE: + SceneItem::display2(4050, 24); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4050::Scene4050() : + _hotspot1(0, CURSOR_LOOK, 4050, 0, LIST_END), + _hotspot2(0, CURSOR_LOOK, 4050, 1, CURSOR_USE, 4050, 15, LIST_END), + _hotspot3(0, CURSOR_LOOK, 4050, 2, CURSOR_USE, 4050, 16, LIST_END), + _hotspot4(0, CURSOR_LOOK, 4050, 4, LIST_END), + _hotspot5(0, CURSOR_LOOK, 4050, 5, LIST_END), + _hotspot6(0, CURSOR_LOOK, 4050, 5, LIST_END), + _hotspot7(0, CURSOR_LOOK, 4050, 6, CURSOR_USE, 4050, 18, LIST_END), + _hotspot8(0, CURSOR_LOOK, 4050, 7, CURSOR_USE, 4050, 19, LIST_END), + _hotspot9(0, CURSOR_LOOK, 4050, 8, CURSOR_USE, 4050, 20, LIST_END), + _hotspot10(0, CURSOR_LOOK, 4050, 9, CURSOR_USE, 4050, 21, LIST_END), + _hotspot11(0, CURSOR_LOOK, 4050, 10, CURSOR_USE, 4050, 22, LIST_END), + _hotspot12(0, CURSOR_LOOK, 4050, 11, CURSOR_USE, 4050, 23, LIST_END), + _hotspot13(0, CURSOR_LOOK, 4050, 3, CURSOR_USE, 4050, 17, LIST_END) { +} + +void Scene4050::postInit(SceneObjectList *OwnerList) { + loadScene(4050); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerPText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerGameText); + + _globals->_player.postInit(); + + switch (_globals->_sceneManager._previousScene) { + case 4000: + if (_globals->getFlag(41)) { + _hotspot15.postInit(); + _hotspot15.setVisage(4054); + _hotspot15.setPosition(Common::Point(206, 103)); + _globals->_sceneItems.push_back(&_hotspot15); + + _globals->_player.setVisage(4008); + _globals->_player.setPosition(Common::Point(206, 62)); + _globals->_player.changeZoom(130); + _globals->_player.setPriority2(200); + _globals->_player.setStrip(2); + + setAction(&_action2); + _globals->_soundHandler.startSound(175); + } else { + _globals->_player.setVisage(5315); + _globals->_player.setPosition(Common::Point(189, 83)); + _globals->_player.changeZoom(130); + _globals->_player.setStrip2(2); + _globals->_player._moveDiff.y = 10; + _globals->_player.animate(ANIM_MODE_2, NULL); + + setAction(&_action4); + _globals->_soundHandler.startSound(176); + } + break; + case 4045: + _hotspot15.postInit(); + _hotspot15.setVisage(4054); + _hotspot15.setPosition(Common::Point(206, 103)); + _globals->_sceneItems.push_back(&_hotspot15); + + _globals->_player.setVisage(4202); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(193, 193)); + + _globals->_soundHandler.startSound(175); + break; + default: + break; + } + + _hotspot13.postInit(); + _hotspot13.setVisage(4053); + _hotspot13.animate(ANIM_MODE_2, NULL); + _hotspot13.setPosition(Common::Point(190, 97)); + + _hotspot17.postInit(); + _hotspot17.setVisage(4050); + _hotspot17.setPosition(Common::Point(209, 119)); + _hotspot17.setPriority2(2); + + _hotspot1.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot2.setBounds(Rect(150, 25, 198, 125)); + _hotspot3.setBounds(Rect(56, 94, 88, 153)); + _hotspot4.setBounds(Rect(170, 7, 209, 18)); + _hotspot5.setBounds(Rect(190, 72, 212, 92)); + _hotspot6.setBounds(Rect(122, 75, 145, 93)); + _hotspot7.setBounds(Rect(109, 103, 263, 158)); + _hotspot8.setBounds(Rect(157, 160, 213, 173)); + _hotspot9.setBounds(Rect(95, 157, 120, 178)); + _hotspot10.setBounds(Rect(278, 43, 310, 115)); + _hotspot11.setBounds(Rect(263, 105, 279, 147)); + _hotspot12.setBounds(Rect(258, 154, 307, 180)); + + _globals->_sceneItems.addItems(&_hotspot17, &_hotspot12, &_hotspot11, &_hotspot10, &_hotspot13, + &_hotspot2, &_hotspot3, &_hotspot4, &_hotspot5, &_hotspot6, &_hotspot8, &_hotspot9, + &_hotspot7, &_hotspot1, NULL); +} + +void Scene4050::signal() { + +} + +void Scene4050::dispatch() { + +} + +/*-------------------------------------------------------------------------- + * Scene 4100 - Village - Hut + * + *--------------------------------------------------------------------------*/ + +void Scene4100::Action1::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(10); + break; + case 1: + scene->_stripManager.start(_globals->_stripNum, this); + break; + case 2: + setDelay(30); + break; + case 3: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4100::Action2::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_hotspot2.postInit(); + scene->_hotspot2.changeZoom(95); + scene->_hotspot2.setVisage(4120); + scene->_hotspot2.animate(ANIM_MODE_1, NULL); + scene->_hotspot2.setStrip2(4); + scene->_hotspot2.setPriority2(100); + scene->_hotspot2.setPosition(Common::Point(214, 119)); + + setDelay(3); + break; + case 1: + ADD_MOVER(scene->_hotspot2, 249, 131); + break; + case 2: + scene->_hotspot2.setStrip2(3); + scene->_hotspot2.setFrame2(5); + scene->_hotspot2.animate(ANIM_MODE_NONE, NULL); + setDelay(3); + break; + case 3: + remove(); + break; + } +} + + +void Scene4100::Action3::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->clearFlag(43); + _globals->clearFlag(36); + setDelay(15); + break; + case 1: + scene->_stripManager.start(4505, this); + break; + case 2: + scene->setAction(&scene->_action2); + case 3: + scene->_stripManager.start(4510, this); + break; + case 4: + setDelay(15); + break; + case 5: + _globals->_sceneManager.changeScene(4150); + break; + } +} + +void Scene4100::Action4::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 2: + scene->_hotspot1.setVisage(4105); + scene->_hotspot1.setFrame(1); + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->clearFlag(43); + _globals->setFlag(42); + scene->_stripManager.start(4119, this); + case 4: + setDelay(15); + break; + case 5: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4100::Action5::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_PLAYER_MOVER(58, 151); + break; + case 1: + if (_globals->_inventory._ladder._sceneNumber == 4100) { + _globals->_inventory._ladder._sceneNumber = 1; + scene->_hotspot6.remove(); + } else { + scene->_hotspot6.postInit(); + scene->_hotspot6.setVisage(4101); + scene->_hotspot6.setPosition(Common::Point(49, 144)); + + _globals->_inventory._ladder._sceneNumber = 4100; + _globals->_sceneItems.push_front(&scene->_hotspot6); + } + + _globals->_player.enableControl(); + remove(); + break; + } +} + + +void Scene4100::Action6::signal() { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + scene->_stripManager.start(4103, this); + ADD_PLAYER_MOVER(245, 167); + break; + case 1: + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4100::Hotspot1::doAction(int action) { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4100, _globals->getFlag(42) ? 24 : 12); + break; + case OBJECT_STUNNER: + SceneItem::display2(4100, 16); + break; + case CURSOR_USE: + SceneItem::display2(4100, 22); + break; + case CURSOR_TALK: + if (_globals->_inventory._peg._sceneNumber == 1) { + _globals->_player.disableControl(); + scene->setAction(&scene->_sequenceManager, scene, 4109, NULL); + } else if (_globals->getFlag(42)) { + scene->setAction(&scene->_sequenceManager, scene, 4102, NULL); + } else { + if (_globals->getFlag(33)) + _globals->_stripNum = 4077; + else if (_globals->getFlag(82)) { + _globals->clearFlag(82); + _globals->_stripNum = 4100; + } else { + _globals->_stripNum = 4075; + _globals->setFlag(33); + } + + scene->setAction(&scene->_action1); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4100::Hotspot2::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + error("*** The Chief's daughter... WOW!"); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4100::Hotspot5::doAction(int action) { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4100, 14); + break; + case CURSOR_TALK: + scene->_sceneMode = 4102; + scene->setAction(&scene->_sequenceManager, scene, 4104, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4100::Hotspot6::doAction(int action) { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4100, 2); + break; + case CURSOR_USE: + if (_globals->getFlag(42)) { + _globals->_player.disableControl(); + scene->setAction(&scene->_action5); + } else { + scene->_sceneMode = 4102; + scene->setAction(&scene->_sequenceManager, scene, 4103, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + + +void Scene4100::Hotspot14::doAction(int action) { + Scene4100 *scene = (Scene4100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4100, 0); + break; + case OBJECT_LADDER: + _globals->_player.disableControl(); + scene->setAction(&scene->_action5); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + + +/*--------------------------------------------------------------------------*/ + +Scene4100::Scene4100() : + _hotspot3(0, CURSOR_LOOK, 4100, 10, CURSOR_USE, 4100, 21, LIST_END), + _hotspot4(0, CURSOR_LOOK, 4100, 8, LIST_END), + _hotspot7(0, CURSOR_USE, 4100, 3, CURSOR_USE, 4150, 29, LIST_END), + _hotspot8(0, CURSOR_LOOK, 4100, 5, LIST_END), + _hotspot9(0, CURSOR_LOOK, 4100, 6, CURSOR_USE, 4100, 20, LIST_END), + _hotspot10(0, CURSOR_LOOK, 4100, 7, CURSOR_USE, 4100, 19, LIST_END), + _hotspot11(0, CURSOR_LOOK, 4100, 8, CURSOR_USE, 4100, 18, LIST_END), + _hotspot12(0, CURSOR_LOOK, 4100, 9, LIST_END), + _hotspot13(0, CURSOR_LOOK, 4100, 11, CURSOR_USE, 4100, 17, LIST_END) { +} + +void Scene4100::postInit(SceneObjectList *OwnerList) { + loadScene(4100); + Scene::postInit(); + setZoomPercents(135, 80, 190, 100); + + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerCHFText); + _stripManager.addSpeaker(&_speakerCDRText); + _stripManager.addSpeaker(&_speakerCDR); + _stripManager.addSpeaker(&_speakerML); + _stripManager.addSpeaker(&_speakerQR); + + _globals->_player.postInit(); + _globals->_player.setVisage(4200); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(4); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(88, 180)); + _globals->_player._moveDiff = Common::Point(7, 4); + + _hotspot1.postInit(); + _hotspot1.setVisage(4102); + _hotspot1.setPriority2(129); + _hotspot1.setPosition(Common::Point(171, 120)); + + _hotspot3.postInit(); + _hotspot3.setVisage(4130); + _hotspot3.animate(ANIM_MODE_2, NULL); + _hotspot3.setPriority2(200); + _hotspot3.setPosition(Common::Point(272, 110)); + + _hotspot4.postInit(); + _hotspot4.setVisage(4130); + _hotspot4.animate(ANIM_MODE_2, NULL); + _hotspot4.setStrip2(2); + _hotspot4.setPosition(Common::Point(152, 167)); + + if (_globals->getFlag(36)) { + _hotspot1.setVisage(4105); + _hotspot1.setStrip(1); + _hotspot1.setFrame(4); + } else if (!_globals->getFlag(43)) { + _hotspot5.postInit(); + _hotspot5.setVisage(4102); + _hotspot5.setStrip2(3); + _hotspot5.setFrame(2); + _hotspot5.setPosition(Common::Point(65, 188)); + + _globals->_sceneItems.push_back(&_hotspot5); + } + + if (_globals->_inventory._ladder._sceneNumber == 4100) { + _hotspot6.postInit(); + _hotspot6.setVisage(4101); + _hotspot6.setPosition(Common::Point(49, 144)); + + _globals->_sceneItems.push_back(&_hotspot6); + } + + _hotspot14.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot7._sceneRegionId = 16; + _hotspot8.setBounds(Rect(90, 0, 211, 113)); + _hotspot9.setBounds(Rect(207, 96, 235, 115)); + _hotspot10.setBounds(Rect(87, 81, 212, 107)); + _hotspot11.setBounds(Rect(61, 148, 243, 168)); + _hotspot12.setBounds(Rect(229, 59, 256, 122)); + _hotspot13.setBounds(Rect(255, 152, 286, 183)); + + _globals->_sceneItems.addItems(&_hotspot3, &_hotspot1, &_hotspot13, &_hotspot12, &_hotspot4, + &_hotspot11, &_hotspot9, &_hotspot7, &_hotspot10, &_hotspot8, &_hotspot14, NULL); + + if (_globals->_sceneManager._previousScene == 4150) { + _globals->_soundHandler.startSound(155); + + if (!_globals->getFlag(42)) { + _hotspot1.setVisage(4104); + _hotspot1.setPosition(Common::Point(152, 118)); + _hotspot1.setStrip2(-1); + _hotspot1.setFrame2(-1); + _hotspot1.setFrame(1); + + _globals->_player.setStrip(2); + _globals->_player.disableControl(); + setAction(&_action4); + + _globals->clearFlag(43); + } + + _globals->_player.setPosition(Common::Point(252, 139)); + _globals->_player.setStrip(2); + } else { + if ((_globals->_inventory._ale._sceneNumber == 4100) && !_globals->getFlag(42)) { + _globals->_player.disableControl(); + setAction(&_action3); + } + if (_globals->getFlag(35)) { + _globals->_player.disableControl(); + _sceneMode = 4101; + setAction(&_sequenceManager, this, 4101, &_globals->_player, NULL); + } + } +} + +void Scene4100::signal() { + switch (_sceneMode) { + case 4101: + _globals->_sceneManager.changeScene(4000); + break; + case 4102: + case 4103: + case 4109: + _globals->_player.enableControl(); + break; + } +} + +void Scene4100::dispatch() { + if (!_action) { + if ((_globals->_player.getRegionIndex() == 15) && !_globals->getFlag(42)) + setAction(&_action6); + + if (_globals->_player.getRegionIndex() == 8) + _globals->_sceneManager.changeScene(4150); + + if (_globals->_player._position.y >= 196) { + _globals->_player.disableControl(); + _sceneMode = 4101; + setAction(&_sequenceManager, this, 4105, &_globals->_player, NULL); + } + } + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 4150 - Village - Bedroom + * + *--------------------------------------------------------------------------*/ + +void Scene4150::Action1::signal() { + Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene; + byte adjustData[4] = {0, 0, 0, 0}; + + switch (_actionIndex++) { + case 0: + setDelay(60); + break; + case 1: + scene->_stripManager.start(4520, this); + break; + case 2: + setDelay(15); + break; + case 3: + setAction(&scene->_action2, this); + break; + case 4: { + for (int idx = 100; idx >= 0; idx -= 5) { + _globals->_scenePalette.fade(adjustData, false, idx); + g_system->updateScreen(); + g_system->delayMillis(10); + } + + scene->_hotspot4.postInit(); + scene->_hotspot4.setVisage(4150); + scene->_hotspot4.setStrip(2); + scene->_hotspot4.setPosition(Common::Point(166, 157)); + + scene->_hotspot1.postInit(); + scene->_hotspot1.setVisage(4156); + scene->_hotspot1.setStrip(1); + scene->_hotspot1.setFrame(1); + + setDelay(120); + break; + } + case 5: + _globals->_scenePalette.loadPalette(4150); + _globals->_scenePalette.refresh(); + setDelay(60); + break; + case 6: + scene->_stripManager.start(4522, this); + break; + case 7: + for (int idx = 100; idx >= 0; idx -= 5) { + _globals->_scenePalette.fade(adjustData, false, idx); + g_system->updateScreen(); + g_system->delayMillis(10); + } + + scene->_hotspot4.remove(); + scene->_hotspot1.setVisage(4157); + scene->_hotspot1.animate(ANIM_MODE_NONE, NULL); + scene->_hotspot1.setStrip(1); + scene->_hotspot1.setFrame(1); + scene->_hotspot1.show(); + + _globals->_player.setVisage(4200); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(3); + _globals->_player.setPosition(Common::Point(139, 166)); + _globals->_player._moveDiff = Common::Point(7, 3); + _globals->_player.show(); + + setDelay(120); + break; + case 8: + _globals->_scenePalette.loadPalette(4150); + _globals->_scenePalette.refresh(); + setDelay(30); + break; + case 9: + scene->_stripManager.start(4523, this); + break; + case 10: + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player._moveDiff = Common::Point(7, 4); + _globals->_player.setStrip(3); + _globals->_player.enableControl(); + + remove(); + break; + } +} + +void Scene4150::Action2::signal() { + Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + scene->_hotspot1.setVisage(4152); + scene->_hotspot1.setStrip(1); + scene->_hotspot1.setFrame(1); + scene->_hotspot1.animate(ANIM_MODE_5, this); + + _globals->_player.animate(ANIM_MODE_5, NULL); + break; + case 2: + _globals->_player.hide(); + scene->_hotspot1.setVisage(4153); + scene->_hotspot1.setStrip(1); + scene->_hotspot1.setFrame(1); + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 3: + remove(); + break; + } +} + +void Scene4150::Action3::signal() { + Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(15); + break; + case 1: + _globals->_player.checkAngle(&scene->_hotspot3); + + if (_globals->_inventory._rope._sceneNumber == 1) { + scene->_hotspot3.postInit(); + scene->_hotspot3.setVisage(4150); + scene->_hotspot3.setPosition(Common::Point(175, 70)); + + _globals->_inventory._rope._sceneNumber = 4150; + _globals->_sceneItems.push_front(&scene->_hotspot3); + } else { + _globals->_inventory._rope._sceneNumber = 1; + scene->_hotspot3.remove(); + } + + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4150::HotspotGroup1::doAction(int action) { + Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4150, 0); + break; + case OBJECT_ROPE: + scene->setAction(&scene->_action3); + break; + } +} + +void Scene4150::HotspotGroup3::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4150, _globals->getFlag(46) ? 9 : 8); + _globals->setFlag(46); + break; + case CURSOR_USE: + SceneItem::display2(4150, 30); + break; + } +} + +void Scene4150::HotspotGroup6::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4150, _globals->getFlag(47) ? 16 : 15); + _globals->setFlag(47); + break; + case CURSOR_USE: + SceneItem::display2(4150, 31); + break; + } +} + +void Scene4150::Hotspot3::doAction(int action) { + Scene4150 *scene = (Scene4150 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4150, 20); + break; + case CURSOR_USE: + scene->setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4150::Scene4150() : + _hotspot1(0, CURSOR_LOOK, 4000, 17, CURSOR_USE, 4150, 21, CURSOR_TALK, 4150, 21, + OBJECT_SCANNER, 4150, 22, OBJECT_STUNNER, 4150, 23, LIST_END), + _hotspot2(0, CURSOR_LOOK, 4150, 4, CURSOR_USE, 4150, 24, LIST_END), + _hotspot7(0, CURSOR_LOOK, 4150, 1, CURSOR_USE, 4150, 25, OBJECT_ROPE, 4150, 26, LIST_END), + _hotspot8(0, CURSOR_LOOK, 4150, 1, CURSOR_USE, 4150, 25, OBJECT_ROPE, 4150, 26, LIST_END), + _hotspot9(0, CURSOR_LOOK, 4150, 2, CURSOR_USE, 4150, 27, OBJECT_SCANNER, 4150, 28, + OBJECT_STUNNER, 4150, 32, LIST_END), + _hotspot10(0, CURSOR_LOOK, 4150, 5, CURSOR_USE, 4150, 29, LIST_END), + _hotspot11(0, CURSOR_LOOK, 4150, 6, CURSOR_USE, 4150, 29, LIST_END), + _hotspot12(0, CURSOR_LOOK, 4150, 7, CURSOR_USE, 4150, 29, LIST_END), + _hotspot17(0, CURSOR_LOOK, 4150, 10, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END), + _hotspot18(0, CURSOR_LOOK, 4150, 11, CURSOR_USE, 4150, 32, OBJECT_STUNNER, 4150, 27, LIST_END), + _hotspot19(0, CURSOR_LOOK, 4150, 12, CURSOR_USE, 4150, 29, LIST_END), + _hotspot20(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END), + _hotspot21(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END), + _hotspot22(0, CURSOR_LOOK, 4150, 13, CURSOR_USE, 4150, 29, LIST_END), + _hotspot23(0, CURSOR_LOOK, 4150, 14, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END), + _hotspot24(0, CURSOR_LOOK, 4150, 14, CURSOR_USE, 4150, 27, OBJECT_STUNNER, 4150, 32, LIST_END) + { +} + +void Scene4150::postInit(SceneObjectList *OwnerList) { + loadScene(4150); + Scene::postInit(); + setZoomPercents(60, 85, 200, 100); + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerCDL); + _stripManager.addSpeaker(&_speakerQText); + + _hotspot2.postInit(); + _hotspot2.setVisage(4171); + _hotspot2.animate(ANIM_MODE_2, NULL); + _hotspot2.setPriority2(100); + _hotspot2.setPosition(Common::Point(76, 147)); + + _hotspot1.postInit(); + _hotspot1.setPosition(Common::Point(177, 201)); + + if (_globals->getFlag(44)) { + _globals->_player.postInit(); + _globals->_player.setVisage(4200); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setStrip(2); + _globals->_player.setPosition(Common::Point(328, 160)); + _globals->_player._moveDiff = Common::Point(7, 4); + _globals->_player.disableControl(); + + _sceneMode = 4151; + setAction(&_sequenceManager, this, 4151, &_globals->_player, NULL); + + _hotspot1.setVisage(4157); + _hotspot1.setPosition(Common::Point(177, 201)); + } else { + _globals->_player.postInit(); + _globals->_player.setVisage(4154); + _globals->_player._canWalk = false; + _globals->_player.setPosition(Common::Point(198, 202)); + _globals->_player.disableControl(); + + _hotspot1.setVisage(4152); + setAction(&_action1); + _globals->setFlag(44); + } + + if (_globals->_inventory._rope._sceneNumber == 4150) { + _hotspot3.postInit(); + _hotspot3.setVisage(4150); + _hotspot3.setPosition(Common::Point(175, 70)); + + _globals->_sceneItems.push_back(&_hotspot3); + } + + _globals->_sceneItems.push_back(&_hotspot1); + + _hotspot5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot6.setBounds(Rect(28, 121, 80, 148)); + _hotspot7.setBounds(Rect(27, 17, 127, 100)); + _hotspot8.setBounds(Rect(62, 11, 117, 22)); + _hotspot9.setBounds(Rect(48, 78, 104, 94)); + _hotspot10.setBounds(Rect(32, 107, 58, 119)); + _hotspot11.setBounds(Rect(1, 130, 17, 163)); + _hotspot12.setBounds(Rect(1, 158, 78, 197)); + _hotspot13.setBounds(Rect(253, 11, 274, 188)); + _hotspot14.setBounds(Rect(4, 15, 29, 153)); + _hotspot15.setBounds(Rect(127, 22, 146, 133)); + _hotspot16.setBounds(Rect(165, 22, 181, 141)); + _hotspot17.setBounds(Rect(186, 31, 217, 52)); + _hotspot18.setBounds(Rect(200, 31, 251, 86)); + _hotspot19.setBounds(Rect(183, 81, 234, 111)); + _hotspot20.setBounds(Rect(188, 120, 219, 142)); + _hotspot21.setBounds(Rect(235, 122, 249, 145)); + _hotspot22.setBounds(Rect(283, 125, 320, 146)); + _hotspot23.setBounds(Rect(284, 27, 306, 160)); + _hotspot24.setBounds(Rect(257, 72, 284, 99)); + _hotspot25.setBounds(Rect(183, 155, 316, 190)); + _hotspot26.setBounds(Rect(98, 169, 238, 198)); + + _globals->_sceneItems.addItems(&_hotspot24, &_hotspot23, &_hotspot13, &_hotspot25, + &_hotspot26, &_hotspot19, &_hotspot22, &_hotspot20, &_hotspot17, &_hotspot16, + &_hotspot15, &_hotspot11, &_hotspot14, &_hotspot18, &_hotspot21, &_hotspot12, + &_hotspot10, &_hotspot9, &_hotspot8, &_hotspot7, &_hotspot6, &_hotspot2, + &_hotspot5, NULL); + + _globals->_soundHandler.startSound(165); + _soundHandler.startSound(311); +} + +void Scene4150::signal() { + if (_sceneMode == 4151) + _globals->_player.enableControl(); + else if (_sceneMode == 4152) + _globals->_sceneManager.changeScene(4100); +} + +void Scene4150::dispatch() { + Scene::dispatch(); + + if (!_action && (_globals->_player._position.x >= 316)) { + _globals->_soundHandler.proc1(NULL); + _globals->_player.disableControl(); + _sceneMode = 4152; + setAction(&_sequenceManager, this, 4152, &_globals->_player, NULL); + } +} + +/*-------------------------------------------------------------------------- + * Scene 4000 - Village + * + *--------------------------------------------------------------------------*/ + +void Scene4250::Action1::signal() { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + ADD_MOVER_NULL(_globals->_player, 6, 190); + ADD_MOVER_NULL(scene->_hotspot3, 9, 195); + ADD_MOVER(scene->_hotspot1, 12, 185); + break; + case 2: + setDelay(30); + break; + case 3: + scene->_stripManager.start(4450, this); + break; + case 4: + case 7: + setDelay(15); + break; + case 5: + ADD_PLAYER_MOVER(220, 175); + scene->_hotspot1.setPriority2(105); + ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 197, 173); + break; + case 6: + scene->_stripManager.start(4470, this); + break; + case 8: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4250::Action2::signal() { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_PLAYER_MOVER(247, 182); + break; + case 1: + _globals->_player.setVisage(2670); + _globals->_player.changeZoom(50); + _globals->_player.setStrip(3); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300)) { + scene->_stripManager.start(4205, this); + } else { + scene->_stripManager.start(4490, this); + } + break; + case 3: + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 4: + _globals->_player.setVisage(2602); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.changeZoom(70); + + if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300)) { + _globals->_player.enableControl(); + remove(); + } else { + ADD_PLAYER_MOVER(6, 180); + ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 12, 185); + } + break; + case 5: + ADD_PLAYER_MOVER(-16, 180); + ADD_PLAYER_MOVER_NULL(scene->_hotspot1, -12, 185); + scene->_hotspot3.setStrip2(2); + ADD_MOVER_NULL(scene->_hotspot5, -30, 195); + break; + case 6: + _globals->clearFlag(59); + _globals->clearFlag(70); + _globals->clearFlag(37); + _globals->clearFlag(114); + _globals->clearFlag(36); + _globals->clearFlag(43); + _globals->_sceneManager.changeScene(2100); + break; + } +} + +void Scene4250::Action3::signal() { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + scene->_stripManager.start(4480, this); + break; + case 2: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4250::Action4::signal() { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + _globals->_player.addMover(NULL); + scene->_stripManager.start((_globals->_inventory._helmet._sceneNumber == 4250) ? 4259 : 4256, this); + break; + case 2: + ADD_PLAYER_MOVER(_globals->_player._position.x + 5, _globals->_player._position.y); + break; + case 3: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene4250::Action5::signal() { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + scene->_hotspot4.setPriority2(195); + scene->_hotspot1.setPriority2(105); + ADD_MOVER_NULL(_globals->_player, 6, 185); + ADD_MOVER_NULL(scene->_hotspot4, 9, 190); + ADD_MOVER(scene->_hotspot1, 12, 180); + break; + case 2: + ADD_PLAYER_MOVER(252, 176); + ADD_PLAYER_MOVER_NULL(scene->_hotspot1, 197, 173); + ADD_PLAYER_MOVER_NULL(scene->_hotspot4, 239, 195); + break; + case 3: + scene->_hotspot4.setPriority2(-1); + scene->_hotspot1.setStrip(5); + scene->_hotspot4.setStrip(7); + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4250::Hotspot1::doAction(int action) { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4250, (_globals->_inventory._helmet._sceneNumber == 4250) ? 19 : 14); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + if (!_globals->_sceneObjects->contains(&scene->_hotspot4)) { + scene->setAction(&scene->_action3); + } else { + scene->_sceneMode = 4260; + if (_globals->_inventory._helmet._sceneNumber == 4250) { + scene->_sceneMode = 4265; + scene->setAction(&scene->_sequenceManager, scene, 4265, this, NULL); + } else { + scene->setAction(&scene->_sequenceManager, scene, + _globals->_sceneObjects->contains(&scene->_hotspot6) ? 4260 : 4262, this, NULL); + } + } + break; + case OBJECT_SCANNER: + if (_globals->_inventory._helmet._sceneNumber == 4250) + SceneItem::display2(4250, 21); + else + SceneHotspot::doAction(action); + break; + case OBJECT_STUNNER: + if (_globals->_inventory._helmet._sceneNumber == 4250) + SceneItem::display2(4250, 22); + else + SceneHotspot::doAction(action); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4250::Hotspot2::doAction(int action) { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + case CURSOR_USE: + SceneItem::display2(4250, 16); + break; + case OBJECT_SCANNER: + if ((_globals->_stripNum == 9000) || (_globals->_stripNum == 4300)) + scene->setAction(&scene->_action2); + else if (_globals->getFlag(55)) + SceneItem::display2(4250, 17); + else { + _globals->setFlag(55); + scene->setAction(&scene->_action2); + } + break; + case OBJECT_STASIS_NEGATOR: + _globals->_player.disableControl(); + scene->_sceneMode = 4252; + scene->setAction(&scene->_sequenceManager, scene, 4252, &_globals->_player, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4250::Hotspot4::doAction(int action) { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4250, (_globals->_inventory._helmet._sceneNumber == 4250) ? 18 : 5); + break; + case OBJECT_SCANNER: + if (_globals->_inventory._helmet._sceneNumber == 4250) + SceneItem::display2(4250, 21); + else + SceneHotspot::doAction(action); + break; + case OBJECT_STUNNER: + if (_globals->_inventory._helmet._sceneNumber == 4250) + SceneItem::display2(4250, 22); + else + SceneHotspot::doAction(action); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + if (!_globals->_sceneObjects->contains(&scene->_hotspot6)) { + scene->_sceneMode = 4254; + scene->setAction(&scene->_sequenceManager, scene, 4263, NULL); + } else { + scene->_sceneMode = 4254; + + if (_globals->_inventory._helmet._sceneNumber == 4250) { + scene->_sceneMode = 4266; + scene->setAction(&scene->_sequenceManager, scene, 4266, this, NULL); + } else { + scene->setAction(&scene->_sequenceManager, scene, + (_globals->_inventory._concentrator._sceneNumber == 1) ? 4255 : 4254, NULL); + } + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4250::Hotspot6::doAction(int action) { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4250, (_globals->_inventory._helmet._sceneNumber == 4250) ? 7 : 6); + break; + case OBJECT_SCANNER: + SceneItem::display2(4250, (_globals->_inventory._helmet._sceneNumber == 4250) ? 1 : 2); + break; + case OBJECT_STUNNER: + SceneItem::display2(4250, (_globals->_inventory._helmet._sceneNumber == 4250) ? 20 : 3); + break; + case OBJECT_HELMET: + _globals->_soundHandler.startSound(354); + _globals->_player.disableControl(); + _globals->_inventory._helmet._sceneNumber = 4250; + + if (_globals->_inventory._concentrator._sceneNumber == 1) { + if (_globals->getFlag(115)) { + scene->_sceneMode = 4269; + scene->setAction(&scene->_sequenceManager, scene, 4269, this, NULL); + } else { + _globals->setFlag(115); + _globals->_events.setCursor(CURSOR_WALK); + scene->setAction(&scene->_sequenceManager, scene, 4256, this, NULL); + } + } else if (_globals->_inventory._keyDevice._sceneNumber == 1) { + scene->_sceneMode = 4267; + scene->setAction(&scene->_sequenceManager, scene, 4267, this, NULL); + } else if (_globals->_inventory._keyDevice._sceneNumber == 4300) { + scene->_sceneMode = 4268; + scene->setAction(&scene->_sequenceManager, scene, 4268, this, NULL); + } else { + _globals->_events.setCursor(CURSOR_WALK); + ADD_MOVER_NULL(scene->_hotspot1, 241, 169); + scene->_sceneMode = 4261; + scene->setAction(&scene->_sequenceManager, scene, 4261, &_globals->_player, this, NULL); + } + break; + case OBJECT_NULLIFIER: + if (_globals->_inventory._helmet._sceneNumber == 4250) { + _globals->_soundHandler.startSound(353); + _globals->_player.disableControl(); + _globals->_inventory._helmet._sceneNumber = 1; + + scene->_sceneMode = 4257; + scene->setAction(&scene->_sequenceManager, scene, 4257, &_globals->_player, this, NULL); + } else { + SceneItem::display2(4250, 4); + } + break; + case CURSOR_TALK: + if (_globals->_inventory._helmet._sceneNumber == 4250) + doAction(OBJECT_HELMET); + else { + _globals->_player.disableControl(); + scene->_sceneMode = 4264; + scene->setAction(&scene->_sequenceManager, scene, 4264, this, NULL); + } + break; + case CURSOR_USE: + if (_globals->_inventory._helmet._sceneNumber == 4250) + doAction(OBJECT_HELMET); + else { + _globals->_player.disableControl(); + if ((_globals->_inventory._items._sceneNumber != 1) || (_globals->_inventory._concentrator._sceneNumber != 1)) { + scene->_sceneMode = 4258; + scene->setAction(&scene->_sequenceManager, scene, 4258, this, NULL); + } else { + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(4251); + scene->_hotspot2.setFrame(scene->_hotspot2.getFrameCount()); + scene->_hotspot2.setPosition(Common::Point(267, 172)); + scene->_hotspot2.hide(); + + scene->_sceneMode = 4259; + scene->setAction(&scene->_sequenceManager, scene, 4259, &_globals->_player, this, &scene->_hotspot2, NULL); + } + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4250::Hotspot8::doAction(int action) { + Scene4250 *scene = (Scene4250 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + case CURSOR_USE: + _globals->_sceneManager.changeScene(4300); + break; + case OBJECT_SCANNER: + SceneItem::display2(4250, 24); + break; + case OBJECT_STUNNER: + SceneItem::display2(4250, 25); + break; + case OBJECT_STASIS_NEGATOR: + _globals->_player.disableControl(); + scene->_sceneMode = 4270; + scene->setAction(&scene->_sequenceManager, scene, + (_globals->_inventory._helmet._sceneNumber == 4250) ? 4270 : 4271, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4250::Scene4250() : + _hotspot7(0, CURSOR_LOOK, 4250, 0, LIST_END) { +} + +void Scene4250::postInit(tSage::SceneObjectList *OwnerList) { + loadScene(4250); + Scene::postInit(); + setZoomPercents(160, 90, 185, 100); + + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerPText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerFLText); + + _speakerSText.setTextPos(Common::Point(40, 40)); + _speakerPText.setTextPos(Common::Point(40, 100)); + _hotspot8._sceneRegionId = 16; + + _globals->_player.postInit(); + _globals->_player.setVisage(2602); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(-13, 190)); + _globals->_player.changeZoom(-1); + _globals->_player._moveDiff = Common::Point(4, 1); + + _hotspot1.postInit(); + _hotspot1.setVisage(2801); + _hotspot1.animate(ANIM_MODE_1, NULL); + _hotspot1.setObjectWrapper(new SceneObjectWrapper()); + _hotspot1.setPosition(Common::Point(-18, 185)); + _hotspot1.changeZoom(-1); + _hotspot1._moveDiff = Common::Point(4, 1); + _globals->_sceneItems.push_back(&_hotspot1); + + if (_globals->_sceneManager._previousScene == 4300) { + _hotspot5.postInit(); + _hotspot5.setVisage(4250); + _hotspot5.setPosition(Common::Point(268, 168)); + _hotspot5.setPriority2(1); + + _hotspot4.postInit(); + _hotspot4.setVisage(2701); + _hotspot4.animate(ANIM_MODE_1, NULL); + _hotspot4.setObjectWrapper(new SceneObjectWrapper()); + _hotspot4.setPosition(Common::Point(272, 175)); + _hotspot4.setStrip(2); + _hotspot4._moveDiff = Common::Point(4, 1); + _hotspot4.changeZoom(70); + _globals->_sceneItems.push_back(&_hotspot4); + + _hotspot1.setPosition(Common::Point(197, 173)); + _hotspot1.changeZoom(70); + + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setPosition(Common::Point(252, 176)); + _globals->_player.changeZoom(70); + + _hotspot6.postInit(); + _hotspot6.setVisage(4302); + _hotspot6.setStrip(4); + _hotspot6.setFrame(3); + _hotspot6.changeZoom(50); + _hotspot6.setPriority2(70); + _hotspot6.setPosition(Common::Point(261, 175)); + + if (_globals->_inventory._helmet._sceneNumber == 4250) { + _hotspot6.setStrip(6); + _hotspot6.setFrame(_hotspot6.getFrameCount()); + } + + if (_globals->getFlag(98)) { + _globals->_sceneItems.push_front(&_hotspot6); + } else { + _hotspot6.hide(); + if ((_globals->_stripNum == 4300) || (_globals->_stripNum == 4301)) { + _globals->setFlag(98); + _globals->_player.setVisage(4302); + _globals->_player.setStrip(5); + _globals->_player.changeZoom(50); + _globals->_player.disableControl(); + + _hotspot4.setPosition(Common::Point(239, 195)); + _sceneMode = 4253; + _globals->_sceneItems.push_front(&_hotspot6); + + setAction(&_sequenceManager, this, 4253, &_globals->_player, NULL); + } + } + } else if (_globals->_stripNum == 9000) { + _hotspot4.postInit(); + _hotspot4.setVisage(2701); + _hotspot4.animate(ANIM_MODE_1, NULL); + _hotspot4.setObjectWrapper(new SceneObjectWrapper()); + _hotspot4.setPosition(Common::Point(-15, 195)); + _hotspot4._moveDiff = Common::Point(4, 1); + _globals->_sceneItems.push_back(&_hotspot4); + + setAction(&_action5); + } else { + _hotspot3.postInit(); + _hotspot3.setVisage(4006); + _hotspot3.animate(ANIM_MODE_1, NULL); + _hotspot3.setObjectWrapper(new SceneObjectWrapper()); + _hotspot3.setPosition(Common::Point(-15, 195)); + _hotspot3.setStrip2(3); + _hotspot3._moveDiff = Common::Point(4, 1); + + setAction(&_action1); + _globals->clearFlag(43); + _globals->clearFlag(114); + _globals->clearFlag(36); + } + + if (_globals->getFlag(17)) { + _globals->_sceneItems.push_back(&_hotspot8); + } else { + _hotspot2.postInit(); + _hotspot2.setVisage(4251); + _hotspot2.setStrip2(1); + _hotspot2.setPriority2(2); + _hotspot2.setFrame(1); + _hotspot2.setPosition(Common::Point(267, 172)); + + _globals->_sceneItems.push_back(&_hotspot2); + } + + _hotspot7.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _globals->_sceneItems.push_back(&_hotspot7); + _globals->_soundHandler.startSound(185); +} + +void Scene4250::signal() { + switch (_sceneMode) { + case 4252: + _globals->setFlag(17); + _globals->_sceneManager.changeScene(4301); + break; + case 4253: + if (_globals->_stripNum == 4301) { + ADD_MOVER_NULL(_hotspot1, 241, 169); + setAction(&_sequenceManager, this, 4261, &_globals->_player, &_hotspot6, NULL); + } else { + _globals->_player.enableControl(); + } + break; + case 4254: + case 4256: + case 4257: + case 4258: + case 4260: + case 4264: + case 4265: + case 4266: + case 4267: + case 4268: + case 4269: + case 4270: + _globals->_player.enableControl(); + break; + case 4255: + case 4262: + case 4263: + break; + case 4259: + _globals->_soundHandler.startSound(360); + _globals->_sceneManager.changeScene(9900); + break; + case 4261: + _globals->_inventory._keyDevice._sceneNumber = 1; + _globals->_player.enableControl(); + break; + } +} + +void Scene4250::dispatch() { + if (_globals->_player.getRegionIndex() == 8) + _globals->_player.changeZoom(90 - (_globals->_player._position.y - 153)); + if (_globals->_player.getRegionIndex() == 12) + _globals->_player.changeZoom(70); + if (_globals->_player.getRegionIndex() == 15) { + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(-1); + } + + if (_hotspot1.getRegionIndex() == 8) + _hotspot1.changeZoom(90 - (_hotspot1._position.y - 153)); + if (_hotspot1.getRegionIndex() == 12) + _hotspot1.changeZoom(70); + if (_hotspot1.getRegionIndex() == 15) { + _hotspot1.changeZoom(-1); + _hotspot1.setPriority2(-1); + } + + if (_hotspot4.getRegionIndex() == 8) + _hotspot4.changeZoom(90 - (_hotspot4._position.y - 153)); + if (_hotspot4.getRegionIndex() == 12) + _hotspot4.changeZoom(70); + if (_hotspot4.getRegionIndex() == 15) { + _hotspot4.changeZoom(-1); + _hotspot4.setPriority2(-1); + } + + Scene::dispatch(); + + if (!_action) { + if (!_globals->getFlag(55) && (_globals->_player.getRegionIndex() == 12)) { + setAction(&_action4); + } + + if (_globals->_sceneObjects->contains(&_hotspot6) && (_globals->_player.getRegionIndex() == 12)) + setAction(&_action4); + } +} + +/*-------------------------------------------------------------------------- + * Scene 4300 - Village - Slaver Ship + * + *--------------------------------------------------------------------------*/ + +void Scene4300::Action1::signal() { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->setFlag(56); + _globals->_scenePalette.addRotation(240, 254, -1); + scene->_hotspot7.animate(ANIM_MODE_6, this); + _globals->_soundHandler.startSound(164); + break; + case 1: + _globals->_soundHandler.startSound(340); + scene->_soundHandler1.startSound(341); + scene->_hotspot1.remove(); + setDelay(3); + break; + case 2: + scene->_soundHandler1.startSound(341); + scene->_hotspot2.remove(); + setDelay(6); + break; + case 3: + scene->_soundHandler1.startSound(341); + scene->_hotspot3.remove(); + setDelay(6); + break; + case 4: + scene->_soundHandler1.startSound(341); + scene->_hotspot4.remove(); + setDelay(12); + break; + case 5: + scene->_soundHandler1.startSound(341); + scene->_hotspot5.remove(); + setDelay(12); + break; + case 6: + scene->_soundHandler1.startSound(341); + scene->_hotspot6.remove(); + setDelay(60); + break; + case 7: + scene->_hotspot10.setPriority2(250); + scene->_hotspot10.animate(ANIM_MODE_5, this); + break; + case 8: + scene->_hotspot13.show(); + scene->_stripManager.start(8015, this, scene); + break; + case 9: + _globals->_soundHandler.startSound(350); + _globals->_sceneManager._fadeMode = FADEMODE_GRADUAL; + _globals->_events.setCursor(CURSOR_USE); + _globals->_player.enableControl(); + + remove(); + break; + } +} + +void Scene4300::Action2::signal() { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: + scene->_stripManager.start(8016, this, scene); + break; + case 2: + _globals->_player.enableControl(); + remove(); + break; + } +} + + +/*--------------------------------------------------------------------------*/ + +void Scene4300::Hotspot8::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, 15); + break; + case CURSOR_USE: + SceneItem::display2(4300, 18); + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 14); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 19); + break; + case OBJECT_KEY_DEVICE: + _globals->_inventory._keyDevice._sceneNumber = 4300; + _globals->_scenePalette.addRotation(240, 254, -1); + animate(ANIM_MODE_5, NULL); + + _globals->setFlag(99); + _globals->_sceneItems.push_back(this); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4300::Hotspot9::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if ((_globals->_inventory._stasisBox2._sceneNumber == 4300) || + (_globals->_inventory._concentrator._sceneNumber == 1)) + SceneItem::display2(4300, 7); + else + SceneItem::display2(4300, 1); + break; + case CURSOR_USE: + if ((_globals->_inventory._stasisBox2._sceneNumber == 4300) || + (_globals->_inventory._concentrator._sceneNumber == 1)) + SceneItem::display2(4300, 7); + else + SceneItem::display2(4300, 3); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 24); + break; + case OBJECT_SCANNER: + if ((_globals->_inventory._stasisBox2._sceneNumber == 4300) || + (_globals->_inventory._concentrator._sceneNumber != 1)) + SceneItem::display2(4300, 22); + else + SceneItem::display2(4300, 23); + break; + default: + NamedHotspot::doAction(action); + break; + } +} + +void Scene4300::Hotspot10::doAction(int action) { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, 2); + break; + case CURSOR_TALK: + _globals->_player.disableControl(); + scene->setAction(&scene->_action2); + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 20); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 21); + break; + case CURSOR_USE: + case OBJECT_HELMET: + _globals->_stripNum = (action == CURSOR_USE) ? 4300 : 4301; + _globals->_events.setCursor(CURSOR_NONE); + _globals->_sceneManager.changeScene(4250); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4300::Hotspot15::signal() { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + scene->_soundHandler2.startSound(345); + + _strip = (_globals->_randomSource.getRandomNumber(6) < 2) ? 2 : 1; + if ((_globals->_inventory._stasisBox2._sceneNumber == 4300) || + (_globals->_inventory._concentrator._sceneNumber == 1)) { + setStrip(1); + setFrame(1); + animate(ANIM_MODE_NONE, NULL); + } else { + animate(ANIM_MODE_5, this); + } +} + +void Scene4300::Hotspot16::doAction(int action) { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, 8); + break; + case CURSOR_USE: + if ((_globals->_inventory._stasisBox2._sceneNumber != 4300) && + (_globals->_inventory._concentrator._sceneNumber != 4300)) { + SceneItem::display2(4300, 16); + } else { + scene->_sceneMode = 4302; + scene->setAction(&scene->_sequenceManager, scene, 4302, this, NULL); + } + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 27); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 24); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene4300::Hotspot17::doAction(int action) { + Scene4300 *scene = (Scene4300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, (_globals->_inventory._stasisBox2._sceneNumber == 4300) ? 17 : 11); + break; + case CURSOR_USE: + if (_globals->_inventory._stasisBox2._sceneNumber != 4300) + SceneItem::display2(4300, 13); + else { + _globals->_scenePalette.clearListeners(); + remove(); + + SceneItem::display2(4300, 12); + _globals->_inventory._concentrator._sceneNumber = 1; + } + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 25); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 26); + break; + case OBJECT_STASIS_BOX2: + scene->_soundHandler1.startSound(352); + _globals->_events.setCursor(CURSOR_USE); + scene->_sceneMode = 4303; + + scene->setAction(&scene->_sequenceManager, scene, 4303, this, NULL); + break; + } +} + +void Scene4300::Hotspot19::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, 9); + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 28); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 24); + break; + case CURSOR_USE: + if ((_globals->_inventory._stasisBox2._sceneNumber != 4300) && + (_globals->_inventory._concentrator._sceneNumber != 4300)) + SceneItem::display2(4300, 10); + else + SceneItem::display2(4300, 29); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene4300::Scene4300() : + _hotspot18(0, CURSOR_LOOK, 4300, 0, LIST_END) { +} + +void Scene4300::postInit(SceneObjectList *OwnerList) { + loadScene(4300); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerFLText); + + _hotspot11.setup(76, 97, 102, 127, 4300, 5, 6); + + _hotspot7.postInit(); + _hotspot7.setPosition(Common::Point(90, 128)); + _hotspot7.setVisage(4303); + _hotspot7.setPriority2(250); + _globals->_sceneItems.push_back(&_hotspot7); + + _hotspot9.setup(120, 49, 174, 91, 4300, -1, -1); + + _hotspot15.postInit(); + _hotspot15.setVisage(4300); + _hotspot15.setPosition(Common::Point(149, 79)); + _hotspot15.signal(); + + if (!_globals->getFlag(99)) { + _hotspot8.postInit(); + _hotspot8.setVisage(4300); + _hotspot8.setStrip(3); + _hotspot8.setPosition(Common::Point(196, 47)); + _globals->_sceneItems.push_back(&_hotspot8); + } + + if (_globals->_inventory._concentrator._sceneNumber == 4300) { + _hotspot17.postInit(); + _hotspot17.setVisage(4300); + _hotspot17.setStrip(6); + _hotspot17.setPriority2(1); + _hotspot17.setPosition(Common::Point(200, 69)); + + if (_globals->_inventory._stasisBox2._sceneNumber == 4300) + _hotspot17.setFrame(_hotspot17.getFrameCount()); + + _globals->_sceneItems.push_back(&_hotspot17); + } + + if (!_globals->getFlag(98)) { + _hotspot10.postInit(); + _hotspot10.setVisage(4302); + _hotspot10.setPosition(Common::Point(244, 179)); + _hotspot10.setPriority2(100); + _globals->_sceneItems.push_back(&_hotspot10); + + _hotspot12.postInit(); + _hotspot12.setVisage(4302); + _hotspot12.setStrip2(3); + _hotspot12.setPosition(Common::Point(231, 185)); + _hotspot12.setPriority2(251); + _hotspot12.hide(); + + _hotspot13.postInit(); + _hotspot13.hide(); + _hotspot13.setVisage(4302); + _hotspot13.setStrip2(2); + _hotspot13.setPosition(Common::Point(256, 168)); + _hotspot13.setPriority2(251); + _hotspot13._numFrames = 1; + _hotspot13.animate(ANIM_MODE_8, 0, NULL); + } + + if (_globals->_inventory._items._sceneNumber == 4300) { + _hotspot16.postInit(); + _hotspot16.setVisage(4300); + _hotspot16.setPosition(Common::Point(169, 141)); + _hotspot16.setPriority2(1); + _hotspot16.setStrip(4); + _globals->_sceneItems.push_back(&_hotspot16); + } + + if (_globals->_sceneManager._previousScene == 4301) { + _globals->_player.disableControl(); + _hotspot7.setFrame(_hotspot7.getFrameCount()); + + _hotspot1.postInit(); + _hotspot1.setVisage(4301); + _hotspot1.setPriority2(145); + _hotspot1.setPosition(Common::Point(160, 64)); + + _hotspot2.postInit(); + _hotspot2.setVisage(4301); + _hotspot2.setStrip2(2); + _hotspot2.setPriority2(140); + _hotspot2.setPosition(Common::Point(166, 90)); + + _hotspot3.postInit(); + _hotspot3.setVisage(4301); + _hotspot3.setStrip2(3); + _hotspot3.setPriority2(135); + _hotspot3.setPosition(Common::Point(173, 114)); + + _hotspot4.postInit(); + _hotspot4.setVisage(4301); + _hotspot4.setStrip2(4); + _hotspot4.setPriority2(130); + _hotspot4.setPosition(Common::Point(187, 141)); + + _hotspot5.postInit(); + _hotspot5.setVisage(4301); + _hotspot5.setStrip2(5); + _hotspot5.setPriority2(125); + _hotspot5.setPosition(Common::Point(201, 164)); + + _hotspot6.postInit(); + _hotspot6.setVisage(4301); + _hotspot6.setStrip2(6); + _hotspot6.setPriority2(120); + _hotspot6.setPosition(Common::Point(219, 186)); + + setAction(&_action1); + } else { + _globals->_player.disableControl(); + _sceneMode = 4304; + setAction(&_sequenceManager, this, 4304, NULL); + } + + _hotspot10.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot19._sceneRegionId = 0; + _globals->_sceneItems.push_back(&_hotspot19); + _globals->_sceneItems.push_back(&_hotspot18); +} + +void Scene4300::stripCallback(int v) { + switch (v) { + case 1: + _hotspot12.show(); + _hotspot12.animate(ANIM_MODE_7, 0, NULL); + break; + case 2: + _hotspot12.hide(); + break; + } +} + +void Scene4300::remove() { + _globals->_scenePalette.clearListeners(); + Scene::remove(); +} + +void Scene4300::signal() { + switch (_sceneMode) { + case 4302: + _globals->_inventory._items._sceneNumber = 1; + _hotspot16.remove(); + _globals->_player.enableControl(); + break; + case 4303: + _globals->_inventory._stasisBox2._sceneNumber = 4300; + _hotspot15.setStrip(1); + _hotspot15.setFrame(1); + _hotspot15.animate(ANIM_MODE_NONE, NULL); + break; + case 4304: + _hotspot14.postInit(); + _hotspot14.setVisage(4300); + _hotspot14.setStrip(7); + _hotspot14.setPosition(Common::Point(60, 199)); + + _gfxButton.setText(EXIT_MSG); + _gfxButton._bounds.centre(60, 193); + _gfxButton.draw(); + _gfxButton._bounds.expandPanes(); + + _globals->_player.enableControl(); + _globals->_scenePalette.addRotation(240, 254, -1); + break; + } +} + +void Scene4300::dispatch() { + if (_action) + _action->dispatch(); +} + +void Scene4300::process(Event &event) { + Scene::process(event); + if (_gfxButton.process(event)) + _globals->_sceneManager.changeScene(4250); +} + +/*-------------------------------------------------------------------------- + * Scene 4301 - Village - Slaver Ship Keypad + * + *--------------------------------------------------------------------------*/ + +void Scene4301::Action1::synchronise(Serialiser &s) { + Action::synchronise(s); + s.syncAsSint16LE(_field34E); + for (int idx = 0; idx < 6; ++idx) + s.syncAsSint16LE(_indexList[idx]); +} + +void Scene4301::Action1::remove() { + Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene; + _globals->_player.enableControl(); + + for (_state = 0; _state < 6; ++_state) + _buttonList[_state].remove(); + + scene->_hotspot3.remove(); + scene->_hotspot2.remove(); + + scene->_hotspot1.animate(ANIM_MODE_6, NULL); + Action::remove(); +} + +void Scene4301::Action1::signal() { + Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + scene->_soundHandler.startSound(164); + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 1: + _globals->_soundHandler.startSound(335); + _globals->_events.setCursor(CURSOR_USE); + + scene->_hotspot2.postInit(); + scene->_hotspot2.setVisage(4303); + scene->_hotspot2.setStrip(2); + scene->_hotspot2.setFrame(1); + scene->_hotspot2.setPosition(Common::Point(30, 15)); + scene->_hotspot2.setPriority2(255); + + scene->_hotspot3.postInit(); + scene->_hotspot3.setVisage(4303); + scene->_hotspot3.setStrip(2); + scene->_hotspot3.setFrame(2); + scene->_hotspot3.setPosition(Common::Point(48, 29)); + scene->_hotspot3.setPriority2(255); + scene->_hotspot3.hide(); + + _field34E = 0; + _state = 0; + _actionIndex = 2; + break; + case 10: + _globals->_events.setCursor(CURSOR_NONE); + scene->_soundHandler.startSound(337); + if (scene->_hotspot3._flags & OBJFLAG_HIDE) + scene->_hotspot3.show(); + else + scene->_hotspot3.hide(); + setDelay(20); + + if (_state <= 8) + _actionIndex = 10; + ++_state; + break; + case 11: + for (_state = 0; _state < 6; ++_state) + _buttonList[_state].remove(); + + scene->_soundHandler.startSound(338); + scene->_hotspot3.hide(); + + _actionIndex = 2; + _state = 0; + _globals->_events.setCursor(CURSOR_USE); + break; + case 20: + _globals->_player.disableControl(); + scene->_soundHandler.startSound(339); + scene->_hotspot3._frame = 3; + if (scene->_hotspot3._flags & OBJFLAG_HIDE) + scene->_hotspot3.show(); + else + scene->_hotspot3.hide(); + + if (_state <= 8) + _actionIndex = 20; + ++_state; + + setDelay(20); + break; + case 21: + scene->_field68E = true; + remove(); + break; + } +} + +void Scene4301::Action1::process(Event &event) { + Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene; + Rect buttonsRect; + + Action::process(event); + if (event.handled || (_actionIndex != 2)) + return; + + buttonsRect = Rect(14, 35, 112, 100); + buttonsRect.translate(30, 15); + + if ((event.eventType == EVENT_BUTTON_DOWN) && buttonsRect.contains(event.mousePos)) { + event.handled = true; + scene->_soundHandler.startSound(336); + + int buttonIndex = ((event.mousePos.y - buttonsRect.top) / 33) * 3 + + ((event.mousePos.x - buttonsRect.left) / 33); + + _buttonList[_state].postInit(); + _buttonList[_state].setVisage(4303); + _buttonList[_state].setStrip(buttonIndex + 3); + _buttonList[_state].setFrame(1); + _buttonList[_state].setPosition(Common::Point((_state % 3) * 25 + 55, (_state / 3) * 25 + 121)); + _buttonList[_state].setPriority2(255); + _buttonList[_state]._numFrames = 25; + _buttonList[_state].animate(ANIM_MODE_5, NULL); + + _indexList[_state++] = buttonIndex; + + if (_state == 6) { + // Six buttons pressed + if ((_indexList[0] == 2) && (_indexList[1] == 3) && (_indexList[2] == 0) && + (_indexList[3] == 4) && (_indexList[4] == 1) && (_indexList[5] == 5)) { + // Entered the correct full combination + _state = 0; + _actionIndex = 20; + } else { + // Incorrect combination entered + _state = 0; + _actionIndex = 10; + } + + signal(); + } + } + + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_ESCAPE)) { + event.handled = true; + remove(); + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4301::Hotspot4::doAction(int action) { + Scene4301 *scene = (Scene4301 *)_globals->_sceneManager._scene; + + if (action == CURSOR_USE) { + _globals->_player.disableControl(); + scene->setAction(&scene->_action1); + } else { + NamedHotspot::doAction(action); + } +} + +void Scene4301::Hotspot5::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(4300, 0); + break; + case CURSOR_USE: + SceneItem::display(4300, 30); + break; + case OBJECT_SCANNER: + SceneItem::display2(4300, 31); + break; + case OBJECT_STUNNER: + SceneItem::display2(4300, 32); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene4301::postInit(SceneObjectList *OwnerList) { + _globals->setFlag(50); + loadScene(4301); + Scene::postInit(); + setZoomPercents(0, 100, 200, 100); + + _field68E = false; + _globals->_inventory._stasisBox2._sceneNumber = 1; + _hotspot4.setup(76, 97, 102, 127, 4300, 5, 6); + + _hotspot1.postInit(); + _hotspot1.setPosition(Common::Point(90, 128)); + _hotspot1.setVisage(4303); + _hotspot1._strip = 1; + _hotspot1._frame = 1; + _hotspot1.setPriority2(250); + + _hotspot5.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _globals->_sceneItems.push_back(&_hotspot5); + + _globals->_player.enableControl(); +} + +void Scene4301::dispatch() { + if (_action) { + _action->dispatch(); + } else if (_field68E) { + _field68E = 0; + _globals->clearFlag(50); + _globals->_sceneManager._fadeMode = FADEMODE_NONE; + _globals->_sceneManager.setNewScene(4300); + } +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes5.h b/engines/tsage/ringworld_scenes5.h new file mode 100644 index 0000000000..0def49ebe6 --- /dev/null +++ b/engines/tsage/ringworld_scenes5.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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES5_H +#define TSAGE_RINGWORLD_SCENES5_H + +#include "common/scummsys.h" +#include "tsage/core.h" +#include "tsage/converse.h" +#include "tsage/ringworld_logic.h" + +namespace tSage { + +class Scene4000 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + class Action9 : public Action { + public: + virtual void signal(); + }; + class Action10 : public Action { + public: + virtual void signal(); + }; + class Action11 : public Action { + public: + virtual void signal(); + }; + class Action12 : public Action { + public: + virtual void signal(); + }; + class Action13 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + private: + int _ctr; + public: + virtual void synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsUint16LE(_ctr); + } + virtual void doAction(int action); + }; + class Hotspot9 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot12 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot13 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot17 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot18 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot23 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager1, _sequenceManager2, _sequenceManager3; + SoundHandler _soundHandler1, _soundHandler2; + SpeakerQR _speakerQR; + SpeakerML _speakerML; + SpeakerMR _speakerMR; + SpeakerSR _speakerSR; + SpeakerCHFL _speakerCHFL; + SpeakerPL _speakerPL; + SpeakerPText _speakerPText; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SpeakerCHFR _speakerCHFR; + SpeakerQL _speakerQL; + SpeakerCHFText _speakerCHFText; + SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5, _hotspot6; + Hotspot7 _hotspot7; + Hotspot8 _hotspot8; + Hotspot9 _hotspot9; + Hotspot10 _hotspot10; + DisplayHotspot _hotspot11; + Hotspot12 _hotspot12; + Hotspot13 _hotspot13; + Hotspot _hotspot14, _hotspot15, _hotspot16; + Hotspot17 _hotspot17; + Hotspot18 _hotspot18; + DisplayHotspot _hotspot19, _hotspot20, _hotspot21, _hotspot22; + Hotspot23 _hotspot23; + DisplayHotspot _hotspot24, _hotspot25, _hotspot26; + SceneObject _hotspot27; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + Action9 _action9; + Action10 _action10; + Action11 _action11; + Action12 _action12; + Action13 _action13; + + Scene4000(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4010 : public Scene { +public: + SequenceManager _sequenceManager; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SceneObject _hotspot1, _hotspot2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); +}; + +class Scene4025 : public Scene { + /* Custom classes */ + class Peg; + + class Hole : public SceneObject { + public: + Peg *_pegPtr; + int _armStrip; + Common::Point _newPosition; + + virtual void synchronise(Serialiser &s); + virtual void doAction(int action); + }; + class Peg : public SceneObject { + public: + int _field88; + int _armStrip; + + Peg() : SceneObject() { _field88 = 0; _armStrip = 3; } + virtual void synchronise(Serialiser &s); + virtual void doAction(int action); + }; + + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; +public: + SequenceManager _sequenceManager; + GfxButton _gfxButton; + SceneObject _armHotspot; + Hole _hole1, _hole2, _hole3, _hole4, _hole5; + Peg _peg1, _peg2, _peg3, _peg4, _peg5; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Peg *_pegPtr, *_pegPtr2; + Hole *_holePtr; + + Scene4025(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronise(Serialiser &s); + virtual void remove(); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); +}; + +class Scene4045 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + +public: + SequenceManager _sequenceManager; + SpeakerQR _speakerQR; + SpeakerML _speakerML; + SpeakerPR _speakerPR; + SpeakerPText _speakerPText; + SpeakerQText _speakerQText; + SpeakerQL _speakerQL; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + DisplayHotspot _hotspot3; + SceneObject _hotspot4, _hotspot5; + Hotspot6 _hotspot6; + DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13, _hotspot14; + Action1 _action1; + Action _action2; + Action _action3; + + Scene4045(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void stripCallback(int v); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4050 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot17 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SpeakerPText _speakerPText; + SpeakerQText _speakerQText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + DisplayHotspot _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5; + DisplayHotspot _hotspot6, _hotspot7, _hotspot8, _hotspot9, _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13; + Hotspot14 _hotspot14; + SceneObject _hotspot15, _hotspot16; + Hotspot17 _hotspot17; + + Scene4050(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4100 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SpeakerMText _speakerMText; + SpeakerML _speakerML; + SpeakerQText _speakerQText; + SpeakerQR _speakerQR; + SpeakerCHFText _speakerCHFText; + SpeakerCDRText _speakerCDRText; + SpeakerCDR _speakerCDR; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + DisplayHotspot _hotspot3, _hotspot4; + Hotspot5 _hotspot5; + Hotspot6 _hotspot6; + DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13; + Hotspot14 _hotspot14; + + Scene4100(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4150 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class HotspotGroup1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class HotspotGroup3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class HotspotGroup6 : public SceneObject { + public: + virtual void doAction(int action); + }; + + class Hotspot3 : public SceneObject { + public: + virtual void doAction(int action); + }; + +public: + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + SpeakerQText _speakerQText; + SpeakerQR _speakerQR; + SpeakerCDL _speakerCDL; + Action1 _action1; + Action2 _action2; + Action3 _action3; + DisplayHotspot _hotspot1, _hotspot2; + Hotspot3 _hotspot3; + SceneObject _hotspot4; + HotspotGroup1 _hotspot5, _hotspot6; + DisplayHotspot _hotspot7, _hotspot8, _hotspot9, _hotspot10, _hotspot11, _hotspot12; + HotspotGroup3 _hotspot13, _hotspot14, _hotspot15, _hotspot16; + DisplayHotspot _hotspot17, _hotspot18, _hotspot19, _hotspot20, _hotspot21; + DisplayHotspot _hotspot22, _hotspot23, _hotspot24; + HotspotGroup6 _hotspot25, _hotspot26; + + Scene4150(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4250 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + +public: + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + SpeakerSR _speakerSR; + SpeakerSL _speakerSL; + SpeakerSText _speakerSText; + SpeakerGameText _speakerGameText; + SpeakerQL _speakerQL; + SpeakerQR _speakerQR; + SpeakerQText _speakerQText; + SpeakerPText _speakerPText; + SpeakerMText _speakerMText; + SpeakerFLText _speakerFLText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + SceneObject _hotspot3; + Hotspot4 _hotspot4; + SceneObject _hotspot5; + Hotspot6 _hotspot6; + DisplayHotspot _hotspot7; + Hotspot8 _hotspot8; + + Scene4250(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene4300 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot9 : public NamedHotspot { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot15 : public SceneObject { + public: + virtual void signal(); + }; + class Hotspot16 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot17 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot19 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler1, _soundHandler2; + SequenceManager _sequenceManager; + GfxButton _gfxButton; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + SpeakerMText _speakerMText; + SpeakerFLText _speakerFLText; + + SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4; + SceneObject _hotspot5, _hotspot6, _hotspot7; + Hotspot8 _hotspot8; + Hotspot9 _hotspot9; + Hotspot10 _hotspot10; + NamedHotspot _hotspot11; + SceneObject _hotspot12, _hotspot13, _hotspot14; + Hotspot15 _hotspot15; + Hotspot16 _hotspot16; + Hotspot17 _hotspot17; + DisplayHotspot _hotspot18; + Hotspot19 _hotspot19; + Action1 _action1; + Action2 _action2; + + Scene4300(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void stripCallback(int v); + virtual void remove(); + virtual void signal(); + virtual void dispatch(); + virtual void process(Event &event); +}; + +class Scene4301 : public Scene { + /* Actions */ + class Action1 : public ActionExt { + public: + SceneObject _buttonList[6]; + int _field34E; + int _indexList[6]; + + virtual void synchronise(Serialiser &s); + virtual void remove(); + virtual void signal(); + virtual void process(Event &event); + }; + + /* Hotspots */ + class Hotspot4 : public NamedHotspot { + public: + virtual void doAction(int action); + }; + class Hotspot5 : public NamedHotspot { + public: + virtual void doAction(int action); + }; + +public: + Common::List<int> _list1; + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + Action1 _action1; + SceneObject _hotspot1, _hotspot2, _hotspot3; + Hotspot4 _hotspot4; + Hotspot5 _hotspot5; + bool _field68E; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void dispatch(); + virtual void synchronise(Serialiser &s) { + Scene::synchronise(s); + s.syncAsSint16LE(_field68E); + } +}; + + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes6.cpp b/engines/tsage/ringworld_scenes6.cpp new file mode 100644 index 0000000000..3ea4d7b279 --- /dev/null +++ b/engines/tsage/ringworld_scenes6.cpp @@ -0,0 +1,2173 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/ringworld_scenes6.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 5000 - Caverns - Entrance + * + *--------------------------------------------------------------------------*/ + +void Scene5000::Action1::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_soundHandler.startSound(190); + scene->_soundHandler.proc5(true); + ADD_MOVER(scene->_hotspot1, 283, 12); + break; + case 2: + break; + case 3: + scene->_hotspot1._moveDiff.y = 1; + scene->_hotspot4.setPosition(Common::Point(scene->_hotspot1._position.x, + scene->_hotspot1._position.y + 15)); + scene->_hotspot4.show(); + setDelay(15); + break; + case 4: + scene->_soundHandler.proc4(); + ADD_MOVER(scene->_hotspot1, 233, 80); + break; + case 5: + scene->_hotspot3.animate(ANIM_MODE_8, 0, NULL); + scene->_hotspot3.show(); + ADD_MOVER(scene->_hotspot1, 233, 90); + break; + case 6: + scene->_hotspot3.remove(); + scene->_hotspot2.setPosition(Common::Point(233, 76)); + scene->_hotspot2.show(); + scene->_hotspot2.animate(ANIM_MODE_5, this); + + scene->_hotspot4.remove(); + break; + case 7: + setDelay(60); + scene->_hotspot2.remove(); + break; + case 8: + scene->_hotspot5.show(); + scene->_hotspot5.animate(ANIM_MODE_5, this); + break; + case 9: + scene->setAction(&scene->_action2); + break; + } +} + +void Scene5000::Action1::dispatch() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + Action::dispatch(); + + if (_actionIndex == 3) { + if (scene->_hotspot1._percent % 2 == 0) { + ++scene->_hotspot1._position.y; + if (scene->_hotspot1._position.x > 233) + --scene->_hotspot1._position.x; + } + + scene->_hotspot1.changeZoom(++scene->_hotspot1._percent); + scene->_hotspot1._flags |= OBJFLAG_PANES; + + if (scene->_hotspot1._percent >= 100) + signal(); + } + + if ((_actionIndex == 5) || (_actionIndex == 6)) { + scene->_hotspot4.setPosition(Common::Point(scene->_hotspot1._position.x, + scene->_hotspot1._position.y + 15)); + } +} + +void Scene5000::Action2::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.setPosition(Common::Point(217, 76)); + setDelay(10); + break; + case 1: + _globals->_player.setStrip2(3); + _globals->_player.animate(ANIM_MODE_1, NULL); + ADD_MOVER(_globals->_player, 214, 89); + break; + case 2: + if (!_globals->getFlag(59)) + setAction(&scene->_action3, this); + _globals->_player.setPriority2(15); + ADD_MOVER(_globals->_player, 208, 100); + break; + case 3: + ADD_MOVER(_globals->_player, 213, 98); + break; + case 4: + ADD_MOVER(_globals->_player, 215, 115); + break; + case 5: + _globals->_player.changeZoom(47); + ADD_MOVER(_globals->_player, 220, 125); + break; + case 6: + ADD_MOVER(_globals->_player, 229, 115); + break; + case 7: + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(35); + ADD_MOVER(_globals->_player, 201, 166); + break; + case 8: + _globals->_player.updateZoom(); + ADD_MOVER(_globals->_player, 205, 146); + break; + case 9: + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(50); + ADD_MOVER(_globals->_player, 220, 182); + break; + case 10: + _globals->_player.updateZoom(); + ADD_MOVER(_globals->_player, 208, 163); + break; + case 11: + _globals->_player.changeZoom(-1); + _globals->_player.setStrip2(-1); + _globals->_player.setPriority2(-1); + ADD_MOVER(_globals->_player, 208, 175); + break; + case 12: + _globals->_player.setStrip(8); + _globals->_player.setFrame(1); + setDelay(10); + break; + case 13: + if (!_globals->_sceneObjects->contains(&scene->_hotspot7)) + setDelay(10); + break; + case 14: + setDelay(30); + break; + case 15: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene5000::Action3::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(10); + break; + case 1: + scene->_hotspot7.postInit(); + scene->_hotspot7.setVisage(2809); + scene->_hotspot7.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot7.setPosition(Common::Point(217, 76)); + scene->_hotspot7.changeZoom(10); + scene->_hotspot7.setStrip2(3); + scene->_hotspot7.setPriority2(200); + scene->_hotspot7._moveDiff.y = 2; + scene->_hotspot7.animate(ANIM_MODE_1, NULL); + ADD_MOVER(scene->_hotspot7, 214, 89); + + _globals->_sceneItems.push_front(&scene->_hotspot7); + break; + case 2: + scene->_hotspot7.changeZoom(-1); + scene->_hotspot7.setPriority2(14); + ADD_MOVER(scene->_hotspot7, 208, 100); + break; + case 3: + ADD_MOVER(scene->_hotspot7, 213, 98); + break; + case 4: + scene->_hotspot7.setPriority2(19); + ADD_MOVER(scene->_hotspot7, 213, 98); + break; + case 5: + scene->_hotspot7.changeZoom(46); + ADD_MOVER(scene->_hotspot7, 220, 125); + break; + case 6: + ADD_MOVER(scene->_hotspot7, 229, 115); + break; + case 7: + scene->_hotspot7.changeZoom(-1); + scene->_hotspot7.setPriority2(34); + ADD_MOVER(scene->_hotspot7, 201, 166); + break; + case 8: + scene->_hotspot7.updateZoom(); + ADD_MOVER(scene->_hotspot7, 205, 146); + break; + case 9: + scene->_hotspot7.changeZoom(-1); + scene->_hotspot7.setPriority2(49); + ADD_MOVER(scene->_hotspot7, 210, 182); + break; + case 10: + scene->_hotspot7.updateZoom(); + ADD_MOVER(scene->_hotspot7, 208, 163); + break; + case 11: + scene->_hotspot7.changeZoom(-1); + scene->_hotspot7.setStrip2(-1); + scene->_hotspot7.setPriority2(-1); + ADD_MOVER(scene->_hotspot7, 175, 166); + break; + case 12: + ADD_MOVER(scene->_hotspot7, 126, 146); + break; + case 13: + scene->_hotspot7.setStrip(2); + remove(); + break; + } +} + +void Scene5000::Action4::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: + _globals->_player.setPriority2(50); + _globals->_player.setStrip2(4); + ADD_MOVER(_globals->_player, 210, 182); + break; + case 2: + ADD_MOVER(_globals->_player, 205, 146); + break; + case 3: + _globals->_player.setPriority2(35); + ADD_MOVER(_globals->_player, 201, 166); + break; + case 4: + ADD_MOVER(_globals->_player, 229, 115); + break; + case 5: + _globals->_player.setPriority2(20); + _globals->_player.changeZoom(47); + ADD_MOVER(_globals->_player, 220, 125); + break; + case 6: + ADD_MOVER(_globals->_player, 215, 115); + break; + case 7: + _globals->_player.changeZoom(-1); + ADD_MOVER(_globals->_player, 213, 98); + break; + case 8: + _globals->_player.setPriority2(15); + ADD_MOVER(_globals->_player, 208, 100); + break; + case 9: + ADD_MOVER(_globals->_player, 214, 89); + break; + case 10: + ADD_MOVER(_globals->_player, 217, 76); + break; + case 11: + _globals->_player.hide(); + setDelay(60); + break; + case 12: + if (!_globals->_sceneObjects->contains(&scene->_hotspot7)) + _globals->_sceneManager.changeScene(2320); + remove(); + break; + } +} + +void Scene5000::Action5::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_MOVER(_globals->_player, 91, 155); + break; + case 1: + _globals->_player.setVisage(2670); + _globals->_player._strip = 4; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + SceneItem::display2(5000, _globals->_sceneObjects->contains(&scene->_hotspot7) ? 17 : 13); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + _globals->_player.setVisage(0); + _globals->_player._strip = 8; + _globals->_player.animate(ANIM_MODE_1, NULL); + + _globals->_player.enableControl(); + remove(); + } +} + +void Scene5000::Action6::signal() { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + _globals->_events.setCursor(CURSOR_WALK); + scene->_stripManager.start(2150, this); + break; + case 2: + _globals->_events.setCursor(CURSOR_NONE); + scene->setAction(&scene->_sequenceManager, this, 5001, &scene->_hotspot7, NULL); + break; + case 3: + ADD_PLAYER_MOVER(208, 163); + break; + case 4: + _globals->_player.setPriority2(50); + _globals->_player.setStrip2(4); + ADD_MOVER(_globals->_player, 210, 182); + break; + case 5: + _globals->_sceneManager.changeScene(2100); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene5000::Hotspot7::doAction(int action) { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5000, 12); + break; + case CURSOR_TALK: + setAction(&scene->_action6); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5000::Hotspot8::doAction(int action) { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5000, 10); + break; + case OBJECT_STUNNER: + SceneItem::display2(5000, 14); + break; + case OBJECT_SCANNER: + setAction(&scene->_action5); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5000::HotspotGroup1::doAction(int action) { + Scene5000 *scene = (Scene5000 *)_globals->_sceneManager._scene; + + if (_globals->_sceneObjects->contains(&scene->_hotspot7)) + scene->setAction(&scene->_action6); + else + SceneItem::display2(5000, 11); +} +/*--------------------------------------------------------------------------*/ + +Scene5000::Scene5000() : + _hotspot1(0, CURSOR_LOOK, 5000, 3, LIST_END), + _hotspot12(0, CURSOR_LOOK, 5000, 6, CURSOR_USE, 5000, 7, OBJECT_STUNNER, 5000, 14, + OBJECT_SCANNER, 5000, 16, LIST_END), + _hotspot13(0, CURSOR_LOOK, 5000, 8, CURSOR_USE, 5000, 9, OBJECT_STUNNER, 5000, 0, + OBJECT_SCANNER, 5000, 16, LIST_END), + _hotspot14(0, CURSOR_LOOK, 5000, 8, CURSOR_USE, 5000, 9, OBJECT_STUNNER, 5000, 0, + OBJECT_SCANNER, 5000, 16, LIST_END), + _hotspot15(0, CURSOR_LOOK, 5000, 2, OBJECT_STUNNER, 5000, 15, LIST_END), + _hotspot16(0, CURSOR_LOOK, 5000, 4, CURSOR_USE, 5000, 5, LIST_END), + _hotspot17(0, CURSOR_LOOK, 5000, 1, LIST_END), + _hotspot18(0, CURSOR_LOOK, 5000, 0, LIST_END) { +} + + +void Scene5000::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + loadScene(5000); + + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerQText); + + _globals->_player.postInit(); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player._moveDiff = Common::Point(4, 2); + _globals->_player.changeZoom(-1); + _globals->_player.disableControl(); + + _hotspot1.postInit(); + _hotspot1.setVisage(5001); + _hotspot1.setFrame2(1); + _hotspot1._moveDiff = Common::Point(5, 5); + _hotspot1.setPriority2(10); + _hotspot1.changeZoom(10); + + _hotspot4.postInit(); + _hotspot4.setVisage(5001); + _hotspot4.setStrip2(2); + _hotspot4._moveDiff = Common::Point(5, 1); + _hotspot4.setPriority2(10); + _hotspot4.changeZoom(100); + _hotspot4.animate(ANIM_MODE_8, 0, NULL); + _hotspot4.hide(); + + _hotspot2.postInit(); + _hotspot2.setVisage(5001); + _hotspot2.setStrip2(3); + _hotspot2._numFrames = 5; + _hotspot2.hide(); + + _hotspot3.postInit(); + _hotspot3.setVisage(5001); + _hotspot3.setStrip2(5); + _hotspot3._numFrames = 5; + _hotspot3.setPosition(Common::Point(233, 76)); + _hotspot3.hide(); + + _hotspot5.postInit(); + _hotspot5.setVisage(5001); + _hotspot5.setStrip2(4); + _hotspot5._numFrames = 5; + _hotspot5.setPriority2(15); + _hotspot5.setPosition(Common::Point(218, 76)); + _hotspot5.hide(); + + _hotspot9.postInit(); + _hotspot9.setVisage(5002); + _hotspot9.setPriority2(80); + _hotspot9.setPosition(Common::Point(71, 174)); + + _hotspot10.postInit(); + _hotspot10.setVisage(5002); + _hotspot10.setStrip2(2); + _hotspot10.setPosition(Common::Point(87, 120)); + + _hotspot11.postInit(); + _hotspot11.setVisage(5002); + _hotspot11.setStrip2(2); + _hotspot11.setFrame(3); + _hotspot10.setPosition(Common::Point(93, 118)); + + setZoomPercents(95, 10, 145, 100); + + _hotspot8.setBounds(Rect(0, 73, 87, 144)); + _hotspot18.setBounds(Rect(54, 0, 319, 85)); + _hotspot17.setBounds(Rect(184, 0, 199, 79)); + _hotspot13.setBounds(Rect(0, 164, 135, 200)); + _hotspot14.setBounds(Rect(0, 0, 105, 140)); + _hotspot15.setBounds(Rect(266, 70, 291, 85)); + _hotspot16.setBounds(Rect(0, 86, 3219, 200)); + _hotspot12.setBounds(Rect(230, 143, 244, 150)); + + _globals->_sceneItems.addItems(&_hotspot9, &_hotspot10, &_hotspot11, &_hotspot8, &_hotspot13, + &_hotspot14, &_hotspot12, &_hotspot15, &_hotspot17, &_hotspot18, &_hotspot16, NULL); + + switch (_globals->_sceneManager._previousScene) { + case 1000: + case 2100: + case 2320: + if (_globals->getFlag(59)) { + _hotspot1.setPosition(Common::Point(233, 90)); + _hotspot1.changeZoom(100); + _hotspot1.show(); + + _hotspot5.setFrame(1); + _hotspot5.animate(ANIM_MODE_5, NULL); + _hotspot5.setPosition(Common::Point(218, 76)); + _hotspot5.show(); + + _globals->_player.setPosition(Common::Point(217, -10)); + _globals->_player.disableControl(); + + setAction(&_action2); + } else { + _globals->_player.setPosition(Common::Point(217, -10)); + _hotspot1.setPosition(Common::Point(320, -10)); + _globals->_player.disableControl(); + + setAction(&_action1); + } + break; + default: + _globals->_player.disableControl(); + _globals->_player.setPosition(Common::Point(0, 146)); + + _hotspot1.changeZoom(100); + _hotspot1.setPosition(Common::Point(233, 90)); + _hotspot1.show(); + + _hotspot5.setFrame(_hotspot5.getFrameCount()); + _hotspot5.show(); + + _sceneMode = 5004; + setAction(&_sequenceManager, this, 5004, &_globals->_player, NULL); + break; + } + + _globals->_soundHandler.startSound(190); +} + +void Scene5000::signal() { + switch (_sceneMode) { + case 5002: + case 5003: + case 5004: + _globals->_player.enableControl(); + break; + case 5005: + _globals->_sceneManager.changeScene(5100); + break; + } +} + +void Scene5000::dispatch() { + Scene::dispatch(); + + if (!_action) { + if (!_globals->_sceneObjects->contains(&_hotspot7) && (_globals->_player.getRegionIndex() == 10)) { + _globals->_player.disableControl(); + _sceneMode = 5005; + setAction(&_sequenceManager, this, 5005, &_globals->_player, NULL); + } + + if (_globals->_player.getRegionIndex() == 8) { + _globals->_player.disableControl(); + + if (_globals->_sceneObjects->contains(&_hotspot7)) { + _sceneMode = 5003; + _globals->_player.addMover(NULL); + setAction(&_sequenceManager, this, 5003, &_globals->_player, NULL); + } else { + setAction(&_action4); + } + } + + if (_globals->_sceneObjects->contains(&_hotspot7) && (_globals->_player.getRegionIndex() == 15)) { + _sceneMode = 5002; + _globals->_player.disableControl(); + _globals->_player.addMover(NULL); + setAction(&_sequenceManager, this, 5002, &_globals->_player, NULL); + } + } +} + +/*-------------------------------------------------------------------------- + * Scene 5100 - Caverns + * + *--------------------------------------------------------------------------*/ + +void Scene5100::Action1::signal() { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + ADD_MOVER(_globals->_player, 1111, 165); + break; + case 2: + _globals->_player.setStrip(6); + _globals->_player.setFrame(1); + setDelay(60); + break; + case 3: + if (_globals->getFlag(10)) { + _globals->_player.enableControl(); + remove(); + } else { + _globals->setFlag(10); + scene->_stripManager.start(5102, this); + } + break; + case 4: + scene->_soundHandler.startSound(206); + + scene->_hotspot5.postInit(); + scene->_hotspot5.setVisage(5362); + scene->_hotspot5.setPosition(Common::Point(1160, 34)); + scene->_hotspot5.setStrip2(2); + scene->_hotspot5.animate(ANIM_MODE_1, NULL); + scene->_hotspot5.setPriority2(10); + + _globals->_sceneItems.push_front(&scene->_hotspot5); + ADD_MOVER(scene->_hotspot5, 999, 14); + break; + case 5: + scene->_hotspot5.setStrip2(4); + scene->_hotspot5._frame = 1; + scene->_hotspot5.animate(ANIM_MODE_5, this); + break; + case 6: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene5100::Action2::signal() { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(5); + break; + case 1: + if (scene->_hotspot8._visage == 2806) + setDelay(1); + else + scene->_hotspot8.animate(ANIM_MODE_5, this); + break; + case 2: + if (scene->_hotspot8._visage != 2806) { + scene->_hotspot8.setVisage(2806); + scene->_hotspot8.setPosition(Common::Point(548, 193)); + scene->_hotspot8.animate(ANIM_MODE_1, NULL); + scene->_hotspot8._angle = 325; + scene->_hotspot8.setObjectWrapper(new SceneObjectWrapper()); + scene->_hotspot8.setStrip(8); + } + + scene->_stripManager.start(5129, this); + break; + case 3: + if (_globals->_player._position.x >= 966) { + ADD_PLAYER_MOVER(1215, 155); + } else { + ADD_PLAYER_MOVER_THIS(scene->_hotspot8, 966, 185); + } + + if (_globals->_player._position.x >= 966) { + setDelay(1); + } else { + ADD_PLAYER_MOVER(966, 190); + } + break; + case 4: + ADD_PLAYER_MOVER_THIS(scene->_hotspot8, 1215, 155); + ADD_PLAYER_MOVER(1215, 155); + break; + case 5: + _globals->_sceneManager.changeScene(2100); + break; + } +} + +void Scene5100::Action3::signal() { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->setFlag(62); + _globals->_player.disableControl(); + _globals->_player.addMover(NULL); + + scene->_hotspot2.addMover(NULL); + scene->_hotspot3.addMover(NULL); + _globals->_player.setVisage(2672); + + if (static_cast<SceneObject *>(_owner)->_position.x >= _globals->_player._position.x) + _globals->_player._strip = 4; + else + _globals->_player._strip = 3; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 1: + _globals->_player.setVisage(2674); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 2: + scene->_soundHandler.startSound(28); + if (static_cast<SceneObject *>(_owner)->_position.x < _globals->_player._position.x) { + scene->_hotspot2.setVisage(5130); + scene->_hotspot2._strip = 1; + scene->_hotspot2._frame = 1; + scene->_hotspot2.animate(ANIM_MODE_5, this); + scene->_hotspot2.setAction(NULL); + + scene->_hotspot3.setStrip2(1); + ADD_PLAYER_MOVER_THIS(scene->_hotspot3, 1200, 100); + } else { + scene->_hotspot3.setVisage(5130); + scene->_hotspot3._strip = 1; + scene->_hotspot3._frame = 1; + scene->_hotspot3.animate(ANIM_MODE_5, this); + scene->_hotspot3.setAction(NULL); + + scene->_hotspot2.setStrip2(2); + ADD_PLAYER_MOVER_NULL(scene->_hotspot2, 10, 140); + + } + + _globals->_player.setVisage(2672); + _globals->_player._frame = _globals->_player.getFrameCount(); + _globals->_player.animate(ANIM_MODE_6, this); + break; + case 3: + break; + case 4: + SceneItem::display2(5100, 38); + _globals->_player.enableControl(); + + _globals->_player.setVisage(0); + _globals->_player._strip = 8; + _globals->_player.animate(ANIM_MODE_1, NULL); + remove(); + break; + } +} + +void Scene5100::Action4::signal() { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + _globals->_player.disableControl(); + scene->_soundHandler.startSound(208); + SceneItem::display2(5100, 15); + + ObjectMover3 *mover = new ObjectMover3(); + scene->_hotspot2.addMover(mover, &_globals->_player, 20, this); + break; + } + case 1: + scene->_hotspot1.postInit(); + scene->_hotspot1.setVisage(5120); + scene->_hotspot1.setPosition(Common::Point(795, 161)); + scene->_hotspot1._strip = 4; + scene->_hotspot1.animate(ANIM_MODE_5, this); + break; + case 2: + setDelay(15); + break; + case 3: + _globals->_sceneManager.changeScene(5200); + break; + } +} + +void Scene5100::Action5::signal() { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(60); + break; + case 1: + scene->_stripManager.start(5128, this); + break; + case 2: + setDelay(15); + break; + case 3: + scene->_sceneMode = 5106; + scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, NULL); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene5100::HotspotGroup1::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, _globals->getFlag(62) ? 41 : 26); + break; + case CURSOR_USE: + SceneItem::display2(5100, 11); + break; + case OBJECT_SCANNER: + SceneItem::display2(5100, 17); + break; + case OBJECT_STUNNER: + if (_globals->getFlag(62)) + SceneItem::display2(5100, 42); + else + setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot4::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, 31); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 5110; + scene->setAction(&scene->_sequenceManager, scene, 5110, &_globals->_player, this, &scene->_hotspot7, NULL); + break; + case CURSOR_TALK: + SceneItem::display2(5100, 34); + break; + case OBJECT_STUNNER: + SceneItem::display2(5100, 36); + break; + case OBJECT_SCANNER: + SceneItem::display2(5100, 37); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::HotspotGroup2::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, _globals->getFlag(62) ? 47 : 23); + break; + case CURSOR_USE: + SceneItem::display2(5100, 29); + break; + case CURSOR_TALK: + if (_position.x >= 600) + SceneItem::display2(5100, 28); + else { + _globals->_player.disableControl(); + scene->_sceneMode = 5114; + scene->setAction(&scene->_sequenceManager, scene, 5114, NULL); + } + break; + case OBJECT_SCANNER: + SceneItem::display2(5100, 43); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot9::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, 32); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 5117; + scene->setAction(&scene->_sequenceManager, scene, 5117, &_globals->_player, NULL); + break; + case OBJECT_STUNNER: + SceneItem::display2(5100, 35); + break; + case OBJECT_SCANNER: + SceneItem::display2(5100, 44); + break; + case OBJECT_BONE: + _globals->_player.disableControl(); + scene->_sceneMode = 5116; + scene->setAction(&scene->_sequenceManager, scene, 5116, &_globals->_player, &scene->_hotspot10, + &scene->_hotspot4, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot17::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, 18); + break; + case CURSOR_USE: + if (_globals->getFlag(67)) + SceneItem::display2(5100, 19); + else { + _globals->_player.disableControl(); + scene->_sceneMode = 5101; + scene->setAction(&scene->_sequenceManager, scene, 5101, &_globals->_player, this, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot18::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->_sceneManager._previousScene != 5000) { + SceneItem::display2(5100, 3); + } else { + switch (_index1) { + case 0: + SceneItem::display2(5100, 0); + ++_index1; + break; + case 1: + SceneItem::display2(5100, 1); + ++_index1; + break; + default: + SceneItem::display2(5100, 2); + break; + } + } + break; + case CURSOR_USE: + switch (_index2) { + case 0: + SceneItem::display2(5100, 8); + ++_index2; + break; + case 1: + SceneItem::display2(5100, 9); + ++_index2; + break; + default: + SceneItem::display2(5100, 10); + break; + } + break; + + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot19::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, _globals->_sceneObjects->contains(&scene->_hotspot14) ? 27 : 20); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + scene->_sceneMode = 5106; + + if (_globals->getFlag(66)) + scene->setAction(&scene->_sequenceManager, scene, 5113, &_globals->_player, NULL); + else { + _globals->setFlag(66); + scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, &scene->_hotspot14, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5100::Hotspot20::doAction(int action) { + Scene5100 *scene = (Scene5100 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5100, 21); + break; + case CURSOR_USE: + _globals->_player.disableControl(); + + if (_globals->getFlag(67)) { + scene->_sceneMode = 5112; + scene->setAction(&scene->_sequenceManager, scene, 5112, &_globals->_player, NULL); + } else { + scene->_sceneMode = 5101; + scene->setAction(&scene->_sequenceManager, scene, 5106, &_globals->_player, &scene->_hotspot17, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene5100::Scene5100() : + _hotspot16(0, CURSOR_LOOK, 5100, 48, LIST_END), + _hotspot21(0, CURSOR_LOOK, 5100, 4, CURSOR_USE, 5100, 5, LIST_END) { +} + +void Scene5100::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(50, 10, 200, 100); + _sceneMode = 0; + + _stripManager.addSpeaker(&_speakerMText); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + _stripManager.addSpeaker(&_speakerBatText); + _speakerQText._npc = &_globals->_player; + _speakerMText._npc = &_globals->_player; + _speakerSText._npc = &_hotspot8; + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.disableControl(); + + if (!_globals->getFlag(66)) { + _hotspot14.postInit(); + _hotspot14.setVisage(5101); + _hotspot14.setPosition(Common::Point(498, 147)); + _hotspot14.setPriority2(200); + _hotspot14._moveDiff.y = 10; + } + + _hotspot17.postInit(); + _hotspot17.setVisage(5101); + _hotspot17._strip = 2; + _hotspot17.setPriority2(200); + + if (_globals->getFlag(67)) + _hotspot17.setPosition(Common::Point(554, 192)); + else + _hotspot17.setPosition(Common::Point(539, 179)); + + _hotspot19.setBounds(Rect(488, 115, 508, 148)); + _hotspot21.setBounds(Rect(1150, 85, 1173, 112)); + _hotspot20.setBounds(Rect(517, 193, 562, 200)); + _globals->_sceneItems.addItems(&_hotspot19, &_hotspot21, NULL); + + if (_globals->getFlag(67)) { + _globals->_sceneItems.addItems(&_hotspot20, &_hotspot17, NULL); + } else { + _globals->_sceneItems.addItems(&_hotspot17, &_hotspot20, NULL); + } + + if (!_globals->getFlag(105)) { + _hotspot4.postInit(); + _hotspot4.setVisage(5363); + _hotspot4.setPosition(Common::Point(1025, 65)); + _hotspot4.setStrip(4); + _hotspot4.animate(ANIM_MODE_7, 0, NULL);; + _globals->_sceneItems.push_back(&_hotspot4); + + _hotspot9.postInit(); + _hotspot9.setVisage(5363); + _hotspot9.setPosition(Common::Point(966, 120)); + _globals->_sceneItems.push_back(&_hotspot9); + + _hotspot10.postInit(); + _hotspot10.setVisage(5363); + _hotspot10.setPosition(Common::Point(999, 68)); + _hotspot10.setStrip(2); + + _hotspot6.postInit(); + _hotspot6.setVisage(5362); + _hotspot6.setPosition(Common::Point(1017, 34)); + _hotspot6._strip = 4; + _hotspot6._frame = _hotspot6.getFrameCount(); + _globals->_sceneItems.push_back(&_hotspot6); + } + + _hotspot16._sceneRegionId = 15; + _globals->_sceneItems.push_back(&_hotspot16); + + if (!_globals->getFlag(62)) { + _hotspot2.postInit(); + _hotspot2.setVisage(5110); + _hotspot2.animate(ANIM_MODE_1, NULL); + _hotspot2._moveDiff.x = 4; + _globals->_sceneItems.push_back(&_hotspot2); + + _hotspot3.postInit(); + _hotspot3.setVisage(5110); + _hotspot3.animate(ANIM_MODE_1, NULL); + _hotspot3._moveDiff.x = 4; + _globals->_sceneItems.push_back(&_hotspot3); + + if (_globals->getFlag(61)) { + _hotspot2.setPosition(Common::Point(483, 189)); + _hotspot3.setPosition(Common::Point(811, 182)); + } else { + _hotspot2.setPosition(Common::Point(610, 170)); + _hotspot3.setPosition(Common::Point(600, 180)); + } + } + + if (_globals->getFlag(60) && (_globals->_inventory._stasisBox._sceneNumber == 1) && + _globals->getFlag(107) && _globals->getFlag(67)) { + _hotspot8.postInit(); + _hotspot8.setVisage(2806); + _hotspot8.setPosition(Common::Point(557, 178)); + _hotspot8.animate(ANIM_MODE_1, NULL); + _hotspot8.setObjectWrapper(new SceneObjectWrapper()); + + _globals->clearFlag(59); + } + + switch (_globals->_sceneManager._previousScene) { + case 5000: + default: + _globals->_player.setPosition(Common::Point(1184, 160)); + setAction(&_action1); + break; + case 5200: + if (_globals->_stripNum == 5200) { + _globals->_player.setVisage(5101); + _globals->_player.setPriority2(200); + _globals->_player.setStrip(5); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(513, 199)); + + _sceneMode = 5108; + setAction(&_sequenceManager, this, 5108, &_globals->_player, NULL); + } else { + _globals->_player.setPosition(Common::Point(20, 175)); + + _hotspot13.postInit(); + _hotspot13.setVisage(5110); + _hotspot13.setPosition(Common::Point(578, 192)); + _hotspot13._strip = 2; + + _hotspot11.postInit(); + _hotspot11.setVisage(5110); + _hotspot11.setPosition(Common::Point(5, 162)); + _hotspot11.setStrip2(1); + _hotspot11._moveDiff = Common::Point(4, 2); + _hotspot11.animate(ANIM_MODE_1, NULL); + + ObjectMover2 *mover = new ObjectMover2(); + _hotspot11.addMover(mover, 15, 20, &_globals->_player); + + _hotspot12.postInit(); + _hotspot12.setVisage(5110); + _hotspot12.setPosition(Common::Point(15, 164)); + _hotspot12.setStrip2(1); + _hotspot12._moveDiff = Common::Point(4, 2); + _hotspot12.animate(ANIM_MODE_1, NULL); + + ObjectMover2 *mover2 = new ObjectMover2(); + _hotspot12.addMover(mover2, 25, 50, &_globals->_player); + + _hotspot17.setPosition(Common::Point(554, 182)); + _globals->_player.disableControl(); + + _sceneMode = 5105; + setAction(&_sequenceManager, this, 5105, &_globals->_player, NULL); + } + break; + case 5300: + switch (_globals->_stripNum) { + case 5300: + _sceneMode = 5111; + + _globals->_player.setVisage(5101); + _globals->_player.setStrip(6); + _globals->_player.setPriority2(170); + _globals->_player.setPosition(Common::Point(1168, 110)); + + setAction(&_sequenceManager, this, 5111, &_globals->_player, NULL); + _hotspot8.setPosition(Common::Point(1107, 178)); + break; + case 5302: + _globals->_player.setPosition(Common::Point(512, 190)); + + if (_globals->_sceneObjects->contains(&_hotspot8)) + setAction(&_action2); + else + _globals->_player.enableControl(); + break; + case 5303: + _hotspot8.setVisage(5102); + _hotspot8.setPosition(Common::Point(533, 172)); + _globals->_player.setPosition(Common::Point(512, 190)); + setAction(&_action2); + break; + } + + if (_globals->getFlag(108)) { + _hotspot6.postInit(); + _hotspot6.setVisage(5362); + _hotspot6.setPosition(Common::Point(542, 19)); + _hotspot6.setStrip(6); + _hotspot6.setFrame(1); + _globals->_sceneItems.push_back(&_hotspot6); + } else if (_globals->_inventory._vial._sceneNumber != 5100) { + _hotspot6.postInit(); + _hotspot6.setVisage(5362); + _hotspot6.setPosition(Common::Point(1152, 70)); + _hotspot6.setPriority2(170); + _hotspot6.setStrip(6); + _hotspot6.setFrame(1); + _globals->_sceneItems.push_back(&_hotspot6); + } + break; + } + + _hotspot18.setBounds(Rect(0, 0, 1280, 200)); + _globals->_sceneItems.push_back(&_hotspot18); + + _hotspot15.postInit(); + _hotspot15.setVisage(5140); + _hotspot15.setStrip(3); + _hotspot15.setPosition(Common::Point(977, 173)); + _hotspot15.setPriority2(1); + + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position); + loadScene(5100); + _globals->_soundHandler.startSound(205); +} + +void Scene5100::signal() { + switch (_sceneMode) { + case 5101: + case 5112: + _globals->setFlag(67); + _globals->_sceneManager.changeScene(5300); + break; + case 5102: + case 5114: + _globals->_player.enableControl(); + break; + case 5103: + if (_globals->getFlag(61)) { + SceneItem::display2(5100, 46); + _globals->_sceneManager.changeScene(5300); + } else { + SceneItem::display2(5100, 45); + _globals->_sceneManager.changeScene(5200); + } + break; + case 5105: + _globals->_sceneManager.changeScene(5300); + break; + case 5106: + _globals->_stripNum = 5111; + _globals->_sceneManager.changeScene(5200); + break; + case 5108: + if (!_globals->getFlag(60)) + _globals->_player.enableControl(); + else if (_globals->_inventory._stasisBox._sceneNumber == 1) + setAction(&_action2); + else + setAction(&_action5); + break; + case 5110: + SceneItem::display2(5100, 30); + _globals->_player._angle = 325; + _globals->_player.enableControl(); + break; + case 5111: + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setVisage(6); + _globals->_player.setStrip(6); + _globals->_player.setPriority2(-1); + _globals->_player.animate(ANIM_MODE_1, NULL); + + if ((_globals->_inventory._vial._sceneNumber != 5100) && !_globals->getFlag(108)) { + _globals->setFlag(108); + _sceneMode = 5130; + _globals->_player.disableControl(); + + _speakerBatText.setTextPos(Common::Point(_globals->_sceneManager._scene->_sceneBounds.left + 20, 30)); + setAction(&_sequenceManager, this, 5130, &_globals->_player, &_hotspot6, NULL); + } else if (_globals->_sceneObjects->contains(&_hotspot8)) { + setAction(&_action2); + } else { + _globals->_player.enableControl(); + } + break; + case 5116: + _globals->setFlag(105); + _globals->_inventory._bone._sceneNumber = 0; + + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setVisage(0); + _globals->_player.setStrip(6); + _globals->_player.setPriority2(-1); + _globals->_player.animate(ANIM_MODE_1, NULL); + break; + case 5117: + _globals->_player.enableControl(); + break; + case 5130: + _hotspot6.setVisage(5362); + _hotspot6.setPosition(Common::Point(542, 25)); + _hotspot6.setStrip(6); + _hotspot6.setFrame(1); + _globals->_player.enableControl(); + break; + case 5150: + _globals->clearFlag(60); + _globals->_sceneManager.changeScene(5300); + break; + } +} + +void Scene5100::dispatch() { + if (_hotspot15._bounds.contains(_globals->_player._position) && !_globals->_player._visage) { + _globals->_player.disableControl(); + _globals->_player.addMover(NULL); + + _soundHandler.startSound(207); + _sceneMode = 5103; + setAction(&_sequenceManager, this, (_globals->_player._position.x >= 966) ? 5104 : 5103, + &_globals->_player, &_hotspot15, NULL); + } + + if (_globals->getFlag(61) && !_globals->getFlag(62) && + ((_globals->_player._position.x - _hotspot2._position.x) < 160) && + (_globals->_sceneManager._previousScene != 5200) && + (_globals->_sceneManager._previousScene != 5150)) { + setAction(NULL); + _sceneMode = 5150; + _soundHandler.startSound(208); + + if (_globals->_inventory._vial._sceneNumber == 5100) { + _globals->_player.addMover(NULL); + _globals->_player.disableControl(); + SceneItem::display2(5100, 39); + } + + _hotspot2.setStrip2(1); + _hotspot3.setStrip2(2); + + ObjectMover3 *mover1 = new ObjectMover3(); + _hotspot2.addMover(mover1, 20, this); + ObjectMover3 *mover2 = new ObjectMover3(); + _hotspot3.addMover(mover2, 20, this); + } + + if (!_action) { + if (((_globals->_player._position.x - _hotspot2._position.x) < 130) && !_globals->getFlag(61)) { + _globals->_player._canWalk = false; + _globals->_player.addMover(NULL); + + PlayerMover2 *mover = new PlayerMover2(); + _hotspot3.addMover(mover, 20, 25, &_globals->_player); + setAction(&_action4); + } + + if ((_globals->_sceneManager._scene->_backgroundBounds.right - 85) <= _globals->_player._position.x) + _globals->_sceneManager.changeScene(5000); + + if (_globals->_player.getRegionIndex() == 8) { + _sceneMode = 5114; + setAction(&_sequenceManager, this, 5115, &_globals->_player, NULL); + } + } + + Scene::dispatch(); +} + +/*-------------------------------------------------------------------------- + * Scene 5200 - Caverns - Throne Room + * + *--------------------------------------------------------------------------*/ + +void Scene5200::Action1::signal() { + Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(59) + 120); + break; + case 1: + scene->_hotspot3.animate(ANIM_MODE_8, 1, this); + _actionIndex = 0; + break; + } +} + +void Scene5200::Action2::signal() { + Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + ADD_PLAYER_MOVER(92, 52); + break; + case 1: + _globals->_player.setVisage(5202); + _globals->_player._strip = 4; + _globals->_player._frame = 1; + _globals->_player.animate(ANIM_MODE_4, 3, 1, this); + break; + case 2: + scene->_soundHandler.proc3(); + scene->_hotspot14.remove(); + + _globals->_inventory._stasisBox._sceneNumber = 1; + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 3: + _globals->_player.setVisage(0); + _globals->_player._strip = 3; + _globals->_player.animate(ANIM_MODE_1, NULL); + + scene->_hotspot8.animate(ANIM_MODE_2, NULL); + ADD_MOVER(scene->_hotspot8, 141, 77); + break; + case 4: + scene->_soundHandler.startSound(303); + + scene->_hotspot8._strip = 2; + scene->_hotspot8._frame = 1; + scene->_hotspot8.animate(ANIM_MODE_5, this); + break; + case 5: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene5200::Action3::signal() { + switch (_actionIndex++) { + _globals->_player.disableControl(); + setDelay(5); + break; + case 1: + ADD_PLAYER_MOVER(285, 62); + break; + case 2: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene5200::Action4::signal() { + Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(120); + break; + case 1: + _globals->_soundHandler.startSound(209); + scene->_stripManager.start(5202, this, scene); + break; + case 2: + scene->_hotspot6.animate(ANIM_MODE_5, this); + break; + case 3: + setDelay(10); + break; + case 4: + scene->_stripManager.start(5204, this, scene); + break; + case 5: + setDelay(60); + break; + case 6: + _globals->_sceneManager.changeScene(5100); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene5200::Hotspot9::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (!_state) { + ++_state; + SceneItem::display2(5200, 5); + } else { + SceneItem::display2(5200, 6); + } + break; + case CURSOR_USE: + SceneItem::display2(5200, 14); + break; + default: + SceneItem::doAction(action); + break; + } +} + +void Scene5200::Hotspot10::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (!_state) { + ++_state; + SceneItem::display2(5200, 7); + } else { + SceneItem::display2(5200, 8); + } + break; + default: + SceneItem::doAction(action); + break; + } +} + +void Scene5200::Hotspot14::doAction(int action) { + Scene5200 *scene = (Scene5200 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5200, 4); + break; + case CURSOR_USE: + scene->setAction(&scene->_action2); + break; + default: + SceneItem::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene5200::Scene5200() : + _hotspot11(0, CURSOR_LOOK, 5200, 0, CURSOR_USE, 5200, 13, LIST_END), + _hotspot12(10, CURSOR_LOOK, 5200, 9, LIST_END), + _hotspot13(8, CURSOR_LOOK, 5200, 0, CURSOR_USE, 5200, 13, LIST_END) { +} + + +void Scene5200::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(0, 150, 199, 150); + _fieldA = 5600; + _fieldE = 5100; + + _hotspot9._state = 0; + _hotspot10._state = 0; + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerGameText); + _stripManager.addSpeaker(&_speakerFLText); + _stripManager.addSpeaker(&_speakerFLL); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.setCallback(this); + + _speakerFLText._textPos.x = 160; + _speakerQText._textPos.x = 20; + + if (_globals->_inventory._stasisBox._sceneNumber == 5200) { + _soundHandler.startSound(216); + _soundHandler.proc5(true); + + _hotspot14.postInit(); + _hotspot14.setVisage(5202); + _hotspot14._strip = 3; + _hotspot14.setPosition(Common::Point(105, 52)); + _hotspot14.setPriority2(90); + + _hotspot8.postInit(); + _hotspot8.setVisage(5202); + _hotspot8._strip = 1; + _hotspot8.setPosition(Common::Point(96, 53)); + _hotspot8.setPriority2(90); + _globals->_sceneItems.push_back(&_hotspot14); + } + + if (_globals->_stripNum == 1111) { + _globals->_soundHandler.startSound(205); + _globals->_player.disableControl(); + + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.changeZoom(75); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip(1); + _globals->_player.setFrame(3); + _globals->_player.setPosition(Common::Point(307, 62)); + + setAction(&_action3); + } else { + _globals->_player.postInit(); + _globals->_player.setVisage(2640); + _globals->_player._strip = 1; + _globals->_player._frame = 4; + _globals->_player.setPosition(Common::Point(105, 199)); + + _hotspot5.postInit(); + _hotspot5.setVisage(5210); + _hotspot5._frame = 2; + _hotspot5.setPosition(Common::Point(189, 167)); + + _hotspot6.postInit(); + _hotspot6.setVisage(5210); + _hotspot6._frame = 1; + _hotspot6._strip = 2; + _hotspot6.setPosition(Common::Point(159, 137)); + + _hotspot7.postInit(); + _hotspot7.setVisage(5210); + _hotspot7._frame = 1; + _hotspot7._strip = 4; + _hotspot7.setPriority2(168); + _hotspot7.setPosition(Common::Point(186, 106)); + + _hotspot1.postInit(); + _hotspot1.setVisage(5212); + _hotspot1._frame = 1; + _hotspot1.setPosition(Common::Point(62, 132)); + + _hotspot2.postInit(); + _hotspot2.setVisage(5212); + _hotspot2._strip = 3; + _hotspot2.setPosition(Common::Point(148, 141)); + _hotspot2.setPriority2(90); + + _hotspot3.postInit(); + _hotspot3.setVisage(5212); + _hotspot3._strip = 2; + _hotspot3.setPosition(Common::Point(62, 109)); + _hotspot3.setPriority2(138); + _hotspot3.setAction(&_action1); + + _hotspot4.postInit(); + _hotspot4.setVisage(5212); + _hotspot4._strip = 4; + _hotspot4.setPosition(Common::Point(146, 110)); + _hotspot4.setPriority2(90); + + _globals->_player.disableControl(); + _globals->setFlag(61); + + setAction(&_action4); + } + + _hotspot11.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot9._sceneRegionId = 11; + _hotspot10._sceneRegionId = 9; + + _globals->_sceneItems.addItems(&_hotspot12, &_hotspot13, &_hotspot9, &_hotspot10, &_hotspot11, NULL); + _globals->_sceneManager._scene->_sceneBounds.centre(_globals->_player._position); + loadScene(5200); +} + +void Scene5200::stripCallback(int v) { + switch (v) { + case 1: + _hotspot7.animate(ANIM_MODE_2, NULL); + break; + case 2: + _hotspot7.animate(ANIM_MODE_NONE, NULL); + break; + } +} + +void Scene5200::dispatch() { + Scene::dispatch(); + + if (!_action && (_globals->_player.getRegionIndex() == 12)) { + _globals->_stripNum = 5200; + _globals->_sceneManager.changeScene(5100); + } +} + +/*-------------------------------------------------------------------------- + * Scene 5300 - Caverns - Pit + * + *--------------------------------------------------------------------------*/ + +void Scene5300::Action1::signal() { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + scene->_hotspot2._numFrames = 4; + scene->_hotspot2.animate(ANIM_MODE_8, 1, NULL); + setDelay(120); + break; + case 2: + scene->_hotspot2.animate(ANIM_MODE_NONE, NULL); + + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.setStrip2(-1); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + ADD_MOVER(_globals->_player, 85, 170); + break; + case 3: + scene->_hotspot2.setPriority2(-1); + _globals->_player.checkAngle(&scene->_hotspot2); + setAction(&scene->_sequenceManager, this, 5305, &scene->_hotspot2, NULL); + break; + case 4: + scene->_stripManager.start(5316, this); + break; + case 5: + if (!_globals->getFlag(106) || !_globals->getFlag(107) || (_globals->_inventory._stasisBox._sceneNumber != 1)) { + _globals->_player.enableControl(); + remove(); + } else { + _globals->getFlag(60); + + if (_globals->getFlag(67)) { + scene->_sceneMode = 5310; + scene->setAction(&scene->_sequenceManager, scene, 5310, &_globals->_player, &scene->_hotspot2, NULL); + } else { + scene->_sceneMode = 5347; + scene->setAction(&scene->_sequenceManager, scene, 5347, NULL); + } + } + break; + } +} + +void Scene5300::Action2::signal() { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(60); + break; + case 1: + _globals->setFlag(60); + scene->_stripManager.start(5328, this); + break; + case 2: + if (_globals->_inventory._stasisBox._sceneNumber == 1) { + _globals->_stripNum = 5303; + setDelay(5); + } else { + _globals->_stripNum = 5302; + scene->_stripManager.start(5329, this); + } + break; + case 3: + _globals->_sceneManager.changeScene(5100); + remove(); + break; + } +} + +void Scene5300::Action3::signal() { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(30); + break; + case 1: + scene->_stripManager.start(_globals->_stripNum, this); + break; + case 2: + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene5300::Hotspot1::doAction(int action) { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5300, 24); + break; + case CURSOR_TALK: + _globals->_stripNum = 5312; + scene->setAction(&scene->_action3); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5300::Hotspot2::doAction(int action) { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5300, 23); + break; + case CURSOR_USE: + if (!_globals->getFlag(106)) { + _globals->_player.disableControl(); + scene->_sceneMode = 5302; + scene->setAction(&scene->_sequenceManager, scene, 5302, &_globals->_player, NULL); + } else { + SceneItem::display2(5300, _globals->getFlag(107) ? 25 : 20); + } + break; + case CURSOR_TALK: + if (!_globals->getFlag(106)) { + _globals->_player.disableControl(); + scene->_sceneMode = 5302; + scene->setAction(&scene->_sequenceManager, scene, 5302, &_globals->_player, NULL); + } else if (!_globals->getFlag(107)) { + SceneItem::display2(5300, 11); + } else { + _globals->_player.disableControl(); + + if (_globals->_inventory._stasisBox._sceneNumber != 1) { + scene->setAction(&scene->_sequenceManager, scene, 5316, NULL); + } else { + _globals->setFlag(60); + scene->_sceneMode = _globals->getFlag(67) ? 5315 : 5347; + scene->setAction(&scene->_sequenceManager, scene, 5315, this); + } + } + break; + case OBJECT_SCANNER: + SceneItem::display2(5300, _globals->getFlag(107) ? 10 : 9); + break; + case OBJECT_MEDKIT: + if (_globals->getFlag(106)) + SceneItem::display2(5300, 7); + else { + _globals->setFlag(106); + _globals->_player.disableControl(); + + scene->_sceneMode = 5303; + scene->setAction(&scene->_sequenceManager, scene, 5303, &_globals->_player, NULL); + } + break; + case OBJECT_VIAL: + if (_globals->getFlag(107)) { + SceneItem::display2(5300, 8); + } else { + _globals->_inventory._vial._sceneNumber = 5300; + _globals->setFlag(107); + _globals->_player.disableControl(); + scene->_sceneMode = 5304; + + scene->setAction(&scene->_sequenceManager, scene, 5304, &_globals->_player, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5300::Hotspot5::doAction(int action) { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5300, 27); + break; + case CURSOR_USE: + _globals->_inventory._bone._sceneNumber = 1; + _globals->_player.disableControl(); + + scene->_sceneMode = 5309; + scene->setAction(&scene->_sequenceManager, scene, 5309, &_globals->_player, this, NULL); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5300::Hotspot6::doAction(int action) { + Scene5300 *scene = (Scene5300 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (!_globals->getFlag(105) || (_globals->_inventory._vial._sceneNumber == 1)) + SceneItem::display2(5300, 4); + else + SceneItem::display2(5300, 26); + break; + case CURSOR_USE: + if (!_globals->getFlag(105) || (_globals->_inventory._vial._sceneNumber != 5100)) { + _globals->_player.disableControl(); + scene->_sceneMode = 5301; + scene->setAction(&scene->_sequenceManager, scene, 5301, &_globals->_player, NULL); + } else { + _globals->_player.disableControl(); + scene->_sceneMode = 5307; + _globals->_inventory._vial._sceneNumber = 1; + + scene->setAction(&scene->_sequenceManager, scene, 5307, &scene->_hotspot1, &_globals->_player, + &scene->_hotspot4, NULL); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5300::Hotspot7::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(63)) + SceneItem::display2(5300, 2); + else { + _globals->setFlag(63); + SceneItem::display2(5300, 0); + SceneItem::display2(5300, 1); + } + break; + case CURSOR_USE: + if (_globals->getFlag(64)) + SceneItem::display2(5300, 15); + else { + _globals->setFlag(64); + SceneItem::display2(5300, 14); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene5300::Hotspot8::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display2(5300, _globals->getFlag(65) ? 6 : 5); + break; + case CURSOR_USE: + SceneItem::display2(5300, 18); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene5300::Scene5300() : + _hotspot3(0, CURSOR_LOOK, 5300, 3, CURSOR_USE, 5300, 16, LIST_END) { +} + +void Scene5300::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + loadScene(5300); + setZoomPercents(0, 100, 199, 100); + + _stripManager.addSpeaker(&_speakerQR); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerBatR); + _stripManager.addSpeaker(&_speakerSR); + _stripManager.addSpeaker(&_speakerSL); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerBatText); + _stripManager.addSpeaker(&_speakerSText); + _stripManager.addSpeaker(&_speakerGameText); + + if (_globals->getFlag(106) && _globals->getFlag(107)) { + _hotspot2.postInit(); + _hotspot2.setVisage(2806); + _hotspot2.setObjectWrapper(new SceneObjectWrapper()); + _hotspot2.setPosition(Common::Point(63, 170)); + _hotspot2.animate(ANIM_MODE_1, NULL); + } else { + _hotspot2.postInit(); + _hotspot2.setVisage(5310); + _hotspot2.setPosition(Common::Point(63, 170)); + _hotspot2.animate(ANIM_MODE_1, NULL); + _hotspot2.setPriority2(98); + } + + _hotspot1.postInit(); + _hotspot1.setVisage(5362); + _hotspot1.setStrip2(3); + _hotspot1.setFrame2(5); + _hotspot1.setPosition(Common::Point(76, 48)); + + _hotspot4.postInit(); + _hotspot4.setVisage(5316); + _hotspot4.setStrip(2); + _hotspot4.setPosition(Common::Point(89, 65)); + _hotspot4.animate(ANIM_MODE_2, NULL); + _hotspot4.hide(); + + if (_globals->getFlag(67)) { + _globals->_player.postInit(); + _globals->_player.setVisage(5316); + _globals->_player.setPosition(Common::Point(191, 27)); + _globals->_player.disableControl(); + + if (_globals->getFlag(107) && _globals->getFlag(106)) { + _hotspot2.postInit(); + _hotspot2.setObjectWrapper(new SceneObjectWrapper()); + _hotspot2.animate(ANIM_MODE_1, NULL); + + setAction(&_action2); + } else { + _globals->_player.setVisage(5315); + _globals->_player.setPosition(Common::Point(204, 86)); + _globals->_player.animate(ANIM_MODE_2, NULL); + _globals->_player.setStrip2(1); + _globals->_player._moveDiff.y = 12; + + _sceneMode = 5308; + setAction(&_sequenceManager, this, 5308, &_globals->_player, NULL); + } + } else { + _hotspot3.postInit(); + _hotspot3.setVisage(5301); + _hotspot3.setPosition(Common::Point(172, 32)); + _hotspot3.setPriority2(1); + _hotspot3.animate(ANIM_MODE_NONE, NULL); + + _globals->_player.postInit(); + _globals->_player.setVisage(5315); + _globals->_player.setPosition(Common::Point(204, 86)); + _globals->_player.animate(ANIM_MODE_2, NULL); + _globals->_player.setStrip2(1); + _globals->_player._moveDiff.y = 12; + _globals->_player.disableControl(); + + _sceneMode = 5306; + setAction(&_sequenceManager, this, 5306, &_globals->_player, &_hotspot3, NULL); + } + + _field1B0A = 1; + if (_globals->_inventory._bone._sceneNumber == 5300) { + _hotspot5.postInit(); + _hotspot5.setVisage(5301); + _hotspot5.setStrip(2); + _hotspot5.setPosition(Common::Point(190, 147)); + _globals->_sceneItems.push_back(&_hotspot5); + } + + _hotspot6.setBounds(Rect(74, 51, 114, 69)); + _hotspot7.setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)); + _hotspot8._sceneRegionId = 8; + + _globals->_sceneItems.addItems(&_hotspot8, &_hotspot2, &_hotspot6, &_hotspot3, &_hotspot7, NULL); + _globals->_soundHandler.startSound(212); +} + +void Scene5300::signal() { + switch (_sceneMode) { + case 5301: + _globals->_stripNum = 5300; + _globals->_sceneManager.changeScene(5100); + break; + case 5302: + case 5308: + case 5316: + case 5347: + _globals->_player.setStrip2(-1); + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.enableControl(); + break; + case 5303: + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.enableControl(); + + if (_globals->getFlag(107)) + setAction(&_action1); + else + SceneItem::display2(5300, 28); + break; + case 5304: + _globals->_player.animate(ANIM_MODE_1, NULL); + _globals->_player.enableControl(); + + if (_globals->getFlag(106)) + setAction(&_action1); + else + SceneItem::display2(5300, 28); + break; + case 5306: + _globals->clearFlag(67); + _globals->_player.setStrip2(-1); + + if ((_globals->_inventory._vial._sceneNumber == 1) || (_globals->_inventory._vial._sceneNumber == 5300)) + _stripManager.start(5303, this); + else + _stripManager.start(5302, this); + _sceneMode = 5302; + break; + case 5307: + _soundHandler.proc1(NULL); + break; + case 5309: + _hotspot5.remove(); + _globals->_player.enableControl(); + break; + case 5310: + _hotspot2.setPriority2(41); + _sceneMode = 5315; + + setAction(&_sequenceManager, this, 5315, &_hotspot2, NULL); + break; + case 5315: + _globals->_stripNum = 5315; + _globals->_sceneManager.changeScene(5100); + break; + } +} + + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes6.h b/engines/tsage/ringworld_scenes6.h new file mode 100644 index 0000000000..272aea4fe9 --- /dev/null +++ b/engines/tsage/ringworld_scenes6.h @@ -0,0 +1,333 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES6_H +#define TSAGE_RINGWORLD_SCENES6_H + +#include "common/scummsys.h" +#include "tsage/ringworld_logic.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +class Scene5000 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + virtual void dispatch(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class HotspotGroup1 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + SpeakerSText _speakerSText; + SpeakerQText _speakerQText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + DisplayHotspot _hotspot1; + SceneObject _hotspot2, _hotspot3, _hotspot4, _hotspot5, _hotspot6; + Hotspot7 _hotspot7; + Hotspot8 _hotspot8; + HotspotGroup1 _hotspot9, _hotspot10, _hotspot11; + DisplayHotspot _hotspot12, _hotspot13, _hotspot14, _hotspot15; + DisplayHotspot _hotspot16, _hotspot17, _hotspot18; + + Scene5000(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene5100 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class HotspotGroup1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class HotspotGroup2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot4 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot9 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot17 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot18 : public SceneHotspot { + public: + int _index1; + int _index2; + + virtual void doAction(int action); + }; + class Hotspot19 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot20 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SequenceManager _sequenceManager; + SoundHandler _soundHandler; + SpeakerMText _speakerMText; + SpeakerQText _speakerQText; + SpeakerSText _speakerSText; + SpeakerBatText _speakerBatText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + HotspotGroup1 _hotspot1, _hotspot2, _hotspot3; + Hotspot4 _hotspot4; + HotspotGroup2 _hotspot5, _hotspot6, _hotspot7; + SceneObject _hotspot8; + Hotspot9 _hotspot9; + SceneObject _hotspot10, _hotspot11, _hotspot12, _hotspot13, _hotspot14, _hotspot15; + DisplayHotspot _hotspot16; + Hotspot17 _hotspot17; + Hotspot18 _hotspot18; + Hotspot19 _hotspot19; + Hotspot20 _hotspot20; + DisplayHotspot _hotspot21; + + Scene5100(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene5200 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot9 : public SceneItemExt { + public: + virtual void doAction(int action); + }; + class Hotspot10 : public SceneItemExt { + public: + virtual void doAction(int action); + }; + class Hotspot14 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + SpeakerFLL _speakerFLL; + SpeakerFLText _speakerFLText; + SpeakerQL _speakerQL; + SpeakerQText _speakerQText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + + SceneObject _hotspot1, _hotspot2, _hotspot3, _hotspot4, _hotspot5, _hotspot6, _hotspot7; + SceneObject _hotspot8; + Hotspot9 _hotspot9; + Hotspot10 _hotspot10; + DisplayHotspot _hotspot11, _hotspot12, _hotspot13; + Hotspot14 _hotspot14; + + Scene5200(); + virtual void stripCallback(int v); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void dispatch(); +}; + +class Scene5300 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + + /* Hotspots */ + class Hotspot1 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot2 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot5 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot6 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot7 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Hotspot8 : public SceneObject { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + SpeakerQR _speakerQR; + SpeakerQL _speakerQL; + SpeakerQText _speakerQText; + SpeakerBatR _speakerBatR; + SpeakerBatText _speakerBatText; + SpeakerSR _speakerSR; + SpeakerSL _speakerSL; + SpeakerSText _speakerSText; + SpeakerGameText _speakerGameText; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Hotspot1 _hotspot1; + Hotspot2 _hotspot2; + DisplayHotspot _hotspot3; + SceneObject _hotspot4; + Hotspot5 _hotspot5; + Hotspot6 _hotspot6; + Hotspot7 _hotspot7; + Hotspot8 _hotspot8; + int _field1B0A; + + Scene5300(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void synchronise(Serialiser &s) { + Scene::synchronise(s); + s.syncAsSint16LE(_field1B0A); + } +}; + + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/ringworld_scenes8.cpp b/engines/tsage/ringworld_scenes8.cpp new file mode 100644 index 0000000000..416b7fe0fd --- /dev/null +++ b/engines/tsage/ringworld_scenes8.cpp @@ -0,0 +1,2508 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "graphics/cursorman.h" +#include "tsage/ringworld_scenes8.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" + +namespace tSage { + +/*-------------------------------------------------------------------------- + * Scene 7000 + * + *--------------------------------------------------------------------------*/ + +void Scene7000::Action1::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + setAction(&scene->_action6, this); + break; + case 2: + scene->_soundHandler.startSound(252, 0, 127); + scene->_object8.remove(); + scene->_object1.postInit(); + scene->_object1.setVisage(7003); + scene->_object1.animate(ANIM_MODE_5, this); + scene->_object1.setPosition(Common::Point(151, 182), 0); + scene->_object1.setPriority2(205); + _globals->_sceneItems.push_front(&scene->_object1); + break; + case 3: + scene->_object1.setStrip(4); + scene->_object1.animate(ANIM_MODE_8, 0, 0); + scene->_stripManager.start(7005, this); + break; + case 4: + scene->_object1.animate(ANIM_MODE_2, 0); + setDelay(3); + break; + case 5: + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action2::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + _globals->_player.addMover(0, 0); + _globals->_player.setVisage(7006); + _globals->_player.setStrip(1); + _globals->_player.setFrame(1); + _globals->_player.setPosition(Common::Point(_globals->_player._position.x, _globals->_player._position.y + 13)); + _globals->_player.changeZoom(68); + _globals->_player.animate(ANIM_MODE_5, this); + scene->_object1.remove(); + break; + case 2: + _globals->_sceneManager.changeScene(7100); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action3::dispatch() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + Action::dispatch(); + if (_actionIndex == 4) + scene->_object4.setPosition(Common::Point(scene->_object3._position.x, scene->_object3._position.y)); +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action3::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + scene->setZoomPercents(10, 10, 62, 100); + scene->_object4.postInit(); + scene->_object4.setVisage(5001); + scene->_object4.setStrip2(2); + scene->_object4.animate(ANIM_MODE_8, 0, 0); + scene->_object4.setPosition(Common::Point(10, 18), 0); + scene->_object4.setPriority2(10); + scene->_object4.changeZoom(100); + scene->_object4.hide(); + break; + case 1: { + NpcMover *mover = new NpcMover(); + Common::Point pt(107, 65); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 2: + scene->_object3.setPriority2(10); + scene->_object4.setPosition(Common::Point(scene->_object3._position.x, scene->_object3._position.y + 15), 0); + scene->_object4.show(); + setDelay(30); + break; + case 3: { + NpcMover *mover = new NpcMover(); + Common::Point pt(107, 92); + scene->_object3.addMover(mover, &pt, this); + break; + } + case 4: + scene->_object4.remove(); + _globals->_sceneManager.changeScene(2100); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action4::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 1: + scene->_object1.hide(); + setDelay(300); + break; + case 2: + _globals->_soundHandler.startSound(252, 0, 127); + scene->_object1.show(); + scene->_object1.setStrip(3); + scene->_object1.setFrame(1); + scene->_object1.animate(ANIM_MODE_5, this); + break; + case 3: + scene->_object1.setStrip(1); + scene->_object1.animate(ANIM_MODE_8, 0, 0); + _globals->setFlag(81); + _globals->_player.enableControl(); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action5::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: { + NpcMover *playerMover = new NpcMover(); + Common::Point pt(88, 121); + _globals->_player.addMover(playerMover, &pt, this); + break; + } + case 1: + _globals->_player.checkAngle(&scene->_object1); + _globals->_soundHandler.startSound(252, 0, 127); + scene->_object1.setStrip(2); + scene->_stripManager.start(7015, this); + break; + case 2: + scene->_object1.setStrip(1); + scene->_object1.setFrame(4); + scene->_object1.animate(ANIM_MODE_6, this); + break; + case 3: { + scene->_object1.remove(); + NpcMover *mover = new NpcMover(); + Common::Point pt(31, 94); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 4: { + NpcMover *mover = new NpcMover(); + Common::Point pt(11, 94); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 5: { + _globals->_player.setPriority2(10); + NpcMover *mover = new NpcMover(); + Common::Point pt(11, 89); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: { + NpcMover *mover = new NpcMover(); + Common::Point pt(41, 89); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 7: + _globals->clearFlag(36); + _globals->clearFlag(37); + _globals->clearFlag(72); + _globals->clearFlag(13); + _globals->_sceneManager.changeScene(2100); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action6::signal() { + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: { + NpcMover *mover = new NpcMover(); + Common::Point pt(12, 91); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: { + NpcMover *mover = new NpcMover(); + Common::Point pt(8, 91); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: { + NpcMover *mover = new NpcMover(); + Common::Point pt(31, 96); + _globals->_player.addMover(mover, &pt, this); + _globals->_player.setPriority2(-1); + break; + } + case 4: { + NpcMover *mover = new NpcMover(); + Common::Point pt(83, 117); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 5: { + NpcMover *mover = new NpcMover(); + Common::Point pt(95, 121); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: + _globals->_player.setStrip(3); + _globals->_player.setFrame(1); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Action7::signal() { + switch (_actionIndex++) { + case 0: + _globals->_player.disableControl(); + setDelay(3); + break; + case 1: + setDelay(3); + break; + case 2: { + NpcMover *mover = new NpcMover(); + Common::Point pt(31, 94); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: { + NpcMover *mover = new NpcMover(); + Common::Point pt(11, 94); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 4: { + _globals->_player.setPriority2(10); + NpcMover *mover = new NpcMover(); + Common::Point pt(11, 89); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 5: { + NpcMover *mover = new NpcMover(); + Common::Point pt(41, 89); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 6: + if (_globals->getFlag(13)) + _globals->_sceneManager.changeScene(2280); + else + _globals->_sceneManager.changeScene(2320); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::SceneItem1::doAction(int action) { + if (action == CURSOR_LOOK) + SceneItem::display(7000, 2, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + + SceneItem::doAction(action); +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::Object1::doAction(int action) { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_TRANSLATOR: + _globals->_player.disableControl(); + _globals->_inventory._translator._sceneNumber = 7000; + if (_globals->_inventory._waldos._sceneNumber == 7000) { + if (_globals->_inventory._jar._sceneNumber == 7000) { + scene->_sceneMode = 7012; + scene->setAction(&scene->_sequenceManager, scene, 7010, &_globals->_player, &scene->_object1, 0, 0); + } else { + scene->_sceneMode = 7015; + scene->setAction(&scene->_sequenceManager, scene, 7017, &_globals->_player, 0, 0); + } + } else { + if (_globals->_inventory._jar._sceneNumber == 7000) { + scene->_sceneMode = 7011; + scene->setAction(&scene->_sequenceManager, scene, 7010, &_globals->_player, &scene->_object1, 0, 0); + } else { + scene->_sceneMode = 7004; + scene->setAction(&scene->_sequenceManager, scene, 7004, &_globals->_player, this, 0, 0); + } + } + break; + case OBJECT_WALDOS: + _globals->_player.disableControl(); + _globals->_inventory._waldos._sceneNumber = 7000; + if (_globals->_inventory._translator._sceneNumber == 7000) { + if (_globals->_inventory._jar._sceneNumber == 7000) { + scene->_sceneMode = 7015; + scene->setAction(&scene->_sequenceManager, scene, 7015, &_globals->_player, 0, 0); + } else { + scene->_sceneMode = 7006; + scene->setAction(&scene->_sequenceManager, scene, 7006, &_globals->_player, 0, 0); + } + } else { + scene->_sceneMode = 7009; + scene->setAction(&scene->_sequenceManager, scene, 7009, &_globals->_player, 0, 0); + } + break; + case OBJECT_JAR: + _globals->_player.disableControl(); + _globals->_inventory._jar._sceneNumber = 7000; + if (_globals->_inventory._translator._sceneNumber == 7000) { + if (_globals->_inventory._waldos._sceneNumber == 7000) { + scene->_sceneMode = 7007; + scene->setAction(&scene->_sequenceManager, scene, 7007, &_globals->_player, &scene->_object1, 0, 0); + } else { + scene->_sceneMode = 7015; + scene->setAction(&scene->_sequenceManager, scene, 7016, &_globals->_player, 0, 0); + } + } else { + scene->_sceneMode = 7008; + scene->setAction(&scene->_sequenceManager, scene, 7008, &_globals->_player, 0, 0); + } + break; + case CURSOR_LOOK: + if (_globals->getFlag(81)) + SceneItem::display(7000, 1, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneItem::display(7000, 0, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (_globals->getFlag(81)) { + _globals->_inventory._stasisBox._sceneNumber = 1; + _globals->_player.disableControl(); + scene->setAction(&scene->_action5); + } else { + SceneItem::display(7000, 5, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } + break; + case CURSOR_TALK: + if (_globals->getFlag(81)) { + _globals->_inventory._stasisBox._sceneNumber = 1; + _globals->_player.disableControl(); + scene->setAction(&scene->_action5); + } else if (_globals->getFlag(52)) { + scene->_sceneMode = 7005; + scene->setAction(&scene->_sequenceManager, scene, 7013, 0, 0); + } else if (_globals->getFlag(13)) { + _globals->_sceneManager._sceneNumber = 7002; + scene->setAction(&scene->_sequenceManager, scene, 7014, 0, 0); + } else { + _globals->_sceneManager._sceneNumber = 7002; + scene->setAction(&scene->_sequenceManager, scene, 7002, 0, 0); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::dispatch() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + + if (!_action) { + if (_globals->_sceneRegions.indexOf(_globals->_player._position) == 8) { + if (!_globals->getFlag(13)) { + _globals->_player.disableControl(); + _globals->_player.addMover(0); + SceneItem::display(7000, 3, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + _sceneMode = 7001; + setAction(&scene->_sequenceManager, this, 7001, &_globals->_player, NULL); + } else if (!_globals->getFlag(52)) { + setAction(&_action2); + } else { + _globals->_player.disableControl(); + _sceneMode = 7003; + setAction(&scene->_sequenceManager, this, 7003, &_globals->_player, 0); + } + } + if (_globals->_sceneRegions.indexOf(_globals->_player._position) == 9) + scene->setAction(&scene->_action7); + } + Scene::dispatch(); +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::postInit(SceneObjectList *OwnerList) { + loadScene(7000); + Scene::postInit(); + setZoomPercents(93, 25, 119, 55); + _stripManager.addSpeaker(&_speakerSKText); + _stripManager.addSpeaker(&_speakerSKL); + _stripManager.addSpeaker(&_speakerQText); + _stripManager.addSpeaker(&_speakerQL); + _stripManager.addSpeaker(&_speakerQR); + + _speakerSKText._npc = &_object1; + _speakerQText._npc = &_globals->_player; + + _object5.postInit(); + _object5.setVisage(7001); + _object5.setStrip2(1); + _object5.animate(ANIM_MODE_2, 0); + _object5.setPosition(Common::Point(49, 147), 0); + _object5.setPriority2(1); + + _object6.postInit(); + _object6.setVisage(7001); + _object6.setStrip2(2); + _object6.animate(ANIM_MODE_2, 0); + _object6.setPosition(Common::Point(160, 139), 0); + _object6.setPriority2(1); + + _object7.postInit(); + _object7.setVisage(7001); + _object7.setStrip2(3); + _object7.animate(ANIM_MODE_2, 0); + _object7.setPosition(Common::Point(272, 129), 0); + _object7.setPriority2(1); + + _object8.postInit(); + _object8.setVisage(7001); + _object8.setStrip2(4); + _object8.animate(ANIM_MODE_2, 0); + _object8.setPosition(Common::Point(176, 175), 0); + _object8.setPriority2(1); + + if (_globals->getFlag(72)) { + _object3.postInit(); + _object3.setVisage(5001); + _object3.setStrip2(1); + _object3.animate(ANIM_MODE_2, 0); + _object3.setPosition(Common::Point(107, 92), 0); + _object3.changeZoom(100); + _object3.setPriority2(10); + + _object1.postInit(); + _object1.setVisage(7003); + if (_globals->getFlag(81)) + _object1.setStrip(4); + else + _object1.setStrip(2); + _object1.setPosition(Common::Point(87, 129), 0); + _object1._numFrames = 4; + _object1.changeZoom(45); + _object1.animate(ANIM_MODE_8, 0, 0); + _globals->_sceneItems.addItems(&_object1, 0); + } + _soundHandler.startSound(251, 0, 127); + if (_globals->_sceneManager._previousScene == 2100) { + if (_globals->getFlag(72)) { + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, 0); + SceneObjectWrapper *wrapper = new SceneObjectWrapper(); + _globals->_player.setObjectWrapper(wrapper); + _globals->_player.setPosition(Common::Point(57, 94), 0); + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(10); + if (_globals->getFlag(81)) { + setAction(&_action4); + } else { + _object1.setPosition(Common::Point(151, 182), 0); + setAction(&_action1); + } + } else { + _globals->_soundHandler.startSound(250, 0, 127); + _globals->setFlag(72); + + _object3.postInit(); + _object3.setVisage(5001); + _object3.setStrip2(1); + _object3.animate(ANIM_MODE_1, 0); + _object3.setPosition(Common::Point(307, 0), 0); + _object3.changeZoom(-1); + setAction(&_action3); + } + } else if (_globals->_sceneManager._previousScene == 2280) { + _globals->_player.postInit(); + _globals->_player.setVisage(2170); + _globals->_player.animate(ANIM_MODE_1, 0); + SceneObjectWrapper *wrapper = new SceneObjectWrapper(); + _globals->_player.setObjectWrapper(wrapper); + _globals->_player.setPosition(Common::Point(57, 94), 0); + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(10); + _globals->_player.disableControl(); + _sceneMode = 7001; + setAction(&_action6, this); + if (!_globals->getFlag(81)) { + _object1.setPosition(Common::Point(151, 182), 0); + _object1.changeZoom(100); + } + _object8.remove(); + _object9.remove(); + } else if (_globals->_sceneManager._previousScene == 2320) { + _globals->_player.postInit(); + _globals->_player.setVisage(0); + _globals->_player.animate(ANIM_MODE_1, 0); + SceneObjectWrapper *wrapper = new SceneObjectWrapper(); + _globals->_player.setObjectWrapper(wrapper); + _globals->_player.setPosition(Common::Point(57, 94), 0); + _globals->_player.changeZoom(-1); + _globals->_player.setPriority2(10); + _sceneMode = 7001; + setAction(&_action6, this); + } else { + _globals->setFlag(72); + + _object3.postInit(); + _object3.setVisage(5001); + _object3.setStrip2(1); + _object3.setPosition(Common::Point(307, 0), 0); + _soundHandler.startSound(151, 0, 127); + _soundHandler.proc5(1); + _globals->_soundHandler.startSound(250, 0, 127); + setAction(&_action3); + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7000::signal() { + Scene7000 *scene = (Scene7000 *)_globals->_sceneManager._scene; + switch (_sceneMode) { + case 7001: + case 7002: + case 7004: + case 7009: + _globals->_player.enableControl(); + break; + case 7003: + _sceneMode = 7001; + setAction(&scene->_sequenceManager, this, 7001, &_globals->_player, NULL); + break; + case 7011: + _sceneMode = 7005; + setAction(&scene->_sequenceManager, this, 7005, &_globals->_player, NULL); + break; + case 7012: + _sceneMode = 7005; + setAction(&scene->_sequenceManager, this, 7012, &_globals->_player, NULL); + break; + case 7015: + setAction(&_action4); + break; + } +} + + +/*-------------------------------------------------------------------------- + * Scene 7100 + * + *--------------------------------------------------------------------------*/ + +void Scene7100::Action3::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: { + Common::Point pt(433, 308); + NpcMover *mover = new NpcMover(); + scene->_object4.addMover(mover, &pt, this); + break; + } + case 2: + scene->_object4.remove(); + remove(); + break; + } +} + +void Scene7100::Action4::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(1) + 1); + break; + case 1: { + scene->_object5.setStrip(3); + Common::Point pt(85, 52); + NpcMover *mover = new NpcMover(); + scene->_object5.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object5.setStrip(4); + Common::Point pt(20, 52); + NpcMover *mover = new NpcMover(); + scene->_object5.addMover(mover, &pt, this); + break; + } + case 3: + _actionIndex = 0; + setDelay(1); + break; + } +} + +void Scene7100::Action5::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: { + Common::Point pt(59, 151); + NpcMover *mover = new NpcMover(); + scene->_object9.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object9.setStrip2(1); + Common::Point pt(127, 144); + NpcMover *mover = new NpcMover(); + scene->_object9.addMover(mover, &pt, this); + break; + } + case 3: { + scene->_object9.setStrip2(2); + scene->_object9.setPriority2(180); + Common::Point pt(8, 181); + NpcMover *mover = new NpcMover(); + scene->_object9.addMover(mover, &pt, this); + break; + } + case 4: { + scene->_object9.remove(); + remove(); + } + } +} + +void Scene7100::Action6::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + scene->_object10.setPriority2(8); + scene->_object10.setPosition(Common::Point(155, 187), 0); + + scene->_object11.setPriority2(8); + scene->_object11.setPosition(Common::Point(155, 190), 0); + + scene->_object12.setPriority2(8); + scene->_object12.setPosition(Common::Point(151, 193), 0); + break; + case 1: { + Common::Point pt1(167, 187); + NpcMover *mover1 = new NpcMover(); + scene->_object10.addMover(mover1, &pt1, this); + + Common::Point pt2(165, 185); + NpcMover *mover2 = new NpcMover(); + scene->_object11.addMover(mover2, &pt2, 0); + + Common::Point pt3(163, 183); + NpcMover *mover3 = new NpcMover(); + scene->_object12.addMover(mover3, &pt3, 0); + break; + } + case 2: { + scene->_object10.setStrip2(6); + Common::Point pt1(91, 187); + NpcMover *mover1 = new NpcMover(); + scene->_object10.addMover(mover1, &pt1, this); + + scene->_object11.setStrip2(6); + scene->_object11.setPriority2(50); + Common::Point pt2(89, 185); + NpcMover *mover2 = new NpcMover(); + scene->_object11.addMover(mover2, &pt2, 0); + + scene->_object12.setStrip2(6); + scene->_object12.setPriority2(50); + Common::Point pt3(87, 183); + NpcMover *mover3 = new NpcMover(); + scene->_object12.addMover(mover3, &pt3, 0); + break; + } + case 3: + _actionIndex = 0; + setDelay(1); + break; + } +} + +void Scene7100::Action7::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: { + scene->_object13.setStrip2(8); + Common::Point pt(324, 87); + NpcMover *mover = new NpcMover(); + scene->_object13.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object13.setStrip2(2); + Common::Point pt(524, 104); + NpcMover *mover = new NpcMover(); + scene->_object13.addMover(mover, &pt, 0); + break; + } + case 3: + _actionIndex = 0; + setDelay(1); + break; + } +} + +void Scene7100::Action8::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: { + scene->_object17.setStrip2(4); + scene->_object18.setStrip2(4); + scene->_object19.setStrip2(4); + + Common::Point pt1(482, 153); + NpcMover *mover1 = new NpcMover(); + scene->_object17.addMover(mover1, &pt1, this); + + Common::Point pt2(480, 146); + NpcMover *mover2 = new NpcMover(); + scene->_object18.addMover(mover2, &pt2, 0); + + Common::Point pt3(470, 153); + NpcMover *mover3 = new NpcMover(); + scene->_object19.addMover(mover3, &pt3, 0); + break; + } + case 2: { + scene->_object17.setStrip2(3); + scene->_object18.setStrip2(3); + scene->_object19.setStrip2(3); + + Common::Point pt1(506, 186); + NpcMover *mover1 = new NpcMover(); + scene->_object17.addMover(mover1, &pt1, this); + + Common::Point pt2(502, 179); + NpcMover *mover2 = new NpcMover(); + scene->_object18.addMover(mover2, &pt2, 0); + + Common::Point pt3(495, 184); + NpcMover *mover3 = new NpcMover(); + scene->_object19.addMover(mover3, &pt3, 0); + break; + } + case 3: { + scene->_object17.setStrip2(4); + scene->_object18.setStrip2(4); + scene->_object19.setStrip2(4); + + Common::Point pt1(386, 167); + NpcMover *mover1 = new NpcMover(); + scene->_object17.addMover(mover1, &pt1, this); + + Common::Point pt2(379, 161); + NpcMover *mover2 = new NpcMover(); + scene->_object18.addMover(mover2, &pt2, 0); + + Common::Point pt3(373, 167); + NpcMover *mover3 = new NpcMover(); + scene->_object19.addMover(mover3, &pt3, 0); + break; + } + case 4: { + scene->_object17.setStrip2(3); + scene->_object18.setStrip2(3); + scene->_object19.setStrip2(3); + + Common::Point pt1(479, 193); + NpcMover *mover1 = new NpcMover(); + scene->_object17.addMover(mover1, &pt1, this); + + Common::Point pt2(473, 187); + NpcMover *mover2 = new NpcMover(); + scene->_object18.addMover(mover2, &pt2, 0); + + Common::Point pt3(466, 192); + NpcMover *mover3 = new NpcMover(); + scene->_object19.addMover(mover3, &pt3, 0); + break; + } + case 5: { + Common::Point pt1(552, 183); + NpcMover *mover1 = new NpcMover(); + scene->_object17.addMover(mover1, &pt1, this); + + Common::Point pt2(552, 178); + NpcMover *mover2 = new NpcMover(); + scene->_object18.addMover(mover2, &pt2, 0); + + Common::Point pt3(541, 183); + NpcMover *mover3 = new NpcMover(); + scene->_object19.addMover(mover3, &pt3, 0); + + _actionIndex = 0; + break; + } + } +} + +void Scene7100::Action9::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1); + break; + case 1: { + scene->_object24.setStrip2(1); + Common::Point pt(64, 159); + NpcMover *mover = new NpcMover(); + scene->_object24.addMover(mover, &pt, this); + break; + } + case 2: { + scene->_object24.setStrip2(2); + scene->_object24.setPriority2(160); + Common::Point pt(34, 159); + NpcMover *mover = new NpcMover(); + scene->_object24.addMover(mover, &pt, this); + break; + } + case 3: { + scene->_object24.setStrip2(1); + Common::Point pt(64, 159); + NpcMover *mover = new NpcMover(); + scene->_object24.addMover(mover, &pt, this); + break; + } + case 4: { + scene->_object24.setStrip2(2); + scene->_object24.setPriority2(180); + Common::Point pt(-12, 182); + NpcMover *mover = new NpcMover(); + scene->_object24.addMover(mover, &pt, this); + break; + } + case 5: { + _actionIndex = 0; + setDelay(1); + break; + } + } +} + +void Scene7100::Action10::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(1000); + break; + case 1: { + Common::Point pt(610, -60); + NpcMover *mover = new NpcMover(); + scene->_object25.addMover(mover, &pt, this); + break; + } + case 2: + scene->_object25.remove(); + remove(); + break; + } +} + +void Scene7100::Action11::signal() { + Scene7100 *scene = (Scene7100 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: { + Common::Point pt(154, 175); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + ObjectMover2 *mover2 = new ObjectMover2(); + scene->_object1.addMover(mover2, 25, 35, &_globals->_player); + break; + } + case 2: { + Common::Point pt(700, 155); + NpcMover *mover = new NpcMover(); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 3: + _globals->_sceneManager.changeScene(7200); + remove(); + break; + } +} + +void Scene7100::postInit(SceneObjectList *OwnerList) { + loadScene(7100); + Scene::postInit(); + setZoomPercents(60, 85, 200, 100); + + _object2.postInit(); + _object2.setVisage(7161); + _object2.animate(ANIM_MODE_2, 0); + _object2.setPosition(Common::Point(10, 140), 0); + _object2._numFrames = 1; + _object2.setPriority2(180); + _object2.setAction(&_action1, 0); + + _object3.postInit(); + _object3.setVisage(7161); + _object3.animate(ANIM_MODE_2, 0); + _object3.setPosition(Common::Point(34, 115), 0); + _object3._numFrames = 1; + _object3.setPriority2(180); + _object3.setAction(&_action2, 0); + + _object4.postInit(); + _object4.setVisage(7164); + _object4.animate(ANIM_MODE_2, 0); + _object4.setPosition(Common::Point(-10, 159), 0); + _object4._numFrames = 2; + _object4.setPriority2(250); + _object4.setAction(&_action3, 0); + + _object5.postInit(); + _object5.setVisage(7162); + _object5.setStrip(3); + _object5.animate(ANIM_MODE_2, 0); + _object5.setPosition(Common::Point(20, 52), 0); + _object5.setAction(&_action4, 0); + + _object9.postInit(); + _object9.setVisage(7160); + _object5.setStrip(2); + _object9.animate(ANIM_MODE_2, 0); + _object9.setPosition(Common::Point(110, 168), 0); + _object9._numFrames = 2; + _object9.setPriority2(16); + _object9.setAction(&_action5, 0); + + _object13.postInit(); + _object13.setVisage(7161); + _object13.setStrip(8); + _object13.animate(ANIM_MODE_2, 0); + _object13.setPosition(Common::Point(524, 104), 0); + _object13._numFrames = 5; + _object13.setPriority2(250); + _object13.setAction(&_action7, 0); + + _object17.postInit(); + _object17.setVisage(7160); + _object17.setStrip(3); + _object17.animate(ANIM_MODE_2, 0); + _object17.setPosition(Common::Point(552, 183), 0); + _object17._numFrames = 4; + _object17._moveDiff.x = 12; + _object17._moveDiff.y = 12; + _object17.setAction(&_action8, 0); + + _object18.postInit(); + _object18.setVisage(7160); + _object18.setStrip(3); + _object18.animate(ANIM_MODE_2, 0); + _object18.setPosition(Common::Point(552, 178), 0); + _object18._numFrames = 4; + _object18._moveDiff.x = 12; + _object18._moveDiff.y = 12; + + _object19.postInit(); + _object19.setVisage(7160); + _object19.setStrip(3); + _object19.animate(ANIM_MODE_2, 0); + _object19.setPosition(Common::Point(541, 183), 0); + _object19._numFrames = 4; + _object19._moveDiff.x = 12; + _object19._moveDiff.y = 12; + + _object24.postInit(); + _object24.setVisage(7162); + _object24.setStrip(1); + _object24.animate(ANIM_MODE_2, 0); + _object24.setPosition(Common::Point(-12, 182), 0); + _object24._numFrames = 4; + _object24.setPriority2(180); + _object24.setAction(&_action9, 0); + + _object25.postInit(); + _object25.setVisage(7163); + _object25.animate(ANIM_MODE_2, 0); + _object25.setPosition(Common::Point(551, 145), 0); + _object25._numFrames = 5; + _object25.setPriority2(160); + _object25.setAction(&_action10, 0); + + // Swimmer 1 + _globals->_player.postInit(); + _globals->_player.setVisage(7101); + _globals->_player.animate(ANIM_MODE_2, 0); + _globals->_player._moveDiff.x = 4; + _globals->_player._moveDiff.y = 2; + _globals->_player.setPosition(Common::Point(135, 135), 0); + _globals->_player.setPriority2(200); + _globals->_player.disableControl(); + + // Swimmer 2 + _object1.postInit(); + _object1.setVisage(7110); + _object1.animate(ANIM_MODE_1, 0); + _object1._moveDiff.x = 4; + _object1._moveDiff.y = 2; + _object1.setPosition(Common::Point(100, 100), 0); + + setAction(&_action11); + _soundHandler1.startSound(270, 0, 127); + _soundHandler2.startSound(275, 0, 127); + _globals->_soundHandler.startSound(270, 0, 127); +} +/*-------------------------------------------------------------------------- + * Scene 7200 + * + *--------------------------------------------------------------------------*/ + +void Scene7200::Action1::signal() { + Scene7200 *scene = (Scene7200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(15); + break; + case 1: { + PlayerMover *mover1 = new PlayerMover(); + Common::Point pt1(165, 147); + scene->_swimmer.addMover(mover1, &pt1, this); + Common::Point pt2(207, 138); + PlayerMover *mover2 = new PlayerMover(); + _globals->_player.addMover(mover2, &pt2, this); + break; + } + case 2: + break; + case 3: + _globals->_sceneManager.changeScene(7300); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7200::Action2::signal() { + Scene7200 *scene = (Scene7200 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(3); + break; + case 1: { + scene->_object2.setPriority2(25); + scene->_object3.setPriority2(25); + scene->_object4.setPriority2(25); + scene->_object2.setStrip(1); + scene->_object3.setStrip(1); + scene->_object4.setStrip(1); + NpcMover *mover1 = new NpcMover(); + Common::Point pt1(54, 90); + scene->_object2.addMover(mover1, &pt1, this); + NpcMover *mover2 = new NpcMover(); + Common::Point pt2(56, 85); + scene->_object3.addMover(mover2, &pt2, 0); + NpcMover *mover3 = new NpcMover(); + Common::Point pt3(54, 80); + scene->_object4.addMover(mover3, &pt3, 0); + break; + } + case 2: { + scene->_object2.setPriority2(160); + scene->_object3.setPriority2(160); + scene->_object4.setPriority2(160); + scene->_object2.setStrip(2); + scene->_object3.setStrip(2); + scene->_object4.setStrip(2); + NpcMover *mover1 = new NpcMover(); + Common::Point pt1(10, 89); + scene->_object2.addMover(mover1, &pt1, this); + NpcMover *mover2 = new NpcMover(); + Common::Point pt2(12, 84); + scene->_object3.addMover(mover2, &pt2, 0); + NpcMover *mover3 = new NpcMover(); + Common::Point pt3(10, 79); + scene->_object4.addMover(mover3, &pt3, 0); + break; + } + case 3: + _actionIndex = 0; + setDelay(1); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7200::postInit(SceneObjectList *OwnerList) { + loadScene(7200); + Scene::postInit(); + _object2.postInit(); + _object2.setVisage(7160); + _object2.animate(ANIM_MODE_2, 0); + _object2.setZoom(10); + _object2.setPosition(Common::Point(53, 88), 0); + _object2.setAction(&_action2); + + _object3.postInit(); + _object3.setVisage(7160); + _object3.animate(ANIM_MODE_2, 0); + _object3.setZoom(10); + _object3.setPosition(Common::Point(55, 83), 0); + + _object4.postInit(); + _object4.setVisage(7160); + _object4.animate(ANIM_MODE_2, 0); + _object4.setZoom(10); + _object4.setPosition(Common::Point(57, 78), 0); + + _object5.postInit(); + _object5.setVisage(7201); + _object5.setPosition(Common::Point(300, 172), 0); + _object5.setPriority(172); + _object5.animate(ANIM_MODE_2, 0); + _object5._numFrames = 3; + + _object6.postInit(); + _object6.setVisage(7201); + _object6.setStrip2(3); + _object6.setPosition(Common::Point(144, 97), 0); + _object6.setPriority(199); + _object6.animate(ANIM_MODE_2, 0); + _object6._numFrames = 3; + + _object7.postInit(); + _object7.setVisage(7201); + _object7.setStrip2(4); + _object7.setPosition(Common::Point(115, 123), 0); + _object7.setPriority(199); + _object7.animate(ANIM_MODE_2, 0); + _object7._numFrames = 3; + + _object8.postInit(); + _object8.setVisage(7201); + _object8.setStrip2(6); + _object8.setPosition(Common::Point(140, 173), 0); + _object8.setPriority(199); + _object8.animate(ANIM_MODE_2, 0); + _object8._numFrames = 3; + + _object9.postInit(); + _object9.setVisage(7201); + _object9.setStrip2(7); + _object9.setPosition(Common::Point(215, 196), 0); + _object9.setPriority(199); + _object9.animate(ANIM_MODE_2, 0); + _object9._numFrames = 3; + + // Orange swimmer + _globals->_player.postInit(); + _globals->_player.setVisage(7110); + _globals->_player.animate(ANIM_MODE_1, 0); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setZoom(50); + _globals->_player.setPosition(Common::Point(-18, 16), 0); + _globals->_player.disableControl(); + + _swimmer.postInit(); + _swimmer.setVisage(7101); + _swimmer.animate(ANIM_MODE_1, 0); + _swimmer.setObjectWrapper(new SceneObjectWrapper()); + _swimmer.setZoom(50); + _swimmer.setPosition(Common::Point(-8, 16), 0); + + setAction(&_action1); + _soundHandler.startSound(271, 0, 127); +} + +/*-------------------------------------------------------------------------- + * Scene 7300 + * + *--------------------------------------------------------------------------*/ + +void Scene7300::Action1::signal() { + Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + case 1: + case 3: + setDelay(30); + break; + case 2: + scene->_stripManager.start(7300, this); + break; + case 4: { + NpcMover *mover = new NpcMover(); + Common::Point pt(102, 122); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 5: + _globals->_player.setStrip(2); + _globals->_player.setFrame(1); + _globals->_player.animate(ANIM_MODE_5, this); + break; + case 6: + _globals->_player.setStrip(3); + _globals->_player._numFrames = 5; + _globals->_player.animate(ANIM_MODE_2, this); + if (_globals->_inventory._translator._sceneNumber == 1) + scene->_stripManager.start(7310, this); + else + scene->_stripManager.start(7305, this); + break; + case 7: + setDelay(3); + _globals->_soundHandler.proc1(0); + break; + case 8: + _globals->_sceneManager.changeScene(2280); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7300::Action2::signal() { + Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + NpcMover *mover1 = new NpcMover(); + Common::Point pt(_globals->_randomSource.getRandomNumber(203), _globals->_randomSource.getRandomNumber(96)); + scene->_object3.addMover(mover1, &pt, this); + _actionIndex = 0; + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7300::Action3::signal() { + Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene; + + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + NpcMover *mover1 = new NpcMover(); + Common::Point pt(_globals->_randomSource.getRandomNumber(76), _globals->_randomSource.getRandomNumber(78)); + scene->_object1.addMover(mover1, &pt, this); + _actionIndex = 0; + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7300::Action4::signal() { + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: + _actionIndex = 0; + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7300::dispatch() { + Scene7300 *scene = (Scene7300 *)_globals->_sceneManager._scene; + scene->_object4.setPosition(Common::Point(scene->_object3._position.x + 15, scene->_object3._position.y + 61)); + scene->_object2.setPosition(Common::Point(scene->_object1._position.x + 1, scene->_object1._position.y - 31)); + + Scene::dispatch(); +} + +/*--------------------------------------------------------------------------*/ + +void Scene7300::postInit(SceneObjectList *OwnerList) { + loadScene(7300); + + Scene::postInit(); + setZoomPercents(60, 85, 200, 100); + + _globals->setFlag(52); + _globals->setFlag(24); + _globals->setFlag(109); + + _stripManager.addSpeaker(&_speakerPOR); + _stripManager.addSpeaker(&_speakerPOText); + _stripManager.addSpeaker(&_speakerSKText); + _stripManager.addSpeaker(&_speakerQU); + + _speakerSKText.setTextPos(Common::Point(100, 20)); + _speakerPOText.setTextPos(Common::Point(100, 160)); + + _object4.postInit(); + _object4.setVisage(7311); + _object4.setStrip(1); + _object4.setFrame(1); + _object4.setPosition(Common::Point(218, 157), 0); + + _object3.postInit(); + _object3.setVisage(7311); + _object3.setStrip(2); + _object3.setFrame(1); + _object3.setPosition(Common::Point(203, 96), 0); + _object3._numFrames = 2; + _object3._moveDiff = Common::Point(1, 1); + _object3.animate(ANIM_MODE_8, 0, 0); + _object3._field7A = 2; + _object3.setAction(&_action2); + + _globals->_player.postInit(); + _globals->_player.setVisage(7305); + _globals->_player.animate(ANIM_MODE_1, 0); + _globals->_player.setPosition(Common::Point(-100, 100), 0); + _globals->_player.disableControl(); + + _object1.postInit(); + _object1.setVisage(7312); + _object1.animate(ANIM_MODE_1, 0); + _object1._moveDiff = Common::Point(1, 1); + _object1.setPosition(Common::Point(76, 78), 0); + _object1._field7A = 1; + _object1.setAction(&_action3); + + _object2.postInit(); + _object2.setVisage(7312); + _object2.setStrip(2); + _object2.animate(ANIM_MODE_2, 0); + _object2.setPosition(Common::Point(77, 47), 0); + _object2.setPriority2(190); + + _object5.postInit(); + _object5.setVisage(7300); + _object5.setPosition(Common::Point(106, 45), 0); + _object5.animate(ANIM_MODE_2, 0); + _object5._numFrames = 5; + + _object6.postInit(); + _object6.setVisage(7300); + _object6.setStrip2(2); + _object6.setPosition(Common::Point(283, 193), 0); + _object6.animate(ANIM_MODE_2, 0); + _object6._numFrames = 3; + + _object7.postInit(); + _object7.setVisage(7300); + _object7.setStrip(4); + _object7.setPosition(Common::Point(295, 77), 0); + _object7.animate(ANIM_MODE_2, 0); + _object7._numFrames = 3; + + _object8.postInit(); + _object8.setVisage(7300); + _object8.setStrip(5); + _object8.setPosition(Common::Point(1, 147), 0); + _object8.animate(ANIM_MODE_2, 0); + _object8._numFrames = 2; + + setAction(&_action1); + _globals->_soundHandler.startSound(272, 0, 127); +} + +/*-------------------------------------------------------------------------- + * Scene 7600 + * + *--------------------------------------------------------------------------*/ + +void Scene7600::Action1::signal() { + switch (_actionIndex++) { + case 0: + setDelay(120); + break; + case 1: { + PlayerMover *mover = new PlayerMover(); + Common::Point pt(389, 57); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_sceneManager.changeScene(7700); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7600::Action2::signal() { + switch (_actionIndex++) { + case 0: + setDelay(30); + break; + case 1: { + NpcMover *mover = new NpcMover(); + Common::Point pt(-30, 195); + _globals->_player.addMover(mover, &pt, this); + break; + } + case 2: + _globals->_sceneManager.changeScene(2320); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene7600::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + setZoomPercents(100, 0, 200, 100); + + _object2.postInit(); + _object2.setVisage(7601); + _object2.setStrip(1); + _object2.animate(ANIM_MODE_2, 0); + _object2.setPosition(Common::Point(48, 135)); + _object2.setPriority2(1); + + _object3.postInit(); + _object3.setVisage(7601); + _object3.setStrip(2); + _object3.animate(ANIM_MODE_2, 0); + _object3.setPosition(Common::Point(158, 136)); + _object3.setPriority2(1); + + _object4.postInit(); + _object4.setVisage(7601); + _object4.setStrip(3); + _object4.animate(ANIM_MODE_2, 0); + _object4.setPosition(Common::Point(293, 141)); + _object4.setPriority2(1); + + _object5.postInit(); + _object5.setVisage(7601); + _object5.setStrip(4); + _object5.animate(ANIM_MODE_2, 0); + _object5.setPosition(Common::Point(405, 143)); + _object5.setPriority2(1); + + _object6.postInit(); + _object6.setVisage(7601); + _object6.setStrip(5); + _object6.animate(ANIM_MODE_2, 0); + _object6.setPosition(Common::Point(379, 191)); + _object6.setPriority2(1); + + _globals->_player.postInit(); + _globals->_player.setVisage(2333); + _globals->_player.animate(ANIM_MODE_1, 0); + _globals->_player.setObjectWrapper(new SceneObjectWrapper()); + _globals->_player.setStrip(1); + _globals->_player._moveDiff = Common::Point(16, 16); + _globals->_player.changeZoom(-1); + _globals->_player.disableControl(); + + if (_globals->_sceneManager._previousScene == 7700) { + _globals->_player.setPosition(Common::Point(389, 57)); + setAction(&_action2); + } else { + _globals->_player.setPosition(Common::Point(-50, 195)); + setAction(&_action1); + } + _sceneBounds.centre(_globals->_player._position.x, _globals->_player._position.y); + loadScene(7600); + _soundHandler2.startSound(255); + _soundHandler1.startSound(251); +} + +/*-------------------------------------------------------------------------- + * Scene 7700 + * + *--------------------------------------------------------------------------*/ + +void Scene7700::Action1::signal() { + SceneObject *fmtObj = (SceneObject *) _fmt; + switch (_actionIndex++) { + case 0: { + PlayerMover *mover1 = new PlayerMover(); + Common::Point pt = Common::Point(fmtObj->_position.x, fmtObj->_position.y + 30); + _globals->_player.addMover(mover1, &pt, this); + break; + } + case 1: + _globals->_player.checkAngle(fmtObj); + if (_globals->_player._field8C == 0) + fmtObj->animate(ANIM_MODE_5, this); + else + fmtObj->animate(ANIM_MODE_6, this); + break; + case 2: + remove(); + break; + } +} + +void Scene7700::Action2::signal() { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + switch (_actionIndex++) { + case 0: + case 2: + setDelay(_globals->_randomSource.getRandomNumber(60) + 60); + break; + case 1: + scene->_prof.animate(ANIM_MODE_7, 0, 0); + setDelay(20); + break; + case 3: + scene->_prof.animate(ANIM_MODE_6, this); + _actionIndex = 0; + break; + } +} + +void Scene7700::Action3::signal() { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + switch (_actionIndex++) { + case 0: + scene->_object15.animate(ANIM_MODE_5, this); + break; + case 1: + scene->_sceneItem10.remove(); + scene->_object15.remove(); + scene->_sceneHotspot8.remove(); + scene->_sceneHotspot9.remove(); + scene->_object19.remove(); + setDelay(60); + // No break on purpose! + case 2: + scene->_soundHandler.startSound(260, 0, 127); + scene->_object8.setVisage(7703); + scene->_object8.setPosition(Common::Point(177, 97), 0); + scene->_object8.setStrip2(3); + scene->_object8.animate(ANIM_MODE_5, this); + scene->_object8._numFrames = 3; + break; + case 3: + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene7700::Action4::signal() { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + switch (_actionIndex++) { + case 2: + scene->_object13.remove(); + // No break on purpose! + case 0: + setDelay(3); + break; + case 1: + CursorMan.showMouse(false); + scene->_object13.postInit(); + scene->_object13.setVisage(7700); + scene->_object13.setStrip2(7); + scene->_object13.setPosition(Common::Point(151, 33), 0); + scene->_object13.animate(ANIM_MODE_5, this); + break; + case 3: + CursorMan.showMouse(true); + SceneItem::display(7700, 11, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + _globals->_player.enableControl(); + remove(); + break; + } +} + +void Scene7700::Action5::signal() { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + switch (_actionIndex++) { + case 0: + setDelay(_globals->_randomSource.getRandomNumber(240)); + break; + case 1: { + scene->_cloud.setFrame(_globals->_randomSource.getRandomNumber(1) + 1); + scene->_cloud.setPosition(Common::Point(133, 145 + _globals->_randomSource.getRandomNumber(54)), 0); + + Common::Point pt(360, scene->_cloud._position.y); + NpcMover *mover = new NpcMover(); + scene->_cloud.addMover(mover, &pt, this); + _actionIndex = 0; + break; + } + } +} + +void Scene7700::Action6::signal() { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + switch (_actionIndex++) { + case 0: + setDelay(5); + break; + case 1: { + Common::Point pt(2, 66); + NpcMover *mover = new NpcMover(); + scene->_easterEgg1.addMover(mover, &pt, this); + break; + } + case 2: + scene->_easterEgg1.setStrip(2); + scene->_easterEgg1.setPosition(Common::Point(43, 65), 0); + + scene->_easterEgg2.postInit(); + scene->_easterEgg2.setVisage(7708); + scene->_easterEgg2.setStrip(3); + scene->_easterEgg2.setPosition(Common::Point(116, 54), 0); + scene->_easterEgg2.animate(ANIM_MODE_2, 0); + + setDelay(120); + break; + case 3: + scene->_easterEgg1.remove(); + scene->_easterEgg2.remove(); + remove(); + break; + } +} + +void Scene7700::SceneHotspot1::doAction(int action) { + if (action == CURSOR_LOOK) + SceneItem::display(7700, 4, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneHotspot::doAction(action); +} + +void Scene7700::SceneHotspot2::doAction(int action) { + if (action == CURSOR_LOOK) + SceneItem::display(7700, 6, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneHotspot::doAction(action); +} + +void Scene7700::SceneHotspot3::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_KEY: + SceneItem::display(7702, 3, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + _globals->_inventory._key._sceneNumber = 7700; + break; + case CURSOR_LOOK: + if (_globals->_inventory._key._sceneNumber == 7700) + scene->setAction(&scene->_action4, 0); + else + SceneItem::display(7700, 53, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (!_globals->getFlag(78)) { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, 0); + } else if (_globals->_inventory._key._sceneNumber == 7700) { + _globals->_player.disableControl(); + scene->_sceneMode = 7705; + scene->setAction(&scene->_sequenceManager, scene, 7705, &_globals->_player, 0); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneHotspot4::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 12, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (!_globals->getFlag(78)) { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, 0); + } else { + SceneItem::display(7700, 12, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneHotspot5::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 28, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (_globals->getFlag(78)) { + if (_globals->_inventory._paper._sceneNumber == 7700) { + _globals->_player.disableControl(); + scene->_sceneMode = 7708; + scene->setAction(&scene->_sequenceManager, scene, 7708, &_globals->_player, 0); + } + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, 0); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneHotspot6::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 43, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + SceneItem::display(7700, 56, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneItem7::doAction(int action) { + if (action == CURSOR_LOOK) + SceneItem::display(7700, 51, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); +} + +void Scene7700::SceneHotspot8::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 48, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + scene->_sceneMode = 7709; + scene->_soundHandler.startSound(259, 0, 127); + scene->_object15.setFrame(scene->_object15.getFrameCount()); + scene->_object15.animate(ANIM_MODE_6, scene); + if ((scene->_field977 == 2) && (scene->_field97B == 0)) { + scene->_field979++; + } else { + scene->_field97B = 0; + scene->_field979 = 0; + scene->_field977 = 0; + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneHotspot9::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 48, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + scene->_sceneMode = 7709; + scene->_soundHandler.startSound(259, 0, 127); + scene->_object15.setFrame(1); + scene->_object15.animate(ANIM_MODE_5, scene); + if (scene->_field977 > 2) { + scene->_field97B = 0; + scene->_field979 = 0; + scene->_field977 = 0; + } + + if (scene->_field979 != 0) { + if (scene->_field979 != 4) { + scene->_field97B = 0; + scene->_field979 = 0; + scene->_field977 = 0; + } else { + scene->_field97B++; + if (scene->_field97B == 3) { + _globals->_player.disableControl(); + scene->setAction(&scene->_action3); + } + } + } else { + scene->_field977++; + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::SceneItem10::doAction(int action) { +} + +void Scene7700::Object1::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display(7700, _lookLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + if (_globals->getFlag(78)) { + _globals->_player.disableControl(); + scene->setAction(&scene->_action1, this); + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, 0); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene7700::SceneHotspot11::doAction(int action) { + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, _lookLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + SceneItem::display(7701, _useLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::Object1::signal() { + if (_state == 0) { + _state = 1; + SceneItem::display(7701, _defltLineNum, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + _state = 0; + } + _globals->_player.enableControl(); +} + +void Scene7700::Object3::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display(7700, 34, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + if (_globals->getFlag(78)) { + if (scene->_object3._frame == 1) { + _globals->_player.disableControl(); + scene->_sceneMode = 7707; + scene->setAction(&scene->_sequenceManager, scene, 7707, &_globals->_player, this, 0); + } else { + SceneItem::display(7700, 60, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, 0); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene7700::Object7::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + if (_globals->getFlag(78)) + SceneItem::display(7700, 45, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneItem::display(7700, 44, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (_globals->getFlag(78)) { + SceneItem::display(7701, 41, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7714, 0); + } + break; + case CURSOR_TALK: + if (_globals->getFlag(78)) { + SceneItem::display(7702, 1, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + _globals->_player.disableControl(); + if (_state == 0) { + _state = 1; + scene->_sceneMode = 7703; + scene->setAction(&scene->_sequenceManager, scene, 7703, 0); + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7712, 0); + } + } + break; + case OBJECT_STUNNER: + if (!_globals->getFlag(78)) { + _globals->_soundHandler.proc3(); + _globals->setFlag(78); + setAction(0); + _globals->_player.disableControl(); + scene->_sceneMode = 7704; + scene->setAction(&scene->_sequenceManager, scene, 7704, &_globals->_player, this, 0); + } + break; + default: + SceneHotspot::doAction(action); + break; + } +} + +void Scene7700::Object8::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + if ((action == CURSOR_LOOK) || (action == CURSOR_USE)) { + if (_strip == 3) { + scene->_object9.postInit(); + scene->_object9.setVisage(7701); + scene->_object9.setStrip2(3); + scene->_object9.setPosition(Common::Point(91, 166), 0); + scene->_object9.setPriority2(200); + + scene->_object14.postInit(); + scene->_object14.setVisage(7701); + scene->_object14.setStrip(2); + scene->_object14.setPriority2(250); + scene->_object14.setPosition(Common::Point(139, 151), 0); + + scene->_gfxButton.setText(EXIT_MSG); + scene->_gfxButton._bounds.centre(140, 189); + scene->_gfxButton.draw(); + scene->_gfxButton._bounds.expandPanes(); + + _globals->_sceneItems.push_front(&scene->_object10); + _globals->_sceneItems.push_front(&scene->_object9); + _globals->_player._canWalk = false; + } else { + scene->_object15.postInit(); + scene->_object15.setVisage(7701); + scene->_object15.setPosition(Common::Point(140, 165), 0); + scene->_object15.setPriority2(200); + + scene->_gfxButton.setText(EXIT_MSG); + scene->_gfxButton._bounds.centre(140, 186); + scene->_gfxButton.draw(); + scene->_gfxButton._bounds.expandPanes(); + + scene->_object19.postInit(); + scene->_object19.setVisage(7700); + scene->_object19.setStrip(6); + scene->_object19.setPosition(Common::Point(140, 192), 0); + + _globals->_sceneItems.push_front(&scene->_object10); + _globals->_sceneItems.push_front(&scene->_object8); + _globals->_sceneItems.push_front(&scene->_object9); + _globals->_events.setCursor(CURSOR_WALK); + _globals->_player._canWalk = false; + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene7700::Object9::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case CURSOR_LOOK: + SceneItem::display(7700, 49, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + SceneItem::display(7701, 42, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_TALK: + SceneItem::display(7702, 4, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case OBJECT_KEY: + if (_frame == 1) { + if (!_globals->getFlag(80)) { + scene->_object10.postInit(); + scene->_object10.setVisage(7701); + scene->_object10.setStrip(4); + scene->_object10.setPosition(Common::Point(159, 136)); + _globals->_sceneItems.push_front(&scene->_object10); + scene->_object10.setPriority2(240); + } + scene->_soundHandler.startSound(262, 0, 127); + scene->_object14.animate(ANIM_MODE_5, 0); + } + _globals->_events.setCursor(CURSOR_WALK); + break; + default: + SceneHotspot::doAction(action); + } +} + +void Scene7700::Object10::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display(7700, 50, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + _globals->setFlag(80); + scene->_sceneItem10.remove(); + scene->_gfxButton._bounds.expandPanes(); + scene->_object14.remove(); + scene->_object9.remove(); + remove(); + } else { + SceneHotspot::doAction(action); + } +} + +void Scene7700::Object11::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + switch (action) { + case OBJECT_SCANNER: + if (_frame != 1) + SceneItem::display(7701, 44, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneItem::doAction(action); + break; + case CURSOR_LOOK: + if (_frame != 1) + SceneItem::display(7700, 9, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + else + SceneItem::display(7700, 52, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case CURSOR_USE: + if (_frame != 1) { + SceneItem::display(7701, 8, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else { + _globals->setFlag(49); + _globals->_player.disableControl(); + scene->_sceneMode = 7706; + scene->setAction(&scene->_sequenceManager, scene, 7706, &_globals->_player, this, NULL); + } + break; + case OBJECT_EMPTY_JAR: + _globals->_inventory._emptyJar._sceneNumber = 0; + _globals->_inventory._jar._sceneNumber = 1; + _globals->_player.disableControl(); + scene->_sceneMode = 7710; + scene->setAction(&scene->_sequenceManager, scene, 7710, &_globals->_player, NULL); + break; + default: + SceneHotspot::doAction(action); + } +} + +void Scene7700::Object12::doAction(int action) { + Scene7700 *scene = (Scene7700 *)_globals->_sceneManager._scene; + + if (action == CURSOR_LOOK) { + SceneItem::display(7700, 15, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + } else if (action == CURSOR_USE) { + if (_globals->getFlag(78)) { + scene->_sceneMode = 7713; + scene->setAction(&scene->_sequenceManager, scene, 7713, &_globals->_player, NULL); + } else { + scene->_sceneMode = 7712; + scene->setAction(&scene->_sequenceManager, scene, 7715, NULL); + } + } else { + SceneHotspot::doAction(action); + } +} + +void Scene7700::signal() { + switch (_sceneMode) { + case 7701: + _globals->_player.setPriority2(-1); + _globals->_player.setStrip2(-1); + if (_globals->getFlag(78)) { + _globals->_player.enableControl(); + } else { + _sceneMode = 7711; + setAction(&_sequenceManager, this, 7711, 0); + } + break; + case 7702: + _soundHandler.proc1(0); + _globals->_sceneManager.changeScene(7600); + break; + case 7703: + case 7706: + case 7707: + case 7711: + case 7712: + _globals->_player.enableControl(); + break; + case 7704: + _globals->_soundHandler.startSound(256, 0, 127); + _prof.setStrip2(4); + _prof.setFrame2(1); + _prof.setPosition(Common::Point(159, 87), 0); + _globals->_player.enableControl(); + break; + case 7705: + case 7708: + _globals->_inventory._key._sceneNumber = 1; + _globals->_player.enableControl(); + break; + case 7709: + _globals->_events.setCursor(CURSOR_USE); + break; + case 7710: + _globals->_player.enableControl(); + SceneItem::display(7700, 62, SET_WIDTH, 200, SET_EXT_BGCOLOUR, 7, LIST_END); + break; + case 7713: + _emptyJar.remove(); + _globals->_inventory._emptyJar._sceneNumber = 1; + break; + default: + break; + } +} + +void Scene7700::process(Event &event) { + Scene::process(event); + + if (contains<SceneItem *>(_globals->_sceneItems, &_sceneItem10)) { + if (_gfxButton.process(event)) { + _sceneItem10.remove(); + _sceneHotspot15.remove(); + _sceneHotspot9.remove(); + if (_globals->_sceneObjects->contains(&_object10)) + _object10.remove(); + if (_globals->_sceneObjects->contains(&_object14)) + _object14.remove(); + _object19.remove(); + _gfxButton._bounds.expandPanes(); + _globals->_player._canWalk = true; + } + } + if ((event.eventType == EVENT_KEYPRESS) && (event.kbd.keycode == Common::KEYCODE_p)) { + event.handled = true; + if (!_globals->_sceneObjects->contains(&_easterEgg1)) { + _easterEgg1.postInit(); + _easterEgg1.setVisage(7708); + _easterEgg1.setPosition(Common::Point(163, 50), 0); + _easterEgg1.setPriority2(1); + _easterEgg1.animate(ANIM_MODE_2, 0); + _easterEgg1.setAction(&_action6); + } + } +} + +void Scene7700::dispatch() { + if ((_globals->_sceneRegions.indexOf(_globals->_player._position) == 6) || (_globals->_player._position.x < 10)) + _globals->_player.changeZoom(100 - ((_globals->_player._position.y - 68) / 2)); + else + _globals->_player.changeZoom(-1); + + if ((_action == 0) && (_globals->_sceneRegions.indexOf(_globals->_player._position) == 30)) { + _globals->_player.disableControl(); + _sceneMode = 7702; + setAction(&_sequenceManager, this, 7702, &_globals->_player, 0); + } + Scene::dispatch(); +} + +void Scene7700::postInit(SceneObjectList *OwnerList) { + loadScene(7700); + Scene::postInit(); + setZoomPercents(100, 80, 200, 100); + _globals->setFlag(53); + _field97B = 0; + _field979 = 0; + _field977 = 0; + + _stripManager.addSpeaker(&_speakerEText); + _stripManager.addSpeaker(&_speakerQText); + _speakerQText._npc = &_globals->_player; + _speakerEText._npc = &_prof; + + _globals->_player.postInit(); + _globals->_player.setVisage(4201); + _globals->_player.animate(ANIM_MODE_1, 0); + SceneObjectWrapper *wrapper = new SceneObjectWrapper(); + _globals->_player.setObjectWrapper(wrapper); + _globals->_player.setPosition(Common::Point(-19, 68), 0); + _globals->_player.setStrip2(7); + _globals->_player.setPriority2(95); + _globals->_player.changeZoom(80); + _globals->_player._moveDiff.x = 6; + _globals->_player._moveDiff.y = 3; + _globals->_player.disableControl(); + + _prof.postInit(); + _prof.setVisage(7706); + + if (_globals->getFlag(78)) { + _prof.setStrip2(4); + _prof.setPriority2(80); + _prof.setPosition(Common::Point(159, 87), 0); + } else { + _prof.setPosition(Common::Point(203, 87), 0); + _prof.setStrip2(2); + _prof._numFrames = 6; + _prof.setAction(&_action2); + } + + _cloud.postInit(); + _cloud.setVisage(7700); + _cloud.setStrip2(5); + _cloud.setPriority2(1); + _cloud.setPosition(Common::Point(133, 160), 0); + _cloud._moveDiff.x = 1; + _cloud._field7A = 7; + _cloud.setAction(&_action5); + + _object1.postInit(); + _object1.setVisage(7700); + _object1.setPosition(Common::Point(184, 61), 0); + _object1._lookLineNum = 18; + _object1._defltLineNum = 16; + + _object2.postInit(); + _object2.setVisage(7700); + _object2.setPosition(Common::Point(184, 70), 0); + _object2.setPriority2(60); + _object2._lookLineNum = 19; + _object2._defltLineNum = 17; + + _object3.postInit(); + _object3.setVisage(7703); + _object3.setPosition(Common::Point(288, 36), 0); + _object3.setStrip(2); + + _object4.postInit(); + _object4.setVisage(7700); + _object4.setPosition(Common::Point(268, 59), 0); + _object4.setStrip(2); + _object4._lookLineNum = 37; + _object4._defltLineNum = 35; + + _object5.postInit(); + _object5.setVisage(7700); + _object5.setPosition(Common::Point(268, 67), 0); + _object5.setPriority2(58); + _object5.setStrip2(3); + _object5._lookLineNum = 38; + _object5._defltLineNum = 36; + + _object6.postInit(); + _object6.setVisage(7700); + _object6.setPosition(Common::Point(268, 75), 0); + _object6.setPriority2(57); + _object6.setStrip2(4); + _object6._lookLineNum = 40; + _object6._defltLineNum = 43; + + _object8.postInit(); + _object8.setVisage(7703); + _object8.setPosition(Common::Point(203, 91), 0); + _object8.setStrip2(4); + _object8.setPriority2(86); + + _sceneHotspot8.setBounds(82, 141, 161, 92); + _sceneHotspot9.setBounds(82, 187, 161, 141); + + _cork.postInit(); + _cork.setVisage(7703); + _cork.setPosition(Common::Point(32, 128), 0); + + if (_globals->getFlag(49)) + _cork.setFrame(_cork.getFrameCount()); + + if (_globals->_inventory._emptyJar._sceneNumber == 7700) { + _emptyJar.postInit(); + _emptyJar.setVisage(7700); + _emptyJar.setStrip(8); + _emptyJar.setPosition(Common::Point(189, 48), 0); + _globals->_sceneItems.addItems(&_emptyJar, NULL); + } + _sceneHotspot1._sceneRegionId = 28; + _sceneHotspot2._sceneRegionId = 6; + _sceneHotspot3._sceneRegionId = 10; + _sceneHotspot4._sceneRegionId = 11; + _sceneHotspot5._sceneRegionId = 9; + _sceneHotspot6._sceneRegionId = 7; + + _sceneItem7.setBounds(0, 320, 200, 0); + _sceneItem10.setBounds(0, 320, 200, 0); + + _sceneHotspot11._sceneRegionId = 57; + _sceneHotspot11._useLineNum = 0; + _sceneHotspot11._lookLineNum = 0; + _sceneHotspot12._sceneRegionId = 2; + _sceneHotspot12._useLineNum = 2; + _sceneHotspot12._lookLineNum = 2; + _sceneHotspot13._sceneRegionId = 12; + _sceneHotspot13._useLineNum = 3; + _sceneHotspot13._lookLineNum = 3; + _sceneHotspot14._sceneRegionId = 18; + _sceneHotspot14._useLineNum = 4; + _sceneHotspot14._lookLineNum = 5; + _sceneHotspot15.setBounds(0, 55, 50, 8); + _sceneHotspot15._useLineNum = 6; + _sceneHotspot15._lookLineNum = 7; + _sceneHotspot16.setBounds(0, 130, 34, 103); + _sceneHotspot16._useLineNum = 8; + _sceneHotspot16._lookLineNum = 9; + _sceneHotspot17.setBounds(41, 180, 46, 170); + _sceneHotspot17._useLineNum = 11; + _sceneHotspot17._lookLineNum = 13; + _sceneHotspot18.setBounds(38, 187, 46, 180); + _sceneHotspot18._useLineNum = 12; + _sceneHotspot18._lookLineNum = 14; + _sceneHotspot19._sceneRegionId = 3; + _sceneHotspot19._useLineNum = 14; + _sceneHotspot19._lookLineNum = 16; + _sceneHotspot20._sceneRegionId = 14; + _sceneHotspot20._useLineNum = 15; + _sceneHotspot20._lookLineNum = 17; + _sceneHotspot21.setBounds(9, 215, 26, 210); + _sceneHotspot21._useLineNum = 18; + _sceneHotspot21._lookLineNum = 20; + _sceneHotspot22.setBounds(10, 221, 26, 215); + _sceneHotspot22._useLineNum = 19; + _sceneHotspot22._lookLineNum = 21; + _sceneHotspot23.setBounds(6, 230, 26, 225); + _sceneHotspot23._useLineNum = 20; + _sceneHotspot23._lookLineNum = 22; + _sceneHotspot24._sceneRegionId = 13; + _sceneHotspot24._useLineNum = 21; + _sceneHotspot24._lookLineNum = 23; + _sceneHotspot25._sceneRegionId = 21; + _sceneHotspot25._useLineNum = 22; + _sceneHotspot25._lookLineNum = 24; + _sceneHotspot26._sceneRegionId = 19; + _sceneHotspot26._useLineNum = 23; + _sceneHotspot26._lookLineNum = 25; + _sceneHotspot27._sceneRegionId = 27; + _sceneHotspot27._useLineNum = 24; + _sceneHotspot27._lookLineNum = 26; + _sceneHotspot28._sceneRegionId = 15; + _sceneHotspot28._useLineNum = 25; + _sceneHotspot28._lookLineNum = 27; + _sceneHotspot29._sceneRegionId = 26; + _sceneHotspot29._useLineNum = 27; + _sceneHotspot29._lookLineNum = 29; + _sceneHotspot30.setBounds(0, 317, 34, 310); + _sceneHotspot30._useLineNum = 28; + _sceneHotspot30._lookLineNum = 30; + _sceneHotspot31._sceneRegionId = 17; + _sceneHotspot31._useLineNum = 29; + _sceneHotspot31._lookLineNum = 31; + _sceneHotspot32._sceneRegionId = 25; + _sceneHotspot32._useLineNum = 30; + _sceneHotspot32._lookLineNum = 32; + _sceneHotspot33._sceneRegionId = 5; + _sceneHotspot33._useLineNum = 31; + _sceneHotspot33._lookLineNum = 33; + _sceneHotspot34.setBounds(42, 292, 48, 281); + _sceneHotspot34._useLineNum = 32; + _sceneHotspot34._lookLineNum = 35; + _sceneHotspot35._sceneRegionId = 24; + _sceneHotspot35._useLineNum = 38; + _sceneHotspot35._lookLineNum = 41; + _sceneHotspot36._sceneRegionId = 1; + _sceneHotspot36._useLineNum = 39; + _sceneHotspot36._lookLineNum = 42; + + _globals->_sceneItems.addItems(&_prof, &_sceneHotspot35, &_object8, &_sceneHotspot34, &_sceneHotspot33, &_sceneHotspot32, NULL); + _globals->_sceneItems.addItems(&_sceneHotspot31, &_sceneHotspot30, &_sceneHotspot29, &_sceneHotspot5, &_sceneHotspot28, &_sceneHotspot27, NULL); + _globals->_sceneItems.addItems(&_sceneHotspot26, &_sceneHotspot25, &_sceneHotspot24, &_sceneHotspot23, &_sceneHotspot22, &_sceneHotspot21, NULL); + _globals->_sceneItems.addItems(&_sceneHotspot20, &_sceneHotspot19, &_sceneHotspot18, &_sceneHotspot17, &_sceneHotspot4, &_sceneHotspot3, NULL); + _globals->_sceneItems.addItems(&_sceneHotspot16, &_sceneHotspot15, &_sceneHotspot2, &_sceneHotspot14, &_cork, &_sceneHotspot1, NULL); + _globals->_sceneItems.addItems(&_sceneHotspot13, &_sceneHotspot12, &_sceneHotspot11, &_object2, &_object1, &_object3, NULL); + _globals->_sceneItems.addItems(&_object6, &_object5, &_object4, &_sceneHotspot6, &_sceneHotspot36, &_sceneItem7, NULL); + + _sceneMode = 7701; + setAction(&_sequenceManager, this, 7701, &_globals->_player, 0); + _soundHandler.startSound(256, 0, 127); +} + +Scene7700::Scene7700() { + _object1._state = 0; + _object2._state = 0; + _object4._state = 0; + _object5._state = 0; + _object6._state = 0; + _prof._state = 0; +} + +} // End of namespace tSage diff --git a/engines/tsage/ringworld_scenes8.h b/engines/tsage/ringworld_scenes8.h new file mode 100644 index 0000000000..0c39920614 --- /dev/null +++ b/engines/tsage/ringworld_scenes8.h @@ -0,0 +1,495 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_RINGWORLD_SCENES8_H +#define TSAGE_RINGWORLD_SCENES8_H + +#include "common/scummsys.h" +#include "tsage/ringworld_logic.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace tSage { + +class NamedHotspotMult : public SceneHotspot { +public: + int _useLineNum, _lookLineNum; + NamedHotspotMult() : SceneHotspot() {} + + virtual Common::String getClassName() { return "NamedHotspotMult"; } +}; + +class SceneObject7700 : public SceneObjectExt { +public: + int _lookLineNum, _defltLineNum; + + virtual void synchronise(Serialiser &s) { + SceneObject::synchronise(s); + s.syncAsSint16LE(_lookLineNum); + s.syncAsSint16LE(_defltLineNum); + } + virtual Common::String getClassName() { return "SceneObject7700"; } +}; + +class Scene7000 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void dispatch(); + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + + /* Objects */ + class Object1 : public SceneObject { + public: + virtual void doAction(int action); + }; + + /* Items */ + class SceneItem1 : public SceneItem { + public: + virtual void doAction(int action); + }; + +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + SpeakerSKText _speakerSKText; + SpeakerSKL _speakerSKL; + SpeakerQL _speakerQL; + SpeakerQR _speakerQR; + SpeakerQText _speakerQText; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneObject _object7; + SceneObject _object8; + SceneObject _object9; + SceneObject _object10; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + SceneItem1 _sceneItem1; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void dispatch(); +}; + +class Scene7100 : public Scene { + /* Actions */ + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + class Action7 : public Action { + public: + virtual void signal(); + }; + class Action8 : public Action { + public: + virtual void signal(); + }; + class Action9 : public Action { + public: + virtual void signal(); + }; + class Action10 : public Action { + public: + virtual void signal(); + }; + class Action11 : public Action { + public: + virtual void signal(); + }; + +public: + SoundHandler _soundHandler1; + SoundHandler _soundHandler2; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneObject _object7; + SceneObject _object8; + SceneObject _object9; + SceneObject _object10; + SceneObject _object11; + SceneObject _object12; + SceneObject _object13; + SceneObject _object14; + SceneObject _object15; + SceneObject _object16; + SceneObject _object17; + SceneObject _object18; + SceneObject _object19; + SceneObject _object20; + SceneObject _object21; + SceneObject _object22; + SceneObject _object23; + SceneObject _object24; + SceneObject _object25; + Action _action1; + Action _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + Action7 _action7; + Action8 _action8; + Action9 _action9; + Action10 _action10; + Action11 _action11; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene7200 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + +public: + Action1 _action1; + Action2 _action2; + SceneObject _swimmer; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneObject _object7; + SceneObject _object8; + SceneObject _object9; + SoundHandler _soundHandler; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene7300 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + +public: + SpeakerPOR _speakerPOR; + SpeakerPOText _speakerPOText; + SpeakerSKText _speakerSKText; + SpeakerQU _speakerQU; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SceneObject _object7; + SceneObject _object8; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void dispatch(); +}; + +class Scene7600 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + +public: + Action1 _action1; + Action2 _action2; + SceneObject _object1; + SceneObject _object2; + SceneObject _object3; + SceneObject _object4; + SceneObject _object5; + SceneObject _object6; + SoundHandler _soundHandler1; + SoundHandler _soundHandler2; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene7700 : public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; + class Action2 : public Action { + public: + virtual void signal(); + }; + class Action3 : public Action { + public: + virtual void signal(); + }; + class Action4 : public Action { + public: + virtual void signal(); + }; + class Action5 : public Action { + public: + virtual void signal(); + }; + class Action6 : public Action { + public: + virtual void signal(); + }; + + class Object1 : public SceneObject7700 { + public: + virtual void signal(); + virtual void doAction(int action); + }; + class Object3 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object7 : public SceneObjectExt { + public: + virtual void doAction(int action); + }; + class Object8 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object9 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object10 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object11 : public SceneObject { + public: + virtual void doAction(int action); + }; + class Object12 : public SceneObject { + public: + virtual void doAction(int action); + }; + + /* Items */ + class SceneHotspot1 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot2 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot3 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot4 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot5 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot6 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneItem7 : public SceneItem { + public: + virtual void doAction(int action); + }; + class SceneHotspot8 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneHotspot9 : public SceneHotspot { + public: + virtual void doAction(int action); + }; + class SceneItem10 : public SceneItem { + public: + virtual void doAction(int action); + }; + class SceneHotspot11 : public NamedHotspotMult { + public: + virtual void doAction(int action); + }; +public: + SoundHandler _soundHandler; + SequenceManager _sequenceManager; + GfxButton _gfxButton; + SpeakerEText _speakerEText; + SpeakerQText _speakerQText; + Object1 _object1; + Object1 _object2; + Object3 _object3; + Object1 _object4; + Object1 _object5; + Object1 _object6; + Object7 _prof; + Object8 _object8; + Object9 _object9; + Object10 _object10; + Object11 _cork; + Object12 _emptyJar; + SceneObject _object13; + SceneObject _object14; + SceneObject _object15; + SceneObject _cloud; + SceneObject _easterEgg1; + SceneObject _easterEgg2; + SceneObject _object19; + Action1 _action1; + Action2 _action2; + Action3 _action3; + Action4 _action4; + Action5 _action5; + Action6 _action6; + SceneHotspot1 _sceneHotspot1; + SceneHotspot2 _sceneHotspot2; + SceneHotspot3 _sceneHotspot3; + SceneHotspot4 _sceneHotspot4; + SceneHotspot5 _sceneHotspot5; + SceneHotspot6 _sceneHotspot6; + SceneItem7 _sceneItem7; + SceneHotspot8 _sceneHotspot8; + SceneHotspot9 _sceneHotspot9; + SceneItem10 _sceneItem10; + SceneHotspot11 _sceneHotspot11; + SceneHotspot11 _sceneHotspot12; + SceneHotspot11 _sceneHotspot13; + SceneHotspot11 _sceneHotspot14; + SceneHotspot11 _sceneHotspot15; + SceneHotspot11 _sceneHotspot16; + SceneHotspot11 _sceneHotspot17; + SceneHotspot11 _sceneHotspot18; + SceneHotspot11 _sceneHotspot19; + SceneHotspot11 _sceneHotspot20; + SceneHotspot11 _sceneHotspot21; + SceneHotspot11 _sceneHotspot22; + SceneHotspot11 _sceneHotspot23; + SceneHotspot11 _sceneHotspot24; + SceneHotspot11 _sceneHotspot25; + SceneHotspot11 _sceneHotspot26; + SceneHotspot11 _sceneHotspot27; + SceneHotspot11 _sceneHotspot28; + SceneHotspot11 _sceneHotspot29; + SceneHotspot11 _sceneHotspot30; + SceneHotspot11 _sceneHotspot31; + SceneHotspot11 _sceneHotspot32; + SceneHotspot11 _sceneHotspot33; + SceneHotspot11 _sceneHotspot34; + SceneHotspot11 _sceneHotspot35; + SceneHotspot11 _sceneHotspot36; + int _field977, _field979, _field97B; + + Scene7700(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp new file mode 100644 index 0000000000..7983e2a34c --- /dev/null +++ b/engines/tsage/saveload.cpp @@ -0,0 +1,387 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/savefile.h" +#include "graphics/scaler.h" +#include "graphics/thumbnail.h" +#include "tsage/globals.h" +#include "tsage/saveload.h" +#include "tsage/tsage.h" + +namespace tSage { + +Saver *_saver; + +SavedObject::SavedObject() { + _saver->addObject(this); +} + +SavedObject::~SavedObject() { + _saver->removeObject(this); +} + +/*--------------------------------------------------------------------------*/ + +Saver::Saver() { + _macroSaveFlag = false; + _macroRestoreFlag = false; +} + +Saver::~Saver() { + // Internal validation that no saved object is still present + int totalLost = 0; + for (SynchronisedList<SavedObject *>::iterator i = _saver->_objList.begin(); i != _saver->_objList.end(); ++i) { + SavedObject *so = *i; + if (so) + ++totalLost; + } + + if (totalLost) + warning("Saved object not destroyed"); +} + +/*--------------------------------------------------------------------------*/ + +void Serialiser::syncPointer(SavedObject **ptr, Common::Serializer::Version minVersion, + Common::Serializer::Version maxVersion) { + int idx; + assert(ptr); + + if (isSaving()) { + // Get the object index for the given pointer and write it out + if (!*ptr) { + idx = 0; + } else { + idx = _saver->blockIndexOf(*ptr); + assert(idx > 0); + } + syncAsUint32LE(idx); + } else { + // Load in the object index and add it into the unresolved pointer list + syncAsUint32LE(idx); + *ptr = NULL; + if (idx > 0) + // For non-zero (null) pointers, create a record for later resolving it to an address + _saver->addSavedObjectPtr(ptr, idx); + } +} + +void Serialiser::validate(const Common::String &s, Common::Serializer::Version minVersion, + Common::Serializer::Version maxVersion) { + Common::String tempStr = s; + syncString(tempStr, minVersion, maxVersion); + + if (isLoading() && (tempStr != s)) + error("Savegame is corrupt"); +} + +void Serialiser::validate(int v, Common::Serializer::Version minVersion, + Common::Serializer::Version maxVersion) { + int tempVal = v; + syncAsUint32LE(tempVal, minVersion, maxVersion); + if (isLoading() && (tempVal != v)) + error("Savegame is corrupt"); +} + +/*--------------------------------------------------------------------------*/ + +Common::Error Saver::save(int slot, const Common::String &saveName) { + assert(!getMacroRestoreFlag()); + + // Signal any objects registered for notification + _saveNotifiers.notify(false); + + // Set fields + _macroSaveFlag = true; + _saveSlot = slot; + + // Set up the serialiser + Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(_vm->generateSaveName(slot)); + Serialiser serialiser(NULL, saveFile); + + // Write out the savegame header + tSageSavegameHeader header; + header.saveName = saveName; + header.version = TSAGE_SAVEGAME_VERSION; + writeSavegameHeader(saveFile, header); + + // Save out objects that need to come at the start of the savegame + for (SynchronisedList<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { + (*i)->listenerSynchronise(serialiser); + } + + // Save each registered SaveObject descendant object into the savegame file + for (SynchronisedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) { + serialiser.validate((*i)->getClassName()); + (*i)->synchronise(serialiser); + } + + // Save file complete + saveFile->writeString("END"); + saveFile->finalize(); + delete saveFile; + + // Final post-save notification + _macroSaveFlag = false; + _saveNotifiers.notify(true); + + return Common::kNoError; +} + +Common::Error Saver::restore(int slot) { + assert(!getMacroSaveFlag()); + + // Signal any objects registered for notification + _loadNotifiers.notify(false); + + // Set fields + _macroSaveFlag = true; + _saveSlot = slot; + _unresolvedPtrs.clear(); + + // Set up the serialiser + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(_vm->generateSaveName(slot)); + Serialiser serialiser(saveFile, NULL); + + // Read in the savegame header + tSageSavegameHeader header; + readSavegameHeader(saveFile, header); + delete header.thumbnail; + + // Load in data for objects that need to come at the start of the savegame + for (Common::List<SaveListener *>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) { + (*i)->listenerSynchronise(serialiser); + } + + // Loop through each registered object to load in the data + for (SynchronisedList<SavedObject *>::iterator i = _objList.begin(); i != _objList.end(); ++i) { + serialiser.validate((*i)->getClassName()); + (*i)->synchronise(serialiser); + } + + // Loop through the remaining data of the file, instantiating new objects. + // Note: I don't store pointers to instantiated objects here, because it's not necessary - the mere act + // of instantiating a saved object registers it with the saver, and will then be resolved to whatever + // object originally had a pointer to it as part of the post-processing step + Common::String className; + serialiser.syncString(className); + while (className != "END") { + SavedObject *savedObject; + if (!_factoryPtr || ((savedObject = _factoryPtr(className)) == NULL)) + error("Unknown class name '%s' encountered trying to restore savegame", className.c_str()); + + // Populate the contents of the object + savedObject->synchronise(serialiser); + + // Move to next object + serialiser.syncString(className); + } + + // Post-process any unresolved pointers to get the correct pointer + resolveLoadPointers(); + + delete saveFile; + + // Final post-restore notifications + _macroRestoreFlag = false; + _loadNotifiers.notify(false); + + return Common::kNoError; +} + +const char *SAVEGAME_STR = "SCUMMVM_TSAGE"; +#define SAVEGAME_STR_SIZE 13 + +bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header) { + char saveIdentBuffer[SAVEGAME_STR_SIZE + 1]; + header.thumbnail = NULL; + + // 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 != TSAGE_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 = new Graphics::Surface(); + if (!Graphics::loadThumbnail(*in, *header.thumbnail)) { + delete header.thumbnail; + header.thumbnail = NULL; + return false; + } + + // Read in save date/time + header.saveYear = in->readSint16LE(); + header.saveMonth = in->readSint16LE(); + header.saveDay = in->readSint16LE(); + header.saveHour = in->readSint16LE(); + header.saveMinutes = in->readSint16LE(); + header.totalFrames = in->readUint32LE(); + + return true; +} + +void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header) { + // Write out a savegame header + out->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1); + + out->writeByte(TSAGE_SAVEGAME_VERSION); + + // Write savegame name + out->write(header.saveName.c_str(), header.saveName.size() + 1); + + // Get the active palette + uint32 workPal[256]; + uint8 thumbPalette[256 * 3]; + const byte *srcP = (const byte *)&workPal[0]; + byte *destP = &thumbPalette[0]; + g_system->getPaletteManager()->grabPalette((byte *)workPal, 0, 256); + for (int idx = 0; idx < 256; ++idx, ++srcP) { + *destP++ = *srcP++; + *destP++ = *srcP++; + *destP++ = *srcP++; + } + + // Create a thumbnail and save it + Graphics::Surface *thumb = new Graphics::Surface(); + Graphics::Surface s = _globals->_screenSurface.lockSurface(); + ::createThumbnail(thumb, (const byte *)s.pixels, SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette); + Graphics::saveThumbnail(*out, *thumb); + _globals->_screenSurface.unlockSurface(); + 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(_globals->_events.getFrameNumber()); +} + +/** + * Adds a serialisable object that should be saved/restored before any other objects + */ +void Saver::addListener(SaveListener *obj) { + _listeners.push_back(obj); +} + +/** + * Adds a listener to be notified before the saving starts + */ +void Saver::addSaveNotifier(SaveNotifierFn fn) { + _saveNotifiers.push_back(fn); +} + +/** + * Adds a listener to be notified before the saving starts + */ +void Saver::addLoadNotifier(SaveNotifierFn fn) { + _loadNotifiers.push_back(fn); +} + +/** + * Registers a SavedObject descendant object for being saved in savegame files + */ +void Saver::addObject(SavedObject *obj) { + _objList.push_back(obj); +} + +/** + * Removes a SavedObject descendant object from the save object list + */ +void Saver::removeObject(SavedObject *obj) { + _objList.remove(obj); +} + +/** + * Returns true if any savegames exist + */ +bool Saver::savegamesExist() const { + Common::String slot1Name = _vm->generateSaveName(1); + + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slot1Name); + bool result = saveFile != NULL; + delete saveFile; + return result; +} + +/** + * Returns the index of the saved block associated with the given saved object pointer + */ +int Saver::blockIndexOf(SavedObject *p) { + int objIndex = 1; + SynchronisedList<SavedObject *>::iterator iObj; + + for (iObj = _objList.begin(); iObj != _objList.end(); ++iObj, ++objIndex) { + SavedObject *iObjP = *iObj; + if (iObjP == p) + return objIndex; + } + + return 0; +} + +/** + * Returns the pointer associated with the specified object index + */ +void Saver::resolveLoadPointers() { + if (_unresolvedPtrs.size() == 0) + // Nothing to resolve + return; + + // Outer loop through the main object list + int objIndex = 1; + for (SynchronisedList<SavedObject *>::iterator iObj = _objList.begin(); iObj != _objList.end(); ++iObj, ++objIndex) { + Common::List<SavedObjectRef>::iterator iPtr; + + for (iPtr = _unresolvedPtrs.begin(); iPtr != _unresolvedPtrs.end(); ) { + SavedObjectRef &r = *iPtr; + if (r._objIndex == objIndex) { + // Found an unresolved pointer to this object + *r._savedObject = *iObj; + iPtr = _unresolvedPtrs.erase(iPtr); + } else { + ++iPtr; + } + } + } + + // At this point, all the unresolved pointers should have been resolved and removed + if (_unresolvedPtrs.size() > 0) + error("Could not resolve savegame block pointers"); +} + +} // End of namespace tSage diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h new file mode 100644 index 0000000000..83661b8f15 --- /dev/null +++ b/engines/tsage/saveload.h @@ -0,0 +1,215 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_SAVELOAD_H +#define TSAGE_SAVELOAD_H + +#include "common/scummsys.h" +#include "common/list.h" +#include "common/memstream.h" +#include "common/savefile.h" +#include "common/serializer.h" + +namespace tSage { + +typedef void (*SaveNotifierFn)(bool postFlag); + +#define TSAGE_SAVEGAME_VERSION 1 + +class SavedObject; + +struct tSageSavegameHeader { + uint8 version; + Common::String saveName; + Graphics::Surface *thumbnail; + int saveYear, saveMonth, saveDay; + int saveHour, saveMinutes; + int totalFrames; +}; + +/*--------------------------------------------------------------------------*/ + +#define SYNC_POINTER(x) s.syncPointer((SavedObject **)&x) +#define SYNC_ENUM(FIELD, TYPE) int v_##FIELD = (int)FIELD; s.syncAsUint16LE(v_##FIELD); \ + if (s.isLoading()) FIELD = (TYPE)v_##FIELD; + +/** + * Derived serialiser class with extra synchronisation types + */ +class Serialiser : public Common::Serializer { +public: + Serialiser(Common::SeekableReadStream *in, Common::WriteStream *out) : Common::Serializer(in, out) {} + + void syncPointer(SavedObject **ptr, Common::Serializer::Version minVersion = 0, + Common::Serializer::Version maxVersion = kLastVersion); + void validate(const Common::String &s, Common::Serializer::Version minVersion = 0, + Common::Serializer::Version maxVersion = kLastVersion); + void validate(int v, Common::Serializer::Version minVersion = 0, + Common::Serializer::Version maxVersion = kLastVersion); +}; + +/*--------------------------------------------------------------------------*/ + +class Serialisable { +public: + virtual ~Serialisable() {} + virtual void synchronise(Serialiser &s) = 0; +}; + +class SaveListener { +public: + virtual ~SaveListener() {} + virtual void listenerSynchronise(Serialiser &s) = 0; +}; + +/*--------------------------------------------------------------------------*/ + +class SavedObject : public Serialisable { +public: + SavedObject(); + virtual ~SavedObject(); + + virtual Common::String getClassName() { return "SavedObject"; } + virtual void synchronise(Serialiser &s) {} + + static SavedObject *createInstance(const Common::String &className); +}; + +/*--------------------------------------------------------------------------*/ + +/** + * Derived list class with extra functionality + */ +template<typename T> +class SynchronisedList : public Common::List<T> { +public: + void synchronise(Serialiser &s) { + int entryCount; + + if (s.isLoading()) { + this->clear(); + s.syncAsUint32LE(entryCount); + + for (int idx = 0; idx < entryCount; ++idx) { + this->push_back(static_cast<T>((T)NULL)); + T &obj = Common::List<T>::back(); + s.syncPointer((SavedObject **)&obj); + } + } else { + // Get the list size + entryCount = this->size(); + + // Write out list + s.syncAsUint32LE(entryCount); + for (typename Common::List<T>::iterator i = this->begin(); i != this->end(); ++i) { + s.syncPointer((SavedObject **)&*i); + } + } + } +}; + +/** + * Search whether an element is contained in a list. + * + * @param l List to search. + * @param v Element to search for. + * @return True in case the element is contained, false otherwise. + */ +template<typename T> +inline bool contains(const Common::List<T> &l, const T &v) { + return (Common::find(l.begin(), l.end(), v) != l.end()); +} + +/** + * Derived list class for holding function pointers + */ +template<typename T> +class FunctionList : public Common::List<void (*)(T)> { +public: + void notify(T v) { + for (typename Common::List<void (*)(T)>::iterator i = this->begin(); i != this->end(); ++i) { + (*i)(v); + } + } +}; + +/*--------------------------------------------------------------------------*/ + +class SavedObjectRef { +public: + SavedObject **_savedObject; + int _objIndex; + + SavedObjectRef() : _savedObject(NULL), _objIndex(-1) {} + SavedObjectRef(SavedObject **so, int objIndex) : _savedObject(so), _objIndex(objIndex) {} +}; + +typedef SavedObject *(*SavedObjectFactory)(const Common::String &className); + +class Saver { +private: + SynchronisedList<SavedObject *> _objList; + FunctionList<bool> _saveNotifiers; + FunctionList<bool> _loadNotifiers; + Common::List<SaveListener *> _listeners; + + Common::List<SavedObjectRef> _unresolvedPtrs; + SavedObjectFactory _factoryPtr; + + bool _macroSaveFlag; + bool _macroRestoreFlag; + int _saveSlot; + + void resolveLoadPointers(); +public: + Saver(); + ~Saver(); + + Common::Error save(int slot, const Common::String &saveName); + Common::Error restore(int slot); + static bool readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header); + static void writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header); + + void addListener(SaveListener *obj); + void addSaveNotifier(SaveNotifierFn fn); + void addLoadNotifier(SaveNotifierFn fn); + void addObject(SavedObject *obj); + void removeObject(SavedObject *obj); + void addFactory(SavedObjectFactory fn) { _factoryPtr = fn; } + void addSavedObjectPtr(SavedObject **ptr, int objIndex) { + _unresolvedPtrs.push_back(SavedObjectRef(ptr, objIndex)); + } + + bool savegamesExist() const; + bool getMacroSaveFlag() const { return _macroSaveFlag; } + bool getMacroRestoreFlag() const { return _macroRestoreFlag; } + int blockIndexOf(SavedObject *p); +}; + +extern Saver *_saver; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp new file mode 100644 index 0000000000..68320066d7 --- /dev/null +++ b/engines/tsage/scenes.cpp @@ -0,0 +1,471 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/scenes.h" +#include "tsage/globals.h" +#include "tsage/ringworld_logic.h" +#include "tsage/tsage.h" + +namespace tSage { + +SceneManager::SceneManager() { + _scene = NULL; + _hasPalette = false; + _sceneNumber = -1; + _nextSceneNumber = -1; + _previousScene = 0; + _fadeMode = FADEMODE_GRADUAL; + _scrollerRect = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _saver->addListener(this); +} + +SceneManager::~SceneManager() { + delete _scene; +} + +void SceneManager::setNewScene(int sceneNumber) { + _nextSceneNumber = sceneNumber; +} + +void SceneManager::checkScene() { + if (_nextSceneNumber != -1) { + sceneChange(); + _nextSceneNumber = -1; + } + + Common::for_each(_globals->_sceneListeners.begin(), _globals->_sceneListeners.end(), SceneHandler::dispatchObject); +} + +void SceneManager::sceneChange() { + // Handle removing the scene + if (_scene) + _scene->remove(); + + // Clear the scene objects + SynchronisedList<SceneObject *>::iterator io = _globals->_sceneObjects->begin(); + while (io != _globals->_sceneObjects->end()) { + SceneObject *sceneObj = *io; + ++io; + sceneObj->removeObject(); + } + + // Clear the secondary scene object list + io = _globals->_sceneManager._altSceneObjects.begin(); + while (io != _globals->_sceneManager._altSceneObjects.end()) { + SceneObject *sceneObj = *io; + ++io; + sceneObj->removeObject(); + } + + // Clear the hotspot list + SynchronisedList<SceneItem *>::iterator ii = _globals->_sceneItems.begin(); + while (ii != _globals->_sceneItems.end()) { + SceneItem *sceneItem = *ii; + ++ii; + sceneItem->remove(); + } + + // TODO: Clear _list_45BAA list + + // If there is an active scene, deactivate it + if (_scene) { + _previousScene = _sceneNumber; + + delete _scene; + _scene = NULL; + _sceneNumber = -1; + } + + // Set the next scene to be active + _sceneNumber = _nextSceneNumber; + + // TODO: Unknown check of word_45CD3 / call to saver method + + // Free any regions + disposeRegions(); + + // Instantiate and set the new scene + _scene = getNewScene(); + _scene->postInit(); +} + +Scene *SceneManager::getNewScene() { + return SceneFactory::createScene(_nextSceneNumber); +} + +void SceneManager::fadeInIfNecessary() { + if (_hasPalette) { + uint32 adjustData = 0; + for (int percent = 0; percent < 100; percent += 5) { + if (_globals->_sceneManager._fadeMode == FADEMODE_IMMEDIATE) + percent = 100; + + _globals->_scenePalette.fade((const byte *)&adjustData, false, percent); + g_system->updateScreen(); + g_system->delayMillis(10); + } + + _globals->_scenePalette.refresh(); + _hasPalette = false; + } +} + +void SceneManager::changeScene(int newSceneNumber) { + // Fade out the scene + ScenePalette scenePalette; + uint32 adjustData = 0; + _globals->_scenePalette.clearListeners(); + scenePalette.getPalette(); + + for (int percent = 100; percent >= 0; percent -= 5) { + scenePalette.fade((byte *)&adjustData, false, percent); + g_system->delayMillis(10); + } + + // Stop any objects that were animating + SynchronisedList<SceneObject *>::iterator i; + for (i = _globals->_sceneObjects->begin(); i != _globals->_sceneObjects->end(); ++i) { + SceneObject *sceneObj = *i; + Common::Point pt(0, 0); + sceneObj->addMover(NULL, &pt); + sceneObj->setObjectWrapper(NULL); + sceneObj->animate(ANIM_MODE_NONE, 0); + + sceneObj->_flags &= !OBJFLAG_PANES; + } + + // Blank out the screen + _globals->_screenSurface.fillRect(_globals->_screenSurface.getBounds(), 0); + + // Set the new scene to be loaded + setNewScene(newSceneNumber); +} + +void SceneManager::setup() { + _saver->addLoadNotifier(SceneManager::loadNotifier); + setBackSurface(); +} + +void SceneManager::setBackSurface() { + int size = _globals->_sceneManager._scene->_backgroundBounds.width() * + _globals->_sceneManager._scene->_backgroundBounds.height(); + + if (size > 96000) { + if (_globals->_sceneManager._scene->_backgroundBounds.width() <= SCREEN_WIDTH) { + // Standard size creation + _globals->_sceneManager._scene->_backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2); + _globals->_sceneManager._scrollerRect = Rect(0, 30, SCREEN_WIDTH, SCREEN_HEIGHT - 30); + } else { + // Wide screen needs extra space to allow for scrolling + _globals->_sceneManager._scene->_backSurface.create(SCREEN_WIDTH * 3 / 2, SCREEN_HEIGHT); + _globals->_sceneManager._scrollerRect = Rect(80, 0, SCREEN_WIDTH - 80, SCREEN_HEIGHT); + } + } else { + _globals->_sceneManager._scene->_backSurface.create( + _globals->_sceneManager._scene->_backgroundBounds.width(), + _globals->_sceneManager._scene->_backgroundBounds.height() + ); + _globals->_sceneManager._scrollerRect = Rect(80, 20, SCREEN_WIDTH - 80, SCREEN_HEIGHT - 20); + } +} + +void SceneManager::saveListener(int saveMode) { + warning("TODO: SceneManager::saveLIstener"); +} + +void SceneManager::loadNotifier(bool postFlag) { + if (postFlag) { + if (_globals->_sceneManager._scene->_activeScreenNumber != -1) + _globals->_sceneManager._scene->loadSceneData(_globals->_sceneManager._scene->_activeScreenNumber); + _globals->_sceneManager._hasPalette = true; + } +} + +void SceneManager::setBgOffset(const Common::Point &pt, int loadCount) { + _sceneBgOffset = pt; + _sceneLoadCount = loadCount; +} + +void SceneManager::listenerSynchronise(Serialiser &s) { + s.validate("SceneManager"); + _altSceneObjects.synchronise(s); + + s.syncAsSint32LE(_sceneNumber); + if (s.isLoading()) { + changeScene(_sceneNumber); + checkScene(); + } + + s.syncAsUint16LE(_globals->_sceneManager._scene->_activeScreenNumber); + _globals->_sceneManager._scrollerRect.synchronise(s); + SYNC_POINTER(_globals->_scrollFollower); + s.syncAsSint16LE(_loadMode); +} + +/*--------------------------------------------------------------------------*/ + +Scene::Scene() : _sceneBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), + _backgroundBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) { + _sceneMode = 0; + _oldSceneBounds = Rect(4000, 4000, 4100, 4100); +} + +Scene::~Scene() { +} + +void Scene::synchronise(Serialiser &s) { + s.syncAsSint32LE(_field12); + s.syncAsSint32LE(_sceneNumber); + s.syncAsSint32LE(_activeScreenNumber); + s.syncAsSint32LE(_sceneMode); + _backgroundBounds.synchronise(s); + _sceneBounds.synchronise(s); + _oldSceneBounds.synchronise(s); + s.syncAsSint16LE(_fieldA); + s.syncAsSint16LE(_fieldE); + + for (int i = 0; i < 256; ++i) + s.syncAsUint16LE(_enabledSections[i]); + for (int i = 0; i < 256; ++i) + s.syncAsSint16LE(_zoomPercents[i]); +} + +void Scene::postInit(SceneObjectList *OwnerList) { + _action = NULL; + _field12 = 0; + _sceneMode = 0; +} + +void Scene::process(Event &event) { + if (_action) + _action->process(event); +} + +void Scene::dispatch() { + if (_action) + _action->dispatch(); +} + +void Scene::loadScene(int sceneNum) { + _sceneNumber = sceneNum; + if (_globals->_scenePalette.loadPalette(sceneNum)) + _globals->_sceneManager._hasPalette = true; + + loadSceneData(sceneNum); +} + +void Scene::loadSceneData(int sceneNum) { + _globals->_sceneManager._scene->_activeScreenNumber = sceneNum; + + // Get the basic scene size + byte *data = _vm->_dataManager->getResource(RES_BITMAP, sceneNum, 9999); + _backgroundBounds = Rect(0, 0, READ_LE_UINT16(data), READ_LE_UINT16(data + 2)); + _globals->_sceneManager._scene->_sceneBounds.contain(_backgroundBounds); + DEALLOCATE(data); + + // Set up a surface for storing the scene background + SceneManager::setBackSurface(); + + // Load the data lists for the scene + _globals->_walkRegions.load(sceneNum); + + // Load the item regions of the scene + _globals->_sceneRegions.load(sceneNum); + + // Load the priority regions + _priorities.load(sceneNum); + + // Initialise the section enabled list + Common::set_to(&_enabledSections[0], &_enabledSections[16 * 16], 0xffff); + + _globals->_sceneOffset.x = (_sceneBounds.left / 160) * 160; + _globals->_sceneOffset.y = (_sceneBounds.top / 100) * 100; + _globals->_paneRefreshFlag[0] = 1; + _globals->_paneRefreshFlag[1] = 1; + _globals->_sceneManager._loadMode = 1; + _globals->_sceneManager._sceneLoadCount = 0; + _globals->_sceneManager._sceneBgOffset = Common::Point(0, 0); + + // Load the background for the scene + loadBackground(0, 0); +} + +void Scene::loadBackground(int xAmount, int yAmount) { + // Adjust the scene bounds by the passed scroll amounts + _sceneBounds.translate(xAmount, yAmount); + _sceneBounds.contain(_backgroundBounds); + _sceneBounds.left &= ~3; + _sceneBounds.right &= ~3; + _globals->_sceneOffset.x &= ~3; + + if ((_sceneBounds.top != _oldSceneBounds.top) || (_sceneBounds.left != _oldSceneBounds.left)) { + if (_globals->_sceneManager._loadMode == 0) { + _globals->_paneRefreshFlag[0] = 2; + _globals->_paneRefreshFlag[1] = 2; + _globals->_sceneManager._loadMode = 2; + } + _oldSceneBounds = _sceneBounds; + } + + _globals->_sceneOffset.x = (_sceneBounds.left / 160) * 160; + _globals->_sceneOffset.y = (_sceneBounds.top / 100) * 100; + + if ((_backgroundBounds.width() / 160) == 3) + _globals->_sceneOffset.x = 0; + if ((_backgroundBounds.height() / 100) == 3) + _globals->_sceneOffset.y = 0; + + if ((_globals->_sceneOffset.x != _globals->_prevSceneOffset.x) || + (_globals->_sceneOffset.y != _globals->_prevSceneOffset.y)) { + // Change has happend, so refresh background + _globals->_prevSceneOffset = _globals->_sceneOffset; + refreshBackground(xAmount, yAmount); + } +} + +void Scene::refreshBackground(int xAmount, int yAmount) { + if (_globals->_sceneManager._scene->_activeScreenNumber == -1) + return; + + // Set the quadrant ranges + int xHalfCount = MIN(_backSurface.getBounds().width() / 160, _backgroundBounds.width() / 160); + int yHalfCount = MIN(_backSurface.getBounds().height() / 100, _backgroundBounds.height() / 100); + int xHalfOffset = (_backgroundBounds.width() / 160) == 3 ? 0 : _sceneBounds.left / 160; + int yHalfOffset = (_backgroundBounds.height() / 100) == 3 ? 0 : _sceneBounds.top / 100; + + // Set the limits and increment amounts + int xInc = (xAmount < 0) ? -1 : 1; + int xSectionStart = (xAmount < 0) ? 15 : 0; + int xSectionEnd = (xAmount < 0) ? -1 : 16; + int yInc = (yAmount < 0) ? -1 : 1; + int ySectionStart = (yAmount < 0) ? 15 : 0; + int ySectionEnd = (yAmount < 0) ? -1 : 16; + bool changedFlag = false; + + for (int yp = ySectionStart; yp != ySectionEnd; yp += yInc) { + for (int xp = xSectionStart; xp != xSectionEnd; xp += xInc) { + if ((yp < yHalfOffset) || (yp >= (yHalfOffset + yHalfCount)) || + (xp < xHalfOffset) || (xp >= (xHalfOffset + xHalfCount))) { + // Flag section as enabled + _enabledSections[xp * 16 + yp] = 0xffff; + } else { + // Check if the section is already loaded + if ((_enabledSections[xp * 16 + yp] == 0xffff) || ((xAmount == 0) && (yAmount == 0))) { + // Chunk isn't loaded, so load it in + Graphics::Surface s = _backSurface.lockSurface(); + GfxSurface::loadScreenSection(s, xp - xHalfOffset, yp - yHalfOffset, xp, yp); + _backSurface.unlockSurface(); + changedFlag = true; + } else { + int yv = (_enabledSections[xp * 16 + yp] == ((xp - xHalfOffset) << 4)) ? 0 : 1; + if (yv | (yp - yHalfOffset)) { + // Copy an existing 160x100 screen section previously loaded + int xSectionDest = xp - xHalfOffset; + int ySectionDest = yp - yHalfOffset; + int xSectionSrc = _enabledSections[xp * 16 + yp] >> 4; + int ySectionSrc = _enabledSections[xp * 16 + yp] & 0xf; + + Rect srcBounds(xSectionSrc * 160, ySectionSrc * 100, + (xSectionSrc + 1) * 160, (ySectionSrc + 1) * 100); + Rect destBounds(xSectionDest * 160, ySectionDest * 100, + (xSectionDest + 1) * 160, (ySectionDest + 1) * 100); + + _backSurface.copyFrom(_backSurface, srcBounds, destBounds); + } + } + + _enabledSections[xp * 16 + yp] = + ((xp - xHalfOffset) << 4) | (yp - yHalfOffset); + } + } + } + + if (changedFlag) { + drawAltObjects(); + } +} + +void Scene::drawAltObjects() { + Common::Array<SceneObject *> objList; + + // Initial loop to set the priority for entries in the list + for (SynchronisedList<SceneObject *>::iterator i = _globals->_sceneManager._altSceneObjects.begin(); + i != _globals->_sceneManager._altSceneObjects.end(); ++i) { + SceneObject *obj = *i; + objList.push_back(obj); + + // Handle updating object priority + if (!(obj->_flags & OBJFLAG_FIXED_PRIORITY)) { + obj->_priority = MIN((int)obj->_position.y - 1, + (int)_globals->_sceneManager._scene->_backgroundBounds.bottom); + } + } + + // Sort the list by priority + _globals->_sceneManager._altSceneObjects.sortList(objList); + + // Drawing loop + for (uint objIndex = 0; objIndex < objList.size(); ++objIndex) { + SceneObject *obj = objList[objIndex]; + + obj->reposition(); + obj->draw(); + } +} + +void Scene::setZoomPercents(int yStart, int minPercent, int yEnd, int maxPercent) { + int var_6 = 0; + int v = 0; + while (v < yStart) + _zoomPercents[v++] = minPercent; + + int diff1 = ABS(maxPercent - minPercent); + int diff2 = ABS(yEnd - yStart); + int var_8 = MAX(diff1, diff2); + + while (var_8-- != 0) { + _zoomPercents[v] = minPercent; + if (diff2 <= diff1) { + ++minPercent; + var_6 += diff2; + if (var_6 >= diff1) { + var_6 -= diff1; + ++v; + } + } else { + ++v; + var_6 += diff1; + if (var_6 >= diff2) { + var_6 -= diff2; + ++minPercent; + } + } + } + + while (yEnd < 256) + _zoomPercents[yEnd++] = minPercent; +} + +} // End of namespace tSage diff --git a/engines/tsage/scenes.h b/engines/tsage/scenes.h new file mode 100644 index 0000000000..1a6f92745d --- /dev/null +++ b/engines/tsage/scenes.h @@ -0,0 +1,115 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_SCENES_H +#define TSAGE_SCENES_H + +#include "common/scummsys.h" +#include "tsage/converse.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/saveload.h" + +namespace tSage { + +class Scene : public StripCallback { +private: + void drawAltObjects(); +public: + int _field12; + int _sceneNumber; + int _activeScreenNumber; + int _sceneMode; + StripManager _stripManager; + + Rect _backgroundBounds; + GfxSurface _backSurface; + Rect _sceneBounds; + Rect _oldSceneBounds; + int _enabledSections[256]; + int _zoomPercents[256]; + ScenePriorities _priorities; + + int _fieldA; + int _fieldE; +public: + Scene(); + virtual ~Scene(); + + virtual Common::String getClassName() { return "Scene"; } + virtual void synchronise(Serialiser &s); + virtual void stripCallback(int v) {} + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void process(Event &event); + virtual void dispatch(); + virtual void loadScene(int sceneNum); + + void setZoomPercents(int yStart, int minPercent, int yEnd, int maxPercent); + void loadBackground(int xAmount, int yAmount); + void refreshBackground(int xAmount, int yAmount); + void loadSceneData(int sceneNum); +}; + +class SceneManager : public GameHandler, public SaveListener { +private: + void disposeRegions() { warning("TODO: disposeRegions()"); } + Scene *getNewScene(); +public: + Scene *_scene; + bool _hasPalette; + int _loadMode; + int _sceneNumber; + int _previousScene; + int _nextSceneNumber; + FadeMode _fadeMode; + Common::Point _sceneBgOffset; + int _sceneLoadCount; + Rect _scrollerRect; + SceneObjectList _altSceneObjects; +public: + SceneManager(); + virtual ~SceneManager(); + + virtual void listenerSynchronise(Serialiser &s); + void setNewScene(int sceneNumber); + void checkScene(); + void sceneChange(); + void fadeInIfNecessary(); + void changeScene(int newSceneNumber); + void setBgOffset(const Common::Point &pt, int loadCount); + + void removeAction(Action *action) { + // Not currently implemented because addAction method doesn't seem to have any callers + } + + static void setup(); + static void setBackSurface(); + static void saveListener(int saveMode); + static void loadNotifier(bool postFlag); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp new file mode 100644 index 0000000000..7c8325d53e --- /dev/null +++ b/engines/tsage/sound.cpp @@ -0,0 +1,62 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "common/endian.h" +#include "tsage/core.h" +#include "tsage/globals.h" +#include "tsage/debugger.h" +#include "tsage/graphics.h" + +namespace tSage { + +void SoundManager::postInit() { + _saver->addSaveNotifier(&SoundManager::saveNotifier); + _saver->addLoadNotifier(&SoundManager::loadNotifier); + _saver->addListener(this); +} + +void SoundManager::saveNotifier(bool postFlag) { + _globals->_soundManager.saveNotifierProc(postFlag); +} + +void SoundManager::saveNotifierProc(bool postFlag) { + warning("TODO: SoundManager::saveNotifierProc"); +} + +void SoundManager::loadNotifier(bool postFlag) { + _globals->_soundManager.loadNotifierProc(postFlag); +} + +void SoundManager::loadNotifierProc(bool postFlag) { + warning("TODO: SoundManager::loadNotifierProc"); +} + +void SoundManager::listenerSynchronise(Serialiser &s) { + s.validate("SoundManager"); + warning("TODO: SoundManager listenerSynchronise"); +} + +} // End of namespace tSage diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h new file mode 100644 index 0000000000..a495344038 --- /dev/null +++ b/engines/tsage/sound.h @@ -0,0 +1,49 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_SOUND_H +#define TSAGE_SOUND_H + +#include "common/scummsys.h" +#include "tsage/saveload.h" + +namespace tSage { + +class SoundManager : public SaveListener { +public: + void dispatch() {} + virtual void listenerSynchronise(Serialiser &s); + virtual void postInit(); + + void proc2() {} + static void saveNotifier(bool postFlag); + void saveNotifierProc(bool postFlag); + static void loadNotifier(bool postFlag); + void loadNotifierProc(bool postFlag); +}; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp new file mode 100644 index 0000000000..46b75e30ea --- /dev/null +++ b/engines/tsage/staticres.cpp @@ -0,0 +1,117 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "tsage/staticres.h" + +namespace tSage { + +const byte CURSOR_ARROW_DATA[] = { + 15, 0, 15, 0, 0, 0, 0, 0, 9, 0, + 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0xFF, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09 +}; + +const byte CURSOR_WALK_DATA[] = { + 15, 0, 15, 0, 7, 0, 7, 0, 9, 0, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x09, 0x09, 0x09, 0x09, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0xFF, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 +}; + +const char *LOOK_SCENE_HOTSPOT = "You see nothing special."; +const char *USE_SCENE_HOTSPOT = "That accomplishes nothing."; +const char *TALK_SCENE_HOTSPOT = "Yak, yak."; +const char *SPECIAL_SCENE_HOTSPOT = "That is a unique use for that."; +const char *DEFAULT_SCENE_HOTSPOT = "That accomplishes nothing."; +const char *SAVE_ERROR_MSG = "Error occurred saving game. Please do not try to restore this game!"; +const char *SAVING_NOT_ALLOWED_MSG = "Saving is not allowed at this time."; +const char *RESTORING_NOT_ALLOWED_MSG = "Restoring is not allowed at this time."; +const char *RESTART_CONFIRM_MSG = "Do you want to restart your game?"; +const char *WATCH_INTRO_MSG = "Do you wish to watch the introduction?"; +const char *INV_EMPTY_MSG = "You have nothing in your possesion."; + +const char *HELP_MSG = "Ringworld\rRevenge of the Patriarch\x14\rScummVM Version\r\r\ +\x01 Keyboard shortcuts...\rF2 - Sound options\rF3 - Quit\r\ +F4 - Restart\rF5 - Save game\rF7 - Restore Game\rF10 - Pause game"; +const char *QUIT_CONFIRM_MSG = "Do you want to quit playing this game?"; +const char *RESTART_MSG = "Do you want to restart this game?"; +const char *GAME_PAUSED_MSG = "Game is paused."; +const char *OPTIONS_MSG = "\x01Options..."; +const char *OK_BTN_STRING = " Ok "; +const char *CANCEL_BTN_STRING = "Cancel"; +const char *QUIT_BTN_STRING = " Quit "; +const char *RESTART_BTN_STRING = "Restart"; +const char *SAVE_BTN_STRING = "Save"; +const char *RESTORE_BTN_STRING = "Restore"; +const char *SOUND_BTN_STRING = "Sound"; +const char *RESUME_BTN_STRING = " Resume \rplay"; +const char *LOOK_BTN_STRING = "Look"; +const char *PICK_BTN_STRING = "Pick"; +const char *START_PLAY_BTN_STRING = " Start Play "; +const char *INTRODUCTION_BTN_STRING = "Introduction"; + +const char *EXIT_MSG = " EXIT "; +const char *SCENE6100_CAREFUL = "Be careful! The probe cannot handle too much of that."; +const char *SCENE6100_TOUGHER = "Hey! This is tougher than it looks!"; +const char *SCENE6100_ONE_MORE_HIT = "You had better be more careful. One more hit like that \ +and the probe may be destroyed."; +const char *SCENE6100_DOING_BEST = "I'm doing the best I can. I just hope it holds together!"; +const char *SCENE6100_REPAIR = "\r\rQuinn and Seeker repair the probe...."; +const char *SCENE6100_ROCKY_AREA = "The rocky area should be directly ahead of you. Do you see it?"; +const char *SCENE6100_REPLY = "Yes. Now if I can just avoid those sunbeams."; +const char *SCENE6100_TAKE_CONTROLS = "You had better take the controls Seeker. My hands are sweating."; +const char *SCENE6100_SURPRISE = "You surprise me Quinn. I would have thought you of hardier stock."; +const char *SCENE6100_SWEAT = "Humans sweat, Kzin twitch their tail. What's the difference?"; +const char *SCENE6100_VERY_WELL = "Very well. I will retrieve the stasis box and return the probe. \ +Wait for it's return in the lander bay."; + +} // End of namespace tSage diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h new file mode 100644 index 0000000000..cb62272735 --- /dev/null +++ b/engines/tsage/staticres.h @@ -0,0 +1,84 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_STATICRES_H +#define TSAGE_STATICRES_H + +#include "common/scummsys.h" + +namespace tSage { + +extern const byte CURSOR_ARROW_DATA[]; + +extern const byte CURSOR_WALK_DATA[]; + +extern const char *LOOK_SCENE_HOTSPOT; +extern const char *USE_SCENE_HOTSPOT; +extern const char *TALK_SCENE_HOTSPOT; +extern const char *SPECIAL_SCENE_HOTSPOT; +extern const char *DEFAULT_SCENE_HOTSPOT; +extern const char *SAVE_ERROR_MSG; +extern const char *SAVING_NOT_ALLOWED_MSG; +extern const char *RESTORING_NOT_ALLOWED_MSG; +extern const char *RESTART_CONFIRM_MSG; +extern const char *WATCH_INTRO_MSG; + +// Dialogs +extern const char *HELP_MSG; +extern const char *QUIT_CONFIRM_MSG; +extern const char *RESTART_MSG; +extern const char *GAME_PAUSED_MSG; +extern const char *OPTIONS_MSG; +extern const char *OK_BTN_STRING; +extern const char *CANCEL_BTN_STRING; +extern const char *QUIT_BTN_STRING; +extern const char *RESTART_BTN_STRING; +extern const char *SAVE_BTN_STRING; +extern const char *RESTORE_BTN_STRING; +extern const char *SOUND_BTN_STRING; +extern const char *RESUME_BTN_STRING; +extern const char *LOOK_BTN_STRING; +extern const char *PICK_BTN_STRING; +extern const char *INV_EMPTY_MSG; +extern const char *START_PLAY_BTN_STRING; +extern const char *INTRODUCTION_BTN_STRING; + +// Scene specific resources +extern const char *EXIT_MSG; +extern const char *SCENE6100_CAREFUL; +extern const char *SCENE6100_TOUGHER; +extern const char *SCENE6100_ONE_MORE_HIT; +extern const char *SCENE6100_DOING_BEST; +extern const char *SCENE6100_REPAIR; +extern const char *SCENE6100_ROCKY_AREA; +extern const char *SCENE6100_REPLY; +extern const char *SCENE6100_TAKE_CONTROLS; +extern const char *SCENE6100_SURPRISE; +extern const char *SCENE6100_SWEAT; +extern const char *SCENE6100_VERY_WELL; + +} // End of namespace tSage + +#endif diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp new file mode 100644 index 0000000000..1f6442f2ff --- /dev/null +++ b/engines/tsage/tsage.cpp @@ -0,0 +1,136 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/debug-channels.h" +#include "common/system.h" +#include "common/savefile.h" +#include "engines/util.h" + +#include "tsage/tsage.h" +#include "tsage/core.h" +#include "tsage/dialogs.h" +#include "tsage/events.h" +#include "tsage/resources.h" +#include "tsage/globals.h" + +namespace tSage { + +TSageEngine *_vm = NULL; + +TSageEngine::TSageEngine(OSystem *system, const tSageGameDescription *gameDesc) : Engine(system), + _gameDescription(gameDesc) { + _vm = this; + DebugMan.addDebugChannel(kRingDebugScripts, "scripts", "Scripts debugging"); + _debugger = new Debugger(); + _dataManager = NULL; +} + +Common::Error TSageEngine::init() { + initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false); + + return Common::kNoError; +} + +TSageEngine::~TSageEngine() { + // Remove all of our debug levels here + DebugMan.clearAllDebugChannels(); + delete _debugger; +} + +bool TSageEngine::hasFeature(EngineFeature f) const { + return + (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + +void TSageEngine::initialise() { + _tSageManager = new RlbManager(_memoryManager, "tsage.rlb"); + _dataManager = new RlbManager(_memoryManager, "ring.rlb"); + + _saver = new Saver(); + _globals = new Globals(); + _globals->gfxManager().setDefaults(); +} + +void TSageEngine::deinitialise() { + delete _globals; + delete _saver; + delete _tSageManager; + delete _dataManager; +} + +Common::Error TSageEngine::run() { + // Basic initialisation + initialise(); + + _globals->_events.showCursor(); + + _globals->_sceneHandler.registerHandler(); + _globals->_game.execute(); + + deinitialise(); + return Common::kNoError; +} + +/** + * Returns true if it is currently okay to restore a game + */ +bool TSageEngine::canLoadGameStateCurrently() { + return _globals->getFlag(50) == 0; +} + +/** + * Returns true if it is currently okay to save the game + */ +bool TSageEngine::canSaveGameStateCurrently() { + return _globals->getFlag(50) == 0; +} + +/** + * Load the savegame at the specified slot index + */ +Common::Error TSageEngine::loadGameState(int slot) { + return _saver->restore(slot); +} + +/** + * Save the game to the given slot index, and with the given name + */ +Common::Error TSageEngine::saveGameState(int slot, const char *desc) { + return _saver->save(slot, desc); +} + +/** + * Support method that generates a savegame name + * @param slot Slot number + */ +Common::String TSageEngine::generateSaveName(int slot) { + return Common::String::format("%s.%03d", _targetName.c_str(), slot); +} + +} // End of namespace tSage diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h new file mode 100644 index 0000000000..2a627d80bc --- /dev/null +++ b/engines/tsage/tsage.h @@ -0,0 +1,104 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef TSAGE_H +#define TSAGE_H + +#include "engines/advancedDetector.h" +#include "engines/engine.h" +#include "common/rect.h" +#include "audio/mixer.h" +#include "common/file.h" + +#include "tsage/core.h" +#include "tsage/resources.h" +#include "tsage/debugger.h" +#include "tsage/events.h" +#include "tsage/graphics.h" +#include "tsage/resources.h" + + +namespace tSage { + +enum { + GType_Ringworld = 0, + GType_BlueForce = 1 +}; + +enum { + GF_DEMO = 1 << 0, + GF_CD = 1 << 1, + GF_FLOPPY = 1 << 2 +}; + +enum { + kRingDebugScripts = 1 << 0 +}; + +struct tSageGameDescription; + +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 200 +#define SCREEN_CENTRE_X 160 +#define SCREEN_CENTRE_Y 100 + +class TSageEngine : public Engine { +private: + const tSageGameDescription *_gameDescription; +public: + TSageEngine(OSystem *system, const tSageGameDescription *gameDesc); + ~TSageEngine(); + virtual bool hasFeature(EngineFeature f) const; + + MemoryManager _memoryManager; + Debugger *_debugger; + RlbManager *_tSageManager; + RlbManager *_dataManager; + + const char *getGameId() const; + uint32 getGameID() const; + uint32 getFeatures() const; + + virtual Common::Error init(); + virtual Common::Error run(); + virtual bool canLoadGameStateCurrently(); + virtual bool canSaveGameStateCurrently(); + virtual Common::Error loadGameState(int slot); + virtual Common::Error saveGameState(int slot, const char *desc); + Common::String generateSaveName(int slot); + + void initialise(); + void deinitialise(); +}; + +extern TSageEngine *_vm; + +#define ALLOCATE_HANDLE(x) _vm->_memoryManager.allocate(x) +#define ALLOCATE(x) _vm->_memoryManager.allocate2(x) +#define DEALLOCATE(x) _vm->_memoryManager.deallocate(x) + +} // End of namespace tSage + +#endif |