/* 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. * * Copyright 2020 Google * */ #include "hadesch/hadesch.h" #include "hadesch/video.h" #include "hadesch/ambient.h" #include "common/translation.h" namespace Hadesch { static const char *kTalusImage = "r1100bb0"; static const char *kTalusImageWithShip = "r1100bc0"; static const char *kTalusMovie = "r1100ba0"; static const char *kTalusHotzone = "Talus"; static const char *kTavernImage = "r2190ba0"; static const char *kTavernHotzone = "Tavern"; static const char *kPoseidonHighlight = "r1230ba0"; static const char *kZeusHighlight = "r1240ba0"; static const char *kHermesHighlight = "r2320ba0"; static const char *kHornless1 = "g0170ob0"; static const char *kHornless2 = "g0170oe0"; static const char *kHornless3 = "g0170oh0"; static const char *kHornless4 = "g0170ok0"; static const char *kHorned = "g1800ob0"; static const char *kHornedHotzone = "HornedStatue"; static const char *kHornless1Hotzone = "HornlessStatue1"; static const char *kHornless2Hotzone = "HornlessStatue2"; static const char *kHornless3Hotzone = "HornlessStatue3"; static const char *kHornless4Hotzone = "HornlessStatue4"; static const char *kMerchantAnim = "r2130ba0"; static const char *kOneManBandAnim = "r2040ba1"; static const char *kOneManBandHotZone = "OneManBand"; static const char *kAtlantisOpening = "r1210bb0"; static const char *kAtlantisLargeDisk = "r1210be0"; static const char *kAtlantisMediumDisk = "r1210bf0"; static const char *kAtlantisSmallDisk = "r1210bg0"; static const char *kAtlantisDiskBackground = "r1210os0"; static const int vaseSol[] = {2, 3, 2, 3}; static const char *vaseSound[] = { "r1220ec0", "r1220ed0", "r1220ee0", "r1220ef0" }; static const char *vaseSegment[] = { "r1220bc0", "r1220bd0", "r1220be0", "r1220bf0" }; enum { kBackgroundZ = 10000, kTalusZ = 6000, kTavernImageZ = 5000, kOneManBandZ = 1600, kMerchantStandZ = 1205, kMerchantZ = 1200, kAtlantisDiskBackgroundZ = 1100, kAtlantisLargeDiskZ = 1000, kAtlantisMediumDiskZ = 900, kAtlantisSmallDiskZ = 800, kAtlantisOpeningZ = 700 }; enum { kIntroMerchantVideoFinished = 12107, kTakenHorned = 12115, kTakenHornless = 12118, kMerchantIdleTimer = 12121, kMerchantIdleAnimCleanup = 12122, kTalueMovieCompleted = 12129, // 12137 is the end of statue animation that we handle as functor instead kAtlantisDoorOpens = 12307, kTavernMovieCompleted = 1012001, kIntroMerchantPanFinished = 1012002, kAtlantisBoatIntro2Finished = 1012003, kTakenWood = 1012005, kSoundVaseSegment1Finished = 1012006, kSoundVaseSegment2Finished = 1012007, kSoundVaseSegment3Finished = 1012008, kSoundVaseSegment4Finished = 1012009, kCoinGiven = 1012010, kSandalsPlaced = 1012011 }; static const PrePoint strongBoxSideDotOffsets[] = { {1060, 278}, {1090, 310}, {1060, 339}, {1032, 305} }; static const PrePoint strongBoxTileOffsets[] = { {1005, 274}, {1035, 276}, {1064, 278}, {1093, 280}, {1005, 304}, {1035, 306}, {1064, 308}, {1093, 310}, {1035, 246}, {1064, 248}, {1035, 337}, {1064, 339} }; static const int baseFrame[4][8] = { { 1, 3, 4, 6, 1, 3, 4, 6 }, { 7, 9, 10, 12, 13, 15, 16, 18 }, { 19, 21, 22, 24, 25, 27, 28, 30 }, { 31, 33, 34, 36, 31, 33, 34, 36 } }; static const int kTileMovementTime = 500; class StrongBoxTile { public: enum Letter { kLetterZ = 1, kLetterE, kLetterU, kLetterS }; enum Orientation { kOrientation0 = 0, kOrientation90 = 90, kOrientation180 = 180, kOrientation270 = 270 }; void rotate() { _orientation = (Orientation) ((_orientation + 90) % 360); } void show() { Common::SharedPtr room = g_vm->getVideoRoom(); int orientation = _orientation / 45; if (_nextPosition != -1 && g_vm->getCurrentTime() > kTileMovementTime + _movementStartTime) { _position = _nextPosition; _nextPosition = -1; } Common::Point pos = strongBoxTileOffsets[_position].get(); if (_nextPosition != -1) { double frac = (g_vm->getCurrentTime() - _movementStartTime + 0.0) / kTileMovementTime; pos = strongBoxTileOffsets[_position].get() * (1-frac) + strongBoxTileOffsets[_nextPosition].get() * frac; } int zVal = 500; switch (_rotationPhase) { case 0: case 2: pos += Common::Point(-5, 4); zVal = 300; break; case 1: orientation++; switch (_position) { case 1: pos = Common::Point(1046, 277); break; case 2: pos = Common::Point(1065, 298); break; case 5: pos = Common::Point(1025, 297); break; case 6: pos = Common::Point(1045, 318); break; } zVal = 300; break; } int frame = baseFrame[_letter - kLetterZ][orientation] - 1; if (_position < 4 && _nextPosition == -1 && _rotationPhase < 0) frame++; room->selectFrame(LayerId("r2010om0", _position, "pos"), zVal, frame, pos); } void setRotationPhase(int phase) { _rotationPhase = phase; } bool isMoving() { return _nextPosition != -1 || _rotationPhase != -1; } int getPosition() { return _position; } Letter getLetter() { return _letter; } Orientation getOrientation() { return _orientation; } void setPosition(int position) { _position = position; } void moveTo(int pos) { _nextPosition = pos; _movementStartTime = g_vm->getCurrentTime(); } StrongBoxTile() { _letter = kLetterZ; _position = 0; _orientation = kOrientation0; _nextPosition = -1; _rotationPhase = -1; } StrongBoxTile(Letter letter, Orientation orientation, int position) { _letter = letter; _position = position; _orientation = orientation; _nextPosition = -1; _rotationPhase = -1; } private: Letter _letter; int _position; int _nextPosition; int _movementStartTime; int _rotationPhase; Orientation _orientation; }; static const struct { StrongBoxTile::Letter letter; StrongBoxTile::Orientation orientation; } initialLetters[12] = { {StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterE, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterU, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterS, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterE, StrongBoxTile::kOrientation0}, {StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation0}, {StrongBoxTile::kLetterU, StrongBoxTile::kOrientation270}, {StrongBoxTile::kLetterS, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterU, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterE, StrongBoxTile::kOrientation90}, {StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation0}, {StrongBoxTile::kLetterS, StrongBoxTile::kOrientation0} }; class CreteHandler : public Handler { public: CreteHandler() { _tavernCounter = 0; _oneManBandCounter = 0; _merchantIsBusy = false; memset(_vaseBusy, 0, sizeof(_vaseBusy)); for (int i =0; i < 12; i++) _strongBoxTiles[i] = StrongBoxTile(initialLetters[i].letter, initialLetters[i].orientation, i); _strongBoxPopup = false; _fadingHades = false; _fadingHadesStartTime = 0; } void handleClick(const Common::String &name) override { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); if (name == kTalusHotzone) { room->playVideo(kTalusMovie, kTalusZ, kTalueMovieCompleted, Common::Point(54, 29)); room->setLayerEnabled(kTalusImageWithShip, false); return; } if (name == "MinosPalace") { room->disableMouse(); g_vm->moveToRoom(kMinosPalaceRoom); return; } if (name == "Poseidon") { Common::Array videos; videos.push_back("r1230na0"); videos.push_back("r1230nb0"); videos.push_back("r1230nc0"); room->playStatueSMK(kPoseidonStatue, kPoseidonHighlight, 5000, videos, 16, 39); return; } if (name == "Zeus") { Common::Array videos; videos.push_back("r1240wa0"); videos.push_back("r1240wb0"); room->playStatueSMK(kZeusStatue, kZeusHighlight, 5000, videos, 23, 35); return; } if (name == "Hermes") { Common::Array videos; videos.push_back("r2320na0"); videos.push_back("r2320nb0"); room->playStatueSMK(kHermesStatue, kHermesHighlight, 4000, videos, 22, 39, kOffsetRightRoom); return; } if (name == kTavernHotzone) { room->playAnimLoop(kTavernImage, 5000, kOffsetRightRoom); room->playVideo(_tavernTalks[_tavernCounter], 5000, kTavernMovieCompleted, kOffsetRightRoom); _tavernCounter = (_tavernCounter + 1) % _tavernTalks.size(); return; } if (name == "Argo") { g_vm->moveToRoom(kArgoRoom); return; } if (name == kHornedHotzone) { g_vm->getHeroBelt()->placeToInventory(kHornedStatue, kTakenHornless); room->setLayerEnabled(kHorned, false); persistent->_creteShowHorned = false; _merchantIsBusy = true; room->disableHotzone(kHornedHotzone); room->disableMouse(); return; } if (name == kHornless1Hotzone) { g_vm->getHeroBelt()->placeToInventory(kHornlessStatue1, kTakenHorned); room->setLayerEnabled(kHornless1, false); persistent->_creteShowHornless1 = false; room->disableHotzone(kHornless1Hotzone); _merchantIsBusy = true; room->disableMouse(); return; } if (name == kHornless2Hotzone) { g_vm->getHeroBelt()->placeToInventory(kHornlessStatue2, kTakenHorned); room->setLayerEnabled(kHornless2, false); persistent->_creteShowHornless2 = false; room->disableHotzone(kHornless2Hotzone); _merchantIsBusy = true; room->disableMouse(); return; } if (name == kHornless3Hotzone) { g_vm->getHeroBelt()->placeToInventory(kHornlessStatue3, kTakenHorned); room->setLayerEnabled(kHornless3, false); persistent->_creteShowHornless3 = false; room->disableHotzone(kHornless3Hotzone); _merchantIsBusy = true; room->disableMouse(); return; } if (name == kHornless4Hotzone) { g_vm->getHeroBelt()->placeToInventory(kHornlessStatue4, kTakenHorned); room->setLayerEnabled(kHornless4, false); persistent->_creteShowHornless4 = false; room->disableHotzone(kHornless4Hotzone); _merchantIsBusy = true; room->disableMouse(); return; } if (name == kOneManBandHotZone) { room->playVideo( Common::String::format( "r2040b%c0", 'a' + (_oneManBandCounter % 3)), 1600, 12135, Common::Point(730, 183)); room->stopAnim(kOneManBandAnim); _oneManBandCounter++; return; } if (name == "AtlantisBoat") { room->pushHotZones("Door.HOT"); room->disableHotzone("wood"); room->selectFrame("r1010ob0", 1200, 0); room->selectFrame(kAtlantisDiskBackground, kAtlantisDiskBackgroundZ, 0); for (unsigned i = 0; i < 3; i++) _atlantisBoatPosition[i] = g_vm->getRnd().getRandomNumberRng(1, 7); renderAtlantisDisks(); if (persistent->_creteIntroAtlantisWood) { room->disableMouse(); room->playVideo("R1210BA0", 600, kAtlantisBoatIntro2Finished); persistent->_creteIntroAtlantisWood = false; } return; } if (name == "SmallDisk") { advanceAtlantisDisk(2); return; } if (name == "MediumDisk") { advanceAtlantisDisk(1); return; } if (name == "LargeDisk") { advanceAtlantisDisk(0); return; } if (name == "wood") { room->selectFrame(kAtlantisOpening, kAtlantisOpeningZ, 9); g_vm->getHeroBelt()->placeToInventory(kWood, kTakenWood); room->popHotZones(); room->disableHotzone("AtlantisBoat"); persistent->_creteShowAtlantisBoat = false; return; } if (name == "Background") { room->popHotZones(); room->stopAnim("r1010ob0"); hideStrongBox(); hideAtlantisPopupOverlays(); showMiniStrongBox(); return; } for (int i = 0; i < 4; i++) { if (name == Common::String::format("VaseSegment%d", i + 1) && !_vaseBusy[i]) { _vasePos[i]++; if (i == 1 || i == 3) _vasePos[i] %= 6; else _vasePos[i] %= 4; _vaseBusy[i] = true; renderVase(); room->playSFX(vaseSound[i], kSoundVaseSegment1Finished + i); return; } } if (name == "sandals") { g_vm->getHeroBelt()->placeToInventory(kSandals, kSandalsPlaced); room->selectFrame("r1220ba0", 500, 0); room->disableMouse(); persistent->_creteSandalsState = Persistent::SANDALS_TAKEN; return; } if (name == "AlchemistStand") { _alchemistAmbient.play(false); return; } if (name == "StrongBoxClosed" || name == "StrongBoxOpen" || name == "StrongBoxOpenPotion" || name == "StrongBoxOpenNoPotion") { showStrongBox(); return; } if (name == "Latch") { room->disableMouse(); persistent->_creteStrongBoxState = Persistent::BOX_OPEN; room->playAnimWithSFX("r2230bb0", "g0082ea0", 1000, PlayAnimParams::keepLastFrame().partial(1, 3), 12402, kOffsetRightRoom); return; } if (name == "ButtonN" && !strongBoxIsBusy()) { strongBoxMoveTiles(1, 8, 9, 2); return; } if (name == "ButtonE" && !strongBoxIsBusy()) { strongBoxMoveTiles(2, 3, 7, 6); return; } if (name == "ButtonW" && !strongBoxIsBusy()) { strongBoxMoveTiles(1, 5, 4, 0); return; } if (name == "ButtonS" && !strongBoxIsBusy()) { strongBoxMoveTiles(5, 6, 11, 10); return; } if (name == "ButtonC" && !strongBoxIsBusy()) { g_vm->addTimer(12409, 250); room->playSFX("r2230ed0", 12412); for (int i = 0; i < 12; i++) { int pos = _strongBoxTiles[i].getPosition(); if (pos == 1 || pos == 2 || pos == 5 || pos == 6) { _strongBoxTiles[i].setRotationPhase(0); } } return; } if (name == "Potion") { room->disableHotzone("Potion"); g_vm->getHeroBelt()->placeToInventory(kCoin, kCoinGiven); persistent->_creteStrongBoxState = Persistent::BOX_OPEN_NO_POTION; room->selectFrame("r2230bf0", 300, -1, kOffsetRightRoom); return; } /* TODO: MNSH: Merchant */ } void handleEvent(int eventId) override { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); switch (eventId) { case kTakenWood: room->stopAnim(kAtlantisOpening); room->stopAnim("r1010ob0"); room->stopAnim(kAtlantisDiskBackground); room->enableMouse(); break; case kTalueMovieCompleted: room->setLayerEnabled(kTalusImageWithShip, true); break; case kTavernMovieCompleted: room->selectFrame(kTavernImage, kTavernImageZ, 0, kOffsetRightRoom); break; case kMerchantIdleTimer: if (!persistent->_creteShowMerchant || !persistent->_creteShowHornless4 || _merchantIsBusy) break; room->setLayerEnabled(kHornless4, false); room->disableHotzone(kHornless4Hotzone); room->playAnim(kMerchantAnim, kMerchantZ, PlayAnimParams::disappear().partial(1, -2), kMerchantIdleAnimCleanup); break; case kMerchantIdleAnimCleanup: room->selectFrame(kMerchantAnim, kMerchantZ, 0); room->setLayerEnabled(kHornless4, persistent->_creteShowHornless4); room->setHotzoneEnabled(kHornless4Hotzone, persistent->_creteShowHornless4 && persistent->_creteTriedHornless[2]); break; case kIntroMerchantPanFinished: room->setLayerEnabled(kMerchantAnim, false); room->playVideo("R2200BA0", kMerchantZ, kIntroMerchantVideoFinished, Common::Point(308, 99)); break; // TODO: replay of R2200BB0 and R2200BC0 case kIntroMerchantVideoFinished: room->disableMouse(); room->playVideo("R2200BB0", kMerchantZ, 12108, Common::Point(304, 113)); _merchantIsBusy = true; break; case 12108: room->disableMouse(); room->playVideo("R2200BC0", kMerchantZ, 12109, Common::Point(304, 110)); _merchantIsBusy = true; break; case 12109: room->selectFrame(kMerchantAnim, kMerchantZ, 0); room->enableMouse(); _merchantIsBusy = false; break; case kTakenHorned: room->setLayerEnabled(kMerchantAnim, false); room->playVideo("r2210ba0", kMerchantZ, 12117, Common::Point(344, 111)); room->disableMouse(); break; case 12117: room->playVideo("r2210bb0", kMerchantZ, 12119, Common::Point(308, 112)); break; case kTakenHornless: room->setLayerEnabled(kMerchantAnim, false); room->playVideo("r2240ba0", kMerchantZ, 12119, Common::Point(314, 91)); _merchantIsBusy = true; break; case 12119: room->selectFrame(kMerchantAnim, kMerchantZ, 0); if (!persistent->_cretePlayedEyeGhostTown) { room->playVideo("r2210bc0", 1000, 12120, Common::Point(0, 216)); persistent->_cretePlayedEyeGhostTown = true; } else { room->enableMouse(); _merchantIsBusy = false; } break; case 12120: room->selectFrame(kMerchantAnim, kMerchantZ, 0); room->enableMouse(); _merchantIsBusy = false; break; case 12128: case 12134: case 12143: case 12146: room->enableMouse(); break; case 12135: room->playAnimLoop(kOneManBandAnim, kOneManBandZ, kOffsetRightRoom); break; case 12142: if (persistent->_quest == kMedusaQuest && !persistent->_cretePlayedPhilAlchemist) { persistent->_cretePlayedPhilAlchemist = true; room->playVideo("r2220bc0", 1000, 12143, Common::Point(640, 216)); room->disableMouse(); } if (persistent->_quest == kRescuePhilQuest && !persistent->_cretePlayedZeusCheckOutThatBox && persistent->_hintsAreEnabled) { g_vm->addTimer(12144, 5000, -1); } break; case 12144: if (!room->isMouseEnabled() || persistent->_cretePlayedZeusCheckOutThatBox) break; persistent->_cretePlayedZeusCheckOutThatBox = true; room->disableMouse(); room->playAnimWithSpeech("r2230ba0", TranscribedSound::make("r2230wa0", "Hey, why don't you check out that box? Maybe it has something that can help"), 4000, PlayAnimParams::keepLastFrame(), 12145, kOffsetRightRoom); break; case kAtlantisBoatIntro2Finished: room->enableMouse(); break; case kAtlantisDoorOpens: room->disableHotzone("LargeDisk"); room->disableHotzone("MediumDisk"); room->disableHotzone("SmallDisk"); room->disableHotzone("Background"); room->enableHotzone("wood"); room->playVideo("r1210bd0", 600, 12308); break; case 12308: room->enableMouse(); break; case kSoundVaseSegment1Finished: case kSoundVaseSegment2Finished: case kSoundVaseSegment3Finished: case kSoundVaseSegment4Finished: { int vase = eventId - kSoundVaseSegment1Finished; bool won = true; _vaseBusy[vase] = false; for (int i = 0; i < 4; i++) { if (_vaseBusy[i]) won = false; } for (int i = 0; i < 4; i++) { if (_vasePos[i] != vaseSol[i]) won = false; } if (!won) break; for (int i = 0; i < 4; i++) room->stopAnim(vaseSegment[i]); for (int i = 0; i < 4; i++) room->disableHotzone(Common::String::format("VaseSegment%d", i + 1)); room->playAnim("r1220ba0", 500, PlayAnimParams::disappear().partial(0, 17), 12206); room->playVideo("r1220mb0", 0); room->playSFX("r1220ea0"); room->disableMouse(); break; } case 12206: showSandals(); persistent->_creteSandalsState = Persistent::SANDALS_SOLVED; room->enableMouse(); break; case 12303: case 12304: case 12305: if (_atlantisBoatPosition[0] == 0 && _atlantisBoatPosition[1] == 0 && _atlantisBoatPosition[2] == 0) { handleEvent(12306); } break; case 12306: room->disableMouse(); hideAtlantisPopupOverlays(); room->playAnimWithSFX(kAtlantisOpening, "r1210eb0", kAtlantisOpeningZ, PlayAnimParams::keepLastFrame().partial(0, 8), kAtlantisDoorOpens); break; case 12402: room->enableMouse(); redrawStrongBox(); // Fallthrough case 12403: room->disableMouse(); room->playAnimWithSpeech("r2230ba0", TranscribedSound::make("r2230wb0", "I think those buttons control the symbols"), 4000, PlayAnimParams::keepLastFrame(), 12404, kOffsetRightRoom); break; case 12404: case 12405: if (persistent->_hintsAreEnabled) g_vm->addTimer(12406, 5000); // Fallthrough case 12407: case 12408: case 12145: room->playAnim("r2230ba0", 4000, PlayAnimParams::disappear().backwards(), -1, kOffsetRightRoom); room->enableMouse(); break; case 12406: if (!room->isMouseEnabled()) break; room->disableMouse(); room->playAnimWithSpeech("r2230ba0", TranscribedSound::make("r2230wc0", "Try to spell my name"), 4000, PlayAnimParams::keepLastFrame(), 12407, kOffsetRightRoom); break; case 12409: for (int i = 0; i < 12; i++) { int pos = _strongBoxTiles[i].getPosition(); if (pos == 1 || pos == 2 || pos == 5 || pos == 6) { _strongBoxTiles[i].setRotationPhase(1); } } g_vm->addTimer(12410, 250); break; case 12410: for (int i = 0; i < 12; i++) { int pos = _strongBoxTiles[i].getPosition(); if (pos == 1 || pos == 2 || pos == 5 || pos == 6) { _strongBoxTiles[i].setRotationPhase(2); _strongBoxTiles[i].rotate(); switch (pos) { case 1: _strongBoxTiles[i].setPosition(2); break; case 2: _strongBoxTiles[i].setPosition(6); break; case 5: _strongBoxTiles[i].setPosition(1); break; case 6: _strongBoxTiles[i].setPosition(5); break; } } } g_vm->addTimer(12411, 250); break; case 12411: for (int i = 0; i < 12; i++) { _strongBoxTiles[i].setRotationPhase(-1); } redrawStrongBox(); break; case 12414: room->playVideo("v4190ma0", 0, 12415); break; case 12204: case 12415: room->enableMouse(); break; case kCoinGiven: g_vm->getHeroBelt()->placeToInventory(kPotion); break; case 12124: _fadingHades = true; _fadingHadesStartTime = g_vm->getCurrentTime(); break; case 12125: room->stopAnim("r2035ba0"); room->playVideo("R2035BE0", 1200, 12127); break; case 12127: g_vm->moveToRoom(kDaedalusRoom); break; case kSandalsPlaced: room->playVideo("r1220bb0", 0, 12204); break; } } void prepareRoom() override { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); Quest quest = persistent->_quest; if (persistent->_creteHadesPusnishesPainAndPanic) { room->disableHeroBelt(); room->disableMouse(); room->addStaticLayer("r2035pa0", kBackgroundZ); // background room->selectFrame("r2035ba0", 1200, 0); // Originally event 12123 room->playSpeech(TranscribedSound::make( "r2035wa0", "Seems the only thing I can count on you two for is target practice"), 12124); persistent->_creteHadesPusnishesPainAndPanic = false; return; } room->loadHotZones("Crete.HOT", false); room->addStaticLayer("r1010pa0", kBackgroundZ); // background g_vm->getHeroBelt()->setColour(HeroBelt::kWarm); if (quest != kMedusaQuest && quest != kRescuePhilQuest) { room->playAnimLoop("r2010oe0", 7000, kOffsetRightRoom); room->playAnimLoop("r2010tb0", 6500, kOffsetRightRoom); } room->playAnimLoop("r2010ta0", 7600, kOffsetRightRoom); room->playAnimLoop("r1120ba0", 5500); room->playAnimLoop("r1160ba0", 5000); room->playAnimLoop("r1170ba0", 5000); room->selectFrame(kTavernImage, kTavernImageZ, 0, kOffsetRightRoom); room->enableMouse(); room->setPannable(true); room->enableHotzone(kTavernHotzone); room->enableHotzone("Argo"); room->enableHotzone("Hermes"); room->enableHotzone("Zeus"); room->enableHotzone("Poseidon"); room->enableHotzone("MinosPalace"); if (quest != kMedusaQuest && quest != kRescuePhilQuest) { room->enableHotzone("AlchemistStand"); } room->setUserPanCallback(-1, -1, 12140, 12142); if (quest == kMedusaQuest && !persistent->_creteAlchemistExploded) { persistent->_creteAlchemistExploded = true; room->disableMouse(); room->playAnimWithSFX("r1190ba0", "r1190ea0", 1005, PlayAnimParams::disappear(), 12128); } if (quest == kRescuePhilQuest || quest == kMedusaQuest) { room->selectFrame("r2010op0", 7500, 0, kOffsetRightRoom); } if (quest == kMedusaQuest) { room->playAnimWithSFX("r2220bb0", "r2220eb0", 4500, PlayAnimParams::loop(), -1, kOffsetRightRoom); } showMiniStrongBox(); switch (quest) { case kCreteQuest: _tavernTalks.push_back("r2250xa0"); _tavernTalks.push_back("r2250xb0"); _tavernTalks.push_back("r2250xc0"); _tavernTalks.push_back("r2250xd0"); _tavernTalks.push_back("r2250xe0"); _tavernTalks.push_back("r2250xf0"); _tavernTalks.push_back("r2220xa0"); _tavernTalks.push_back("r2220xb0"); _tavernTalks.push_back("r2220xc0"); _tavernTalks.push_back("r2220xd0"); _tavernTalks.push_back("r2220xe0"); _tavernTalks.push_back("r2220xf0"); break; case kTroyQuest: _tavernTalks.push_back("r2260xa0"); _tavernTalks.push_back("r2260xb0"); _tavernTalks.push_back("r2195xa0"); _tavernTalks.push_back("r2195xb0"); _tavernTalks.push_back("r2290xf0"); _tavernTalks.push_back("r2220xa0"); _tavernTalks.push_back("r2220xb0"); _tavernTalks.push_back("r2220xc0"); _tavernTalks.push_back("r2220xd0"); _tavernTalks.push_back("r2220xe0"); _tavernTalks.push_back("r2220xf0"); break; case kMedusaQuest: _tavernTalks.push_back("r2270xa0"); _tavernTalks.push_back("r2270xb0"); _tavernTalks.push_back("r2290xg0"); _tavernTalks.push_back("r2290xh0"); _tavernTalks.push_back("r2290xi0"); _tavernTalks.push_back("r2290xj0"); _tavernTalks.push_back("r2290xk0"); _tavernTalks.push_back("r2290xl0"); break; case kRescuePhilQuest: _tavernTalks.push_back("r2280xa0"); _tavernTalks.push_back("r2280xc0"); _tavernTalks.push_back("r2280xd0"); _tavernTalks.push_back("r2290xg0"); _tavernTalks.push_back("r2290xh0"); _tavernTalks.push_back("r2290xi0"); _tavernTalks.push_back("r2290xj0"); _tavernTalks.push_back("r2290xk0"); _tavernTalks.push_back("r2290xl0"); break; // To silence warning case kNoQuest: case kEndGame: case kNumQuests: break; } _tavernTalks.push_back("r2290xa0"); _tavernTalks.push_back("r2290xb0"); _tavernTalks.push_back("r2290xc0"); _tavernTalks.push_back("r2290xd0"); _tavernTalks.push_back("r2290xe0"); int bg1_variant = -1; int bg2_variant = -1; bool showOiBoat = false; if (!persistent->_creteShowMerchant && (quest != kMedusaQuest || !persistent->_medisleShowFates)) { bg1_variant = g_vm->getRnd().getRandomNumberRng(0, 2); bg2_variant = g_vm->getRnd().getRandomNumberRng(0, 2); debug("BG variants %d and %d", bg1_variant, bg2_variant); } if (randomBool()) { showOiBoat = true; room->addStaticLayer("r1010oi0", 4000); } if (randomBool()) room->addStaticLayer("r1010oj0", 4000); if (randomBool()) room->addStaticLayer("r1010ok0", 4000); if (randomBool()) room->addStaticLayer("r1010ol0", 4000); if (randomBool()) room->addStaticLayer("r1010on0", 4001); if (randomBool()) room->addStaticLayer("r1010oo0", 4000); if (randomBool()) room->addStaticLayer("r1010op0", 4100); if (randomBool()) room->addStaticLayer("r1010or0", 6500); if (quest != kCreteQuest) persistent->_creteShowAtlantisBoat = false; if (persistent->_creteShowAtlantisBoat) { room->addStaticLayer("r1010od0", 3900); room->addStaticLayer("r1010ta0", 3800); room->enableHotzone("AtlantisBoat"); } room->playAnimLoop("r1010om0", 3000); int minotaurPosition = -1; int toughGuyPosition = -1; int womanSmellPosition = -1; if (quest == kCreteQuest && !persistent->_creteShowMerchant && !persistent->_creteShowAtlantisBoat) minotaurPosition = g_vm->getRnd().getRandomNumberRng(0, 3); bool showCat = false; bool showStatueMan = false; bool showOldMan = false; bool showBlondBoy = false; bool showMotherAndKidSmall = false; bool showMotherAndKid = false; bool showManSelling = false; bool showDrawinWithoutWoman = false; bool showWomanDrawing = false; bool showWomanGraffiti = false; bool showGirlAndNut = false; bool showOneManBand = false; int ambientComposite = g_vm->getRnd().getRandomNumberRng(1, 8); debug("Ambients from Composite %d selected. \n", ambientComposite); switch (ambientComposite) { case 1: showGirlAndNut = true; if (quest != kCreteQuest && quest != kTroyQuest) { toughGuyPosition = 1; break; } if (minotaurPosition == 1) { if (randomBool()) toughGuyPosition = 0; break; } if (persistent->_creteShowMerchant) { showOneManBand = true; showWomanGraffiti = true; break; } if (randomBool()) { toughGuyPosition = 0; showOneManBand = true; showWomanGraffiti = true; } else toughGuyPosition = 1; break; case 2: womanSmellPosition = g_vm->getRnd().getRandomNumberRng(0, 2); showWomanDrawing = true; showManSelling = true; if (quest != kMedusaQuest && quest != kRescuePhilQuest) showMotherAndKid = true; showBlondBoy = true; break; case 3: if (quest != kRescuePhilQuest && bg1_variant != 0 && bg1_variant != 1) showCat = true; showOldMan = true; if (!persistent->_creteShowMerchant) { showManSelling = true; toughGuyPosition = 2; } showWomanGraffiti = true; showWomanDrawing = true; break; case 4: if (quest != kRescuePhilQuest && bg1_variant != 0 && bg1_variant != 1) showCat = true; showWomanDrawing = true; toughGuyPosition = 2; showOneManBand = true; break; case 5: if (quest != kCreteQuest && quest != kTroyQuest) toughGuyPosition = 1; else toughGuyPosition = g_vm->getRnd().getRandomBit(); womanSmellPosition = g_vm->getRnd().getRandomBit(); break; case 6: showWomanGraffiti = true; showWomanDrawing = true; if (quest != kCreteQuest && quest != kTroyQuest) toughGuyPosition = 1; else toughGuyPosition = g_vm->getRnd().getRandomBit(); break; case 7: womanSmellPosition = g_vm->getRnd().getRandomNumberRng(0, 2); if (womanSmellPosition == 2 && (quest != kCreteQuest && quest != kTroyQuest)) womanSmellPosition = -1; if (quest == kMedusaQuest) showStatueMan = true; showMotherAndKidSmall = true; showWomanGraffiti = true; break; case 8: if (quest != kCreteQuest && quest != kTroyQuest) { toughGuyPosition = 1; showDrawinWithoutWoman = true; break; } if (!persistent->_creteShowMerchant && randomBool()) { toughGuyPosition = 2; showBlondBoy = true; } else toughGuyPosition = 1; showOldMan = true; showDrawinWithoutWoman = true; break; } int birdsState = g_vm->getRnd().getRandomNumberRng(0, 2); int dolphinPosition = -1; if (!persistent->_creteShowAtlantisBoat) dolphinPosition = g_vm->getRnd().getRandomNumberRng(0, showOiBoat ? 1 : 2); if (quest != kMedusaQuest && quest != kRescuePhilQuest) _alchemistAmbient = ambient("r2220ba0", "r2220ec0", 5500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom, true); // Disable conflicting images if (minotaurPosition == 1 && (toughGuyPosition == 1 || toughGuyPosition == 2)) toughGuyPosition = -1; if (minotaurPosition == 1) { showWomanGraffiti = false; showManSelling = false; showOneManBand = false; } if (persistent->_creteShowMerchant && (toughGuyPosition == 0 || toughGuyPosition == 1)) toughGuyPosition = -1; if (womanSmellPosition == 2) showMotherAndKid = false; if (persistent->_creteShowMerchant) showCat = false; if (quest != kCreteQuest && quest != kTroyQuest) showOldMan = false; debug("toughGuyPosition = %d, minotaurPosition = %d, dolphinPosition = %d", toughGuyPosition, minotaurPosition, dolphinPosition); if (showWomanGraffiti) ambient("r2370ba0", "r2370ea0", 1700, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); switch (toughGuyPosition) { case 0: ambient("r2340ba0", "r2340ea0", 1400, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); break; case 1: ambient("r2340bb0", "r2340eb0", 1400, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); break; case 2: ambient("r2340be0", "r2340ee0", 1600, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); break; } if (showOneManBand) { room->playAnimLoop(kOneManBandAnim, kOneManBandZ, kOffsetRightRoom); room->enableHotzone(kOneManBandHotZone); } if (showGirlAndNut) ambient("r2140ba0", "r2140ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showWomanDrawing) ambient("r2110ba0", "r2110ea0", 1600, 10, 30, AmbientAnim::PAN_LEFT); if (showDrawinWithoutWoman) room->addStaticLayer("r2110bb0", 1600); if (showManSelling) ambient("r2150ba0", "r2150ea0", 1600, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showMotherAndKid) ambient("r2160ba0", "r2160ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showMotherAndKidSmall) ambient("r2160bb0", "", 1500, 15, 30, AmbientAnim::PAN_LEFT); if (showBlondBoy) ambient("r2350ba0", "r2350ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showOldMan) ambient("r2100bb0", "r2100eb0", 1500, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showStatueMan) ambient("r2050ba0", "r2050ea0", 1500, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); if (showCat) { room->addStaticLayer("r2010on0", kMerchantStandZ); ambient("r2080bb0", "r2080eb0", kMerchantZ, 10, 30, AmbientAnim::PAN_LEFT); } if (persistent->_creteShowMerchant) { room->addStaticLayer("r2010on0", kMerchantStandZ); room->selectFrame(kMerchantAnim, kMerchantZ, 0); room->playSFX("G0261mA0"); if (persistent->_creteShowHorned) { room->addStaticLayer(kHorned, 1220); room->enableHotzone(kHornedHotzone); } if (persistent->_creteShowHornless2) { room->addStaticLayer(kHornless2, 1190); room->setHotzoneEnabled(kHornless2Hotzone, persistent->_creteTriedHornless[0]); } if (persistent->_creteShowHornless1) { room->addStaticLayer(kHornless1, 1180); room->enableHotzone(kHornless1Hotzone); } if (persistent->_creteShowHornless3) { room->addStaticLayer(kHornless3, 1180); room->setHotzoneEnabled(kHornless3Hotzone, persistent->_creteTriedHornless[1]); } if (persistent->_creteShowHornless4) { room->addStaticLayer(kHornless4, 1180); room->setHotzoneEnabled(kHornless4Hotzone, persistent->_creteTriedHornless[2]); g_vm->addTimer(kMerchantIdleTimer, 10000, -1); } } if (birdsState == 0) { room->addStaticLayer(kTalusImageWithShip, kTalusZ); room->enableHotzone(kTalusHotzone); } else room->addStaticLayer(kTalusImage, kTalusZ); // TODO: fix this switch (minotaurPosition) { case 0: ambient("r2060bf0", "r2060ee0", 1800, 3, 4, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); // shouldn't be an ambient break; case 1: ambient("r2060bt0", "r2060ei0", 1650, 3, 4, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); // shouldn't be an ambient break; case 2: // ambient("r1110ea0", "", 15, 30); // wrong break; case 3: ambient("r1110ba0", "r1110eb0", 850, 20, 40, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); break; } switch (womanSmellPosition) { case 0: ambient("r2380ba0", "r2380ea0", 1550, 15, 30, AmbientAnim::PAN_ANY); break; case 1: ambient("r2380bc0", "r2380ec0", 1550, 15, 30, AmbientAnim::PAN_ANY); break; case 2: ambient("r2380bd0", "r2380ed0", 1550, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); break; } switch (birdsState) { case 0: ambient("r1060ba0", "r1060ea0", 4500, 10, 40, AmbientAnim::PAN_ANY); break; case 1: ambient("r1060bb0","r1060eb0", 4500, 5, 40, AmbientAnim::PAN_ANY); break; case 2: ambient("r1060bc0", "r1060ec0", 4500, 5, 40, AmbientAnim::PAN_ANY); break; } if (dolphinPosition >= 0) { Common::String dolphinAnim = Common::String::format( "r1150b%c0", 'a' + dolphinPosition); Common::String dolphinSound = Common::String::format( "r1150e%c0", 'a' + dolphinPosition); ambient(dolphinAnim, dolphinSound, 5500, 5, 20, AmbientAnim::PAN_LEFT); } if (bg1_variant >= 0 && bg2_variant >= 0) { Common::String bg2 = Common::String::format( "r1010o%c1", 'e' + bg2_variant); room->addStaticLayer(bg2, 3500); Common::String bg1 = Common::String::format( "r1010o%c0", 'e' + bg1_variant); room->addStaticLayer(bg1, 1000); } room->playMusicLoop("R1010eA0"); if (g_vm->getPreviousRoomId() == kMinosPalaceRoom) { room->panRightInstant(); if (persistent->_creteIntroMerchant) { room->disableMouse(); room->panLeftAnim(kIntroMerchantPanFinished); _merchantIsBusy = true; persistent->_creteIntroMerchant = false; } if (persistent->_creteIntroAtlantisBoat) { persistent->_creteIntroAtlantisBoat = false; room->disableMouse(); room->playVideo("r1180ba0", 0, 12134, Common::Point(640, 216)); } } if (quest == kMedusaQuest && persistent->_medisleShowFates) { switch (persistent->_creteSandalsState) { case Persistent::SANDALS_NOT_SOLVED: for (int i = 0; i < 4; i++) room->enableHotzone(Common::String::format("VaseSegment%d", i + 1)); _vasePos[0] = (g_vm->getRnd().getRandomNumberRng(1, 3) + 2) % 4; _vasePos[1] = (g_vm->getRnd().getRandomNumberRng(1, 5) + 3) % 6; _vasePos[2] = (g_vm->getRnd().getRandomNumberRng(1, 5) + 2) % 6; _vasePos[3] = (g_vm->getRnd().getRandomNumberRng(1, 3) + 3) % 4; renderVase(); break; case Persistent::SANDALS_SOLVED: showSandals(); break; case Persistent::SANDALS_TAKEN: room->selectFrame("r1220ba0", 500, 0); break; } } switch (persistent->_quest) { case kCreteQuest: if (!persistent->_roomVisited[kMinosPalaceRoom]) { room->playVideo("r1260ma0", 0); break; } if (persistent->_creteShowMerchant) { room->playVideo("g0261ma0", 0); break; } break; case kMedusaQuest: if (persistent->_medisleShowFates && persistent->_creteSandalsState == Persistent::SANDALS_NOT_SOLVED) room->playVideo("r1220ma0", 0); break; case kRescuePhilQuest: if (persistent->_creteStrongBoxState == Persistent::BOX_CLOSED || persistent->_creteStrongBoxState == Persistent::BOX_OPEN) room->playVideo("r2230ma0", 0); break; // To silence warning case kTroyQuest: case kNoQuest: case kEndGame: case kNumQuests: break; } if (!persistent->_creteSaidHelenPermanentResident && persistent->_quest == kTroyQuest) { persistent->_creteSaidHelenPermanentResident = true; room->disableMouse(); room->playVideo("r1250ba0", 0, 12134, Common::Point(0, 216)); } } void frameCallback() override { if (_strongBoxPopup && strongBoxIsBusy()) redrawStrongBox(); if (_fadingHades) { Common::SharedPtr room = g_vm->getVideoRoom(); int val = (256 * (g_vm->getCurrentTime() - _fadingHadesStartTime)) / 2000; if (val >= 256) { _fadingHades = false; val = 256; handleEvent(12125); } room->setColorScale("r2035pa0", 256 - val); } } private: void showMiniStrongBox() { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); if (persistent->_quest != kRescuePhilQuest) return; switch(persistent->_creteStrongBoxState) { case Persistent::BOX_CLOSED: room->enableHotzone("StrongBoxClosed"); room->selectFrame("r2010ba0", 5000, 0, kOffsetRightRoom); break; case Persistent::BOX_OPEN: room->enableHotzone("StrongBoxOpen"); room->selectFrame("r2010ba0", 5000, 1, kOffsetRightRoom); break; case Persistent::BOX_OPEN_POTION: room->enableHotzone("StrongBoxOpenPotion"); room->selectFrame("r2010ba0", 5000, 2, kOffsetRightRoom); break; case Persistent::BOX_OPEN_NO_POTION: room->enableHotzone("StrongBoxOpenNoPotion"); room->selectFrame("r2010ba0", 5000, 3, kOffsetRightRoom); break; } } AmbientAnim ambient(const Common::String &anim, const Common::String &sound, int zValue, int minint, int maxint, AmbientAnim::PanType pan, Common::Point offset = Common::Point(0,0), bool loop = true) { AmbientAnim ret = AmbientAnim(anim, sound, zValue, minint * 1000, maxint * 1000, loop ? AmbientAnim::KEEP_LOOP : AmbientAnim::DISAPPEAR, offset, pan); ret.start(); return ret; } bool randomBool() const { return g_vm->getRnd().getRandomBit(); } void renderAtlantisDisks() { Common::SharedPtr room = g_vm->getVideoRoom(); room->selectFrame(kAtlantisLargeDisk, kAtlantisLargeDiskZ, _atlantisBoatPosition[0]); room->selectFrame(kAtlantisMediumDisk, kAtlantisMediumDiskZ, _atlantisBoatPosition[1]); room->selectFrame(kAtlantisSmallDisk, kAtlantisSmallDiskZ, _atlantisBoatPosition[2]); } void advanceAtlantisDisk(int diskNum) { Common::SharedPtr room = g_vm->getVideoRoom(); _atlantisBoatPosition[diskNum] = (_atlantisBoatPosition[diskNum] + 1) % 8; renderAtlantisDisks(); room->playSFX(Common::String::format("r1210e%c0", 'e' + diskNum), 12303 + diskNum); } void hideAtlantisPopupOverlays() { Common::SharedPtr room = g_vm->getVideoRoom(); room->stopAnim(kAtlantisLargeDisk); room->stopAnim(kAtlantisMediumDisk); room->stopAnim(kAtlantisSmallDisk); room->stopAnim(kAtlantisDiskBackground); } void renderVase() { Common::SharedPtr room = g_vm->getVideoRoom(); for(int i = 0; i < 4; i++) room->selectFrame(vaseSegment[i], 1000, _vasePos[i]); } void showSandals() { Common::SharedPtr room = g_vm->getVideoRoom(); room->playAnim("r1220ba0", 500, PlayAnimParams::loop().partial(9, 17)); room->enableHotzone("sandals"); } void showStrongBox() { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); // User already clicked, no need to play that anim persistent->_cretePlayedZeusCheckOutThatBox = true; room->pushHotZones("Box.Hot"); room->playSFX("g0082ea0"); redrawStrongBox(); _strongBoxPopup = true; switch(persistent->_creteStrongBoxState) { case Persistent::BOX_CLOSED: room->selectFrame("r2230bb0", 1000, 1, kOffsetRightRoom); break; case Persistent::BOX_OPEN: room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom); break; case Persistent::BOX_OPEN_POTION: room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom); room->selectFrame("r2230bf0", 300, -2, kOffsetRightRoom); break; case Persistent::BOX_OPEN_NO_POTION: room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom); room->selectFrame("r2230bf0", 300, -1, kOffsetRightRoom); break; } } void hideStrongBox() { Common::SharedPtr room = g_vm->getVideoRoom(); room->stopAnim("r2230bb0"); room->stopAnim("r2230bf0"); for (int i = 0; i < 12; i++) room->stopAnim(LayerId("r2010om0", i, "pos")); room->stopAnim(LayerId("r2010om1", 0, "center")); for (int i = 0; i < 4; i++) { room->stopAnim(LayerId("r2010om1", i, "side")); } _strongBoxPopup = false; } void redrawStrongBox() { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); room->setHotzoneEnabled("Potion", persistent->_creteStrongBoxState == Persistent::BOX_OPEN_POTION); room->setHotzoneEnabled("Latch", persistent->_creteStrongBoxState == Persistent::BOX_CLOSED); room->setHotzoneEnabled("ButtonN", persistent->_creteStrongBoxState == Persistent::BOX_OPEN); room->setHotzoneEnabled("ButtonS", persistent->_creteStrongBoxState == Persistent::BOX_OPEN); room->setHotzoneEnabled("ButtonE", persistent->_creteStrongBoxState == Persistent::BOX_OPEN); room->setHotzoneEnabled("ButtonW", persistent->_creteStrongBoxState == Persistent::BOX_OPEN); room->setHotzoneEnabled("ButtonC", persistent->_creteStrongBoxState == Persistent::BOX_OPEN); switch(persistent->_creteStrongBoxState) { case Persistent::BOX_CLOSED: break; case Persistent::BOX_OPEN: room->selectFrame(LayerId("r2010om1", 0, "center"), 400, 0, Common::Point(1060, 308)); for (int i = 0; i < 4; i++) { room->selectFrame(LayerId("r2010om1", i, "side"), 400, 1, strongBoxSideDotOffsets[i].get()); } { bool wasMoving = strongBoxIsBusy(); for (int i = 0; i < 12; i++) { _strongBoxTiles[i].show(); } if (wasMoving && !strongBoxIsBusy()) { strongBoxCheckSolution(); } } break; case Persistent::BOX_OPEN_POTION: case Persistent::BOX_OPEN_NO_POTION: room->selectFrame(LayerId("r2010om1", 0, "center"), 400, 0, Common::Point(1060, 308)); for (int i = 0; i < 4; i++) { room->selectFrame(LayerId("r2010om1", i, "side"), 400, 1, strongBoxSideDotOffsets[i].get()); } for (int i = 0; i < 12; i++) { _strongBoxTiles[i].show(); } break; } } bool strongBoxIsBusy() { for (int i = 0; i < 12; i++) { if (_strongBoxTiles[i].isMoving()) { return true; } } return false; } void strongBoxCheckSolution() { Common::SharedPtr room = g_vm->getVideoRoom(); Persistent *persistent = g_vm->getPersistent(); bool zOk = false, eOk = false, uOk = false, sOk = false; for (int i = 0; i < 12; i++) { if (_strongBoxTiles[i].getPosition() == 0 && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterZ && (_strongBoxTiles[i].getOrientation() == 0 || _strongBoxTiles[i].getOrientation() == 180)) zOk = true; if (_strongBoxTiles[i].getPosition() == 1 && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterE && _strongBoxTiles[i].getOrientation() == 0) eOk = true; if (_strongBoxTiles[i].getPosition() == 2 && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterU && _strongBoxTiles[i].getOrientation() == 0) uOk = true; if (_strongBoxTiles[i].getPosition() == 3 && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterS && (_strongBoxTiles[i].getOrientation() == 0 || _strongBoxTiles[i].getOrientation() == 180)) sOk = true; } if (zOk && eOk && uOk && sOk) { persistent->_creteStrongBoxState = Persistent::BOX_OPEN_POTION; room->disableMouse(); room->enableHotzone("Potion"); room->disableHotzone("ButtonS"); room->disableHotzone("ButtonN"); room->disableHotzone("ButtonE"); room->disableHotzone("ButtonW"); room->disableHotzone("ButtonC"); room->playAnimWithSFX("r2230bf0", "r2230ea0", 300, PlayAnimParams::keepLastFrame().partial(0, -2), 12414, kOffsetRightRoom); } } void strongBoxMoveTiles(int p1, int p2, int p3, int p4) { Common::SharedPtr room = g_vm->getVideoRoom(); room->playSFX("r2230ee0"); for (int i = 0; i < 12; i++) { int pos = _strongBoxTiles[i].getPosition(); if (pos == p1) _strongBoxTiles[i].moveTo(p2); if (pos == p2) _strongBoxTiles[i].moveTo(p3); if (pos == p3) _strongBoxTiles[i].moveTo(p4); if (pos == p4) _strongBoxTiles[i].moveTo(p1); } } bool _fadingHades; int _fadingHadesStartTime; int _tavernCounter; int _oneManBandCounter; int _atlantisBoatPosition[3]; bool _merchantIsBusy; int _vasePos[4]; bool _vaseBusy[4]; bool _strongBoxPopup; StrongBoxTile _strongBoxTiles[12]; Common::Array _tavernTalks; AmbientAnim _alchemistAmbient; }; Common::SharedPtr makeCreteHandler() { return Common::SharedPtr(new CreteHandler()); } }