1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * Copyright 2020 Google
22  *
23  */
24 #include "hadesch/hadesch.h"
25 #include "hadesch/video.h"
26 #include "hadesch/ambient.h"
27 #include "common/translation.h"
28 
29 namespace Hadesch {
30 
31 static const char *kTalusImage = "r1100bb0";
32 static const char *kTalusImageWithShip = "r1100bc0";
33 static const char *kTalusMovie = "r1100ba0";
34 static const char *kTalusHotzone = "Talus";
35 static const char *kTavernImage = "r2190ba0";
36 static const char *kTavernHotzone = "Tavern";
37 static const char *kPoseidonHighlight = "r1230ba0";
38 static const char *kZeusHighlight = "r1240ba0";
39 static const char *kHermesHighlight = "r2320ba0";
40 static const char *kHornless1 = "g0170ob0";
41 static const char *kHornless2 = "g0170oe0";
42 static const char *kHornless3 = "g0170oh0";
43 static const char *kHornless4 = "g0170ok0";
44 static const char *kHorned = "g1800ob0";
45 static const char *kHornedHotzone = "HornedStatue";
46 static const char *kHornless1Hotzone = "HornlessStatue1";
47 static const char *kHornless2Hotzone = "HornlessStatue2";
48 static const char *kHornless3Hotzone = "HornlessStatue3";
49 static const char *kHornless4Hotzone = "HornlessStatue4";
50 static const char *kMerchantAnim = "r2130ba0";
51 static const char *kOneManBandAnim = "r2040ba1";
52 static const char *kOneManBandHotZone = "OneManBand";
53 static const char *kAtlantisOpening = "r1210bb0";
54 static const char *kAtlantisLargeDisk = "r1210be0";
55 static const char *kAtlantisMediumDisk = "r1210bf0";
56 static const char *kAtlantisSmallDisk = "r1210bg0";
57 static const char *kAtlantisDiskBackground = "r1210os0";
58 
59 static const int vaseSol[] = {2, 3, 2, 3};
60 static const char *vaseSound[] = {
61 	"r1220ec0",
62 	"r1220ed0",
63 	"r1220ee0",
64 	"r1220ef0"
65 };
66 
67 static const char *vaseSegment[] = {
68 	"r1220bc0",
69 	"r1220bd0",
70 	"r1220be0",
71 	"r1220bf0"
72 };
73 
74 enum {
75 	kBackgroundZ = 10000,
76 	kTalusZ = 6000,
77 	kTavernImageZ = 5000,
78 	kOneManBandZ = 1600,
79 	kMerchantStandZ = 1205,
80 	kMerchantZ = 1200,
81 	kAtlantisDiskBackgroundZ = 1100,
82 	kAtlantisLargeDiskZ = 1000,
83 	kAtlantisMediumDiskZ = 900,
84 	kAtlantisSmallDiskZ = 800,
85 	kAtlantisOpeningZ = 700
86 };
87 
88 enum {
89 	kIntroMerchantVideoFinished = 12107,
90 	kTakenHorned = 12115,
91 	kTakenHornless = 12118,
92 	kMerchantIdleTimer = 12121,
93 	kMerchantIdleAnimCleanup = 12122,
94 	kTalueMovieCompleted = 12129,
95 	// 12137 is the end of statue animation that we handle as functor instead
96 	kAtlantisDoorOpens = 12307,
97 	kTavernMovieCompleted = 1012001,
98 	kIntroMerchantPanFinished = 1012002,
99 	kAtlantisBoatIntro2Finished = 1012003,
100 	kTakenWood = 1012005,
101 	kSoundVaseSegment1Finished = 1012006,
102 	kSoundVaseSegment2Finished = 1012007,
103 	kSoundVaseSegment3Finished = 1012008,
104 	kSoundVaseSegment4Finished = 1012009,
105 	kCoinGiven = 1012010,
106 	kSandalsPlaced = 1012011
107 };
108 
109 static const PrePoint strongBoxSideDotOffsets[] = {
110 	{1060, 278},
111 	{1090, 310},
112 	{1060, 339},
113 	{1032, 305}
114 };
115 
116 static const PrePoint strongBoxTileOffsets[] = {
117 	{1005, 274},
118 	{1035, 276},
119 	{1064, 278},
120 	{1093, 280},
121 	{1005, 304},
122 	{1035, 306},
123 	{1064, 308},
124 	{1093, 310},
125 	{1035, 246},
126 	{1064, 248},
127 	{1035, 337},
128 	{1064, 339}
129 };
130 
131 static const int baseFrame[4][8] = {
132 	{  1,  3,  4,  6,  1,  3,  4,  6 },
133 	{  7,  9, 10, 12, 13, 15, 16, 18 },
134 	{ 19, 21, 22, 24, 25, 27, 28, 30 },
135 	{ 31, 33, 34, 36, 31, 33, 34, 36 }
136 };
137 
138 static const int kTileMovementTime = 500;
139 
140 class StrongBoxTile {
141 public:
142 	enum Letter {
143 		kLetterZ = 1,
144 		kLetterE,
145 		kLetterU,
146 		kLetterS
147 	};
148 	enum Orientation {
149 		kOrientation0 = 0,
150 		kOrientation90 = 90,
151 		kOrientation180 = 180,
152 		kOrientation270 = 270
153 	};
154 
rotate()155 	void rotate() {
156 		_orientation = (Orientation) ((_orientation + 90) % 360);
157 	}
158 
show()159 	void show() {
160 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
161 		int orientation = _orientation / 45;
162 		if (_nextPosition != -1 && g_vm->getCurrentTime() > kTileMovementTime + _movementStartTime) {
163 			_position = _nextPosition;
164 			_nextPosition = -1;
165 		}
166 		Common::Point pos = strongBoxTileOffsets[_position].get();
167 		if (_nextPosition != -1) {
168 			double frac = (g_vm->getCurrentTime() - _movementStartTime + 0.0) / kTileMovementTime;
169 			pos = strongBoxTileOffsets[_position].get() * (1-frac) + strongBoxTileOffsets[_nextPosition].get() * frac;
170 		}
171 		int zVal = 500;
172 		switch (_rotationPhase) {
173 		case 0:
174 		case 2:
175 			pos += Common::Point(-5, 4);
176 			zVal = 300;
177 			break;
178 		case 1:
179 			orientation++;
180 			switch (_position) {
181 			case 1:
182 				pos = Common::Point(1046, 277);
183 				break;
184 			case 2:
185 				pos = Common::Point(1065, 298);
186 				break;
187 			case 5:
188 				pos = Common::Point(1025, 297);
189 				break;
190 			case 6:
191 				pos = Common::Point(1045, 318);
192 				break;
193 			}
194 			zVal = 300;
195 			break;
196 		}
197 		int frame = baseFrame[_letter - kLetterZ][orientation] - 1;
198 		if (_position < 4 && _nextPosition == -1 && _rotationPhase < 0)
199 			frame++;
200 		room->selectFrame(LayerId("r2010om0", _position, "pos"),
201 				  zVal, frame, pos);
202 	}
203 
setRotationPhase(int phase)204 	void setRotationPhase(int phase) {
205 		_rotationPhase = phase;
206 	}
207 
isMoving()208 	bool isMoving() {
209 		return _nextPosition != -1 || _rotationPhase != -1;
210 	}
211 
getPosition()212 	int getPosition() {
213 		return _position;
214 	}
215 
getLetter()216 	Letter getLetter() {
217 		return _letter;
218 	}
219 
getOrientation()220 	Orientation getOrientation() {
221 		return _orientation;
222 	}
223 
setPosition(int position)224 	void setPosition(int position) {
225 		_position = position;
226 	}
227 
moveTo(int pos)228 	void moveTo(int pos) {
229 		_nextPosition = pos;
230 		_movementStartTime = g_vm->getCurrentTime();
231 	}
232 
StrongBoxTile()233 	StrongBoxTile() {
234 		_letter = kLetterZ;
235 		_position = 0;
236 		_orientation = kOrientation0;
237 		_nextPosition = -1;
238 		_rotationPhase = -1;
239 	}
240 
StrongBoxTile(Letter letter,Orientation orientation,int position)241 	StrongBoxTile(Letter letter, Orientation orientation, int position) {
242 		_letter = letter;
243 		_position = position;
244 		_orientation = orientation;
245 		_nextPosition = -1;
246 		_rotationPhase = -1;
247 	}
248 private:
249 	Letter _letter;
250 	int _position;
251 	int _nextPosition;
252 	int _movementStartTime;
253 	int _rotationPhase;
254 	Orientation _orientation;
255 };
256 
257 static const struct {
258 	StrongBoxTile::Letter letter;
259 	StrongBoxTile::Orientation orientation;
260 } initialLetters[12] = {
261 	{StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation90},
262 	{StrongBoxTile::kLetterE, StrongBoxTile::kOrientation90},
263 	{StrongBoxTile::kLetterU, StrongBoxTile::kOrientation90},
264 	{StrongBoxTile::kLetterS, StrongBoxTile::kOrientation90},
265 	{StrongBoxTile::kLetterE, StrongBoxTile::kOrientation0},
266 	{StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation0},
267 	{StrongBoxTile::kLetterU, StrongBoxTile::kOrientation270},
268 	{StrongBoxTile::kLetterS, StrongBoxTile::kOrientation90},
269 	{StrongBoxTile::kLetterU, StrongBoxTile::kOrientation90},
270 	{StrongBoxTile::kLetterE, StrongBoxTile::kOrientation90},
271 	{StrongBoxTile::kLetterZ, StrongBoxTile::kOrientation0},
272 	{StrongBoxTile::kLetterS, StrongBoxTile::kOrientation0}
273 };
274 
275 class CreteHandler : public Handler {
276 public:
CreteHandler()277 	CreteHandler() {
278 		_tavernCounter = 0;
279 		_oneManBandCounter = 0;
280 		_merchantIsBusy = false;
281 		memset(_vaseBusy, 0, sizeof(_vaseBusy));
282 		for (int i =0; i < 12; i++)
283 			_strongBoxTiles[i] = StrongBoxTile(initialLetters[i].letter, initialLetters[i].orientation, i);
284 		_strongBoxPopup = false;
285 		_fadingHades = false;
286 		_fadingHadesStartTime = 0;
287 	}
288 
handleClick(const Common::String & name)289 	void handleClick(const Common::String &name) override {
290 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
291 		Persistent *persistent = g_vm->getPersistent();
292 		if (name == kTalusHotzone) {
293 			room->playVideo(kTalusMovie, kTalusZ, kTalueMovieCompleted,
294 					Common::Point(54, 29));
295 			room->setLayerEnabled(kTalusImageWithShip, false);
296 			return;
297 		}
298 
299 		if (name == "MinosPalace") {
300 			room->disableMouse();
301 			g_vm->moveToRoom(kMinosPalaceRoom);
302 			return;
303 		}
304 
305 		if (name == "Poseidon") {
306 			Common::Array<Common::String> videos;
307 			videos.push_back("r1230na0");
308 			videos.push_back("r1230nb0");
309 			videos.push_back("r1230nc0");
310 
311 			room->playStatueSMK(kPoseidonStatue,
312 					    kPoseidonHighlight,
313 					    5000,
314 					    videos, 16, 39);
315 			return;
316 		}
317 
318 		if (name == "Zeus") {
319 			Common::Array<Common::String> videos;
320 			videos.push_back("r1240wa0");
321 			videos.push_back("r1240wb0");
322 
323 			room->playStatueSMK(kZeusStatue, kZeusHighlight, 5000,
324 					    videos, 23, 35);
325 			return;
326 		}
327 
328 		if (name == "Hermes") {
329 			Common::Array<Common::String> videos;
330 			videos.push_back("r2320na0");
331 			videos.push_back("r2320nb0");
332 
333 			room->playStatueSMK(kHermesStatue,
334 					    kHermesHighlight,
335 					    4000,
336 					    videos, 22, 39, kOffsetRightRoom);
337 			return;
338 		}
339 
340 		if (name == kTavernHotzone) {
341 			room->playAnimLoop(kTavernImage, 5000, kOffsetRightRoom);
342 			room->playVideo(_tavernTalks[_tavernCounter], 5000,
343 					   kTavernMovieCompleted,
344 					   kOffsetRightRoom);
345 			_tavernCounter = (_tavernCounter + 1) % _tavernTalks.size();
346 			return;
347 		}
348 
349 		if (name == "Argo") {
350 			g_vm->moveToRoom(kArgoRoom);
351 			return;
352 		}
353 
354 		if (name == kHornedHotzone) {
355 			g_vm->getHeroBelt()->placeToInventory(kHornedStatue, kTakenHornless);
356 			room->setLayerEnabled(kHorned, false);
357 			persistent->_creteShowHorned = false;
358 			_merchantIsBusy = true;
359 			room->disableHotzone(kHornedHotzone);
360 			room->disableMouse();
361 			return;
362 		}
363 
364 		if (name == kHornless1Hotzone) {
365 			g_vm->getHeroBelt()->placeToInventory(kHornlessStatue1, kTakenHorned);
366 			room->setLayerEnabled(kHornless1, false);
367 			persistent->_creteShowHornless1 = false;
368 			room->disableHotzone(kHornless1Hotzone);
369 			_merchantIsBusy = true;
370 			room->disableMouse();
371 			return;
372 		}
373 
374 		if (name == kHornless2Hotzone) {
375 			g_vm->getHeroBelt()->placeToInventory(kHornlessStatue2, kTakenHorned);
376 			room->setLayerEnabled(kHornless2, false);
377 			persistent->_creteShowHornless2 = false;
378 			room->disableHotzone(kHornless2Hotzone);
379 			_merchantIsBusy = true;
380 			room->disableMouse();
381 			return;
382 		}
383 
384 		if (name == kHornless3Hotzone) {
385 			g_vm->getHeroBelt()->placeToInventory(kHornlessStatue3, kTakenHorned);
386 			room->setLayerEnabled(kHornless3, false);
387 			persistent->_creteShowHornless3 = false;
388 			room->disableHotzone(kHornless3Hotzone);
389 			_merchantIsBusy = true;
390 			room->disableMouse();
391 			return;
392 		}
393 
394 		if (name == kHornless4Hotzone) {
395 			g_vm->getHeroBelt()->placeToInventory(kHornlessStatue4, kTakenHorned);
396 			room->setLayerEnabled(kHornless4, false);
397 			persistent->_creteShowHornless4 = false;
398 			room->disableHotzone(kHornless4Hotzone);
399 			_merchantIsBusy = true;
400 			room->disableMouse();
401 			return;
402 		}
403 
404 		if (name == kOneManBandHotZone) {
405 			room->playVideo(
406 				Common::String::format(
407 					"r2040b%c0", 'a' + (_oneManBandCounter % 3)),
408 				1600,
409 				12135, Common::Point(730, 183));
410 			room->stopAnim(kOneManBandAnim);
411 			_oneManBandCounter++;
412 			return;
413 		}
414 
415 		if (name == "AtlantisBoat") {
416 			room->pushHotZones("Door.HOT");
417 			room->disableHotzone("wood");
418 			room->selectFrame("r1010ob0", 1200, 0);
419 			room->selectFrame(kAtlantisDiskBackground, kAtlantisDiskBackgroundZ, 0);
420 			for (unsigned i = 0; i < 3; i++)
421 				_atlantisBoatPosition[i] = g_vm->getRnd().getRandomNumberRng(1, 7);
422 			renderAtlantisDisks();
423 			if (persistent->_creteIntroAtlantisWood) {
424 				room->disableMouse();
425 				room->playVideo("R1210BA0", 600, kAtlantisBoatIntro2Finished);
426 				persistent->_creteIntroAtlantisWood = false;
427 			}
428 			return;
429 
430 		}
431 
432 		if (name == "SmallDisk") {
433 			advanceAtlantisDisk(2);
434 			return;
435 		}
436 
437 		if (name == "MediumDisk") {
438 			advanceAtlantisDisk(1);
439 			return;
440 		}
441 
442 		if (name == "LargeDisk") {
443 			advanceAtlantisDisk(0);
444 			return;
445 		}
446 
447 		if (name == "wood") {
448 			room->selectFrame(kAtlantisOpening, kAtlantisOpeningZ, 9);
449 			g_vm->getHeroBelt()->placeToInventory(kWood, kTakenWood);
450 			room->popHotZones();
451 			room->disableHotzone("AtlantisBoat");
452 			persistent->_creteShowAtlantisBoat = false;
453 			return;
454 		}
455 
456 		if (name == "Background") {
457 			room->popHotZones();
458 			room->stopAnim("r1010ob0");
459 			hideStrongBox();
460 			hideAtlantisPopupOverlays();
461 			showMiniStrongBox();
462 			return;
463 		}
464 
465 		for (int i = 0; i < 4; i++) {
466 			if (name == Common::String::format("VaseSegment%d", i + 1) && !_vaseBusy[i]) {
467 				_vasePos[i]++;
468 				if (i == 1 || i == 3)
469 					_vasePos[i] %= 6;
470 				else
471 					_vasePos[i] %= 4;
472 				_vaseBusy[i] = true;
473 				renderVase();
474 				room->playSFX(vaseSound[i], kSoundVaseSegment1Finished + i);
475 				return;
476 			}
477 		}
478 
479 		if (name == "sandals") {
480 			g_vm->getHeroBelt()->placeToInventory(kSandals, kSandalsPlaced);
481 			room->selectFrame("r1220ba0", 500, 0);
482 			room->disableMouse();
483 			persistent->_creteSandalsState = Persistent::SANDALS_TAKEN;
484 			return;
485 		}
486 
487 		if (name == "AlchemistStand") {
488 			_alchemistAmbient.play(false);
489 			return;
490 		}
491 
492 		if (name == "StrongBoxClosed"
493 			|| name == "StrongBoxOpen"
494 			|| name == "StrongBoxOpenPotion"
495 			|| name == "StrongBoxOpenNoPotion") {
496 			showStrongBox();
497 			return;
498 		}
499 
500 		if (name == "Latch") {
501 			room->disableMouse();
502 			persistent->_creteStrongBoxState = Persistent::BOX_OPEN;
503 			room->playAnimWithSFX("r2230bb0", "g0082ea0", 1000,
504 					      PlayAnimParams::keepLastFrame().partial(1, 3),
505 					      12402, kOffsetRightRoom);
506 			return;
507 		}
508 
509 		if (name == "ButtonN" && !strongBoxIsBusy()) {
510 			strongBoxMoveTiles(1, 8, 9, 2);
511 			return;
512 		}
513 
514 		if (name == "ButtonE" && !strongBoxIsBusy()) {
515 			strongBoxMoveTiles(2, 3, 7, 6);
516 			return;
517 		}
518 
519 		if (name == "ButtonW" && !strongBoxIsBusy()) {
520 			strongBoxMoveTiles(1, 5, 4, 0);
521 			return;
522 		}
523 
524 		if (name == "ButtonS" && !strongBoxIsBusy()) {
525 			strongBoxMoveTiles(5, 6, 11, 10);
526 			return;
527 		}
528 
529 		if (name == "ButtonC" && !strongBoxIsBusy()) {
530 			g_vm->addTimer(12409, 250);
531 			room->playSFX("r2230ed0", 12412);
532 			for (int i = 0; i < 12; i++) {
533 				int pos = _strongBoxTiles[i].getPosition();
534 				if (pos == 1 || pos == 2 || pos == 5 || pos == 6) {
535 					_strongBoxTiles[i].setRotationPhase(0);
536 				}
537 			}
538 			return;
539 		}
540 
541 		if (name == "Potion") {
542 			room->disableHotzone("Potion");
543 			g_vm->getHeroBelt()->placeToInventory(kCoin, kCoinGiven);
544 			persistent->_creteStrongBoxState = Persistent::BOX_OPEN_NO_POTION;
545 			room->selectFrame("r2230bf0", 300, -1, kOffsetRightRoom);
546 			return;
547 		}
548 		/*
549 TODO:
550  MNSH: Merchant
551 */
552 	}
553 
handleEvent(int eventId)554 	void handleEvent(int eventId) override {
555 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
556 		Persistent *persistent = g_vm->getPersistent();
557 		switch (eventId) {
558 		case kTakenWood:
559 			room->stopAnim(kAtlantisOpening);
560 			room->stopAnim("r1010ob0");
561 			room->stopAnim(kAtlantisDiskBackground);
562 			room->enableMouse();
563 			break;
564 		case kTalueMovieCompleted:
565 			room->setLayerEnabled(kTalusImageWithShip, true);
566 			break;
567 		case kTavernMovieCompleted:
568 			room->selectFrame(kTavernImage, kTavernImageZ, 0, kOffsetRightRoom);
569 			break;
570 		case kMerchantIdleTimer:
571 			if (!persistent->_creteShowMerchant
572 			    || !persistent->_creteShowHornless4 || _merchantIsBusy)
573 				break;
574 			room->setLayerEnabled(kHornless4, false);
575 			room->disableHotzone(kHornless4Hotzone);
576 			room->playAnim(kMerchantAnim, kMerchantZ,
577 				       PlayAnimParams::disappear().partial(1, -2),
578 				       kMerchantIdleAnimCleanup);
579 			break;
580 		case kMerchantIdleAnimCleanup:
581 			room->selectFrame(kMerchantAnim, kMerchantZ, 0);
582 			room->setLayerEnabled(kHornless4, persistent->_creteShowHornless4);
583 			room->setHotzoneEnabled(kHornless4Hotzone, persistent->_creteShowHornless4 && persistent->_creteTriedHornless[2]);
584 			break;
585 		case kIntroMerchantPanFinished:
586 			room->setLayerEnabled(kMerchantAnim, false);
587 			room->playVideo("R2200BA0", kMerchantZ,
588 					kIntroMerchantVideoFinished,
589 					Common::Point(308, 99));
590 			break;
591 		// TODO: replay of R2200BB0 and R2200BC0
592 		case kIntroMerchantVideoFinished:
593 			room->disableMouse();
594 			room->playVideo("R2200BB0", kMerchantZ,
595 					12108,
596 					Common::Point(304, 113));
597 			_merchantIsBusy = true;
598 			break;
599 		case 12108:
600 			room->disableMouse();
601 			room->playVideo("R2200BC0", kMerchantZ,
602 					12109,
603 					Common::Point(304, 110));
604 			_merchantIsBusy = true;
605 			break;
606 		case 12109:
607 			room->selectFrame(kMerchantAnim, kMerchantZ, 0);
608 			room->enableMouse();
609 			_merchantIsBusy = false;
610 			break;
611 		case kTakenHorned:
612 			room->setLayerEnabled(kMerchantAnim, false);
613 			room->playVideo("r2210ba0", kMerchantZ, 12117,
614 					Common::Point(344, 111));
615 			room->disableMouse();
616 			break;
617 		case 12117:
618 			room->playVideo("r2210bb0", kMerchantZ, 12119,
619 				Common::Point(308, 112));
620 			break;
621 		case kTakenHornless:
622 			room->setLayerEnabled(kMerchantAnim, false);
623 			room->playVideo("r2240ba0", kMerchantZ, 12119,
624 				Common::Point(314, 91));
625 			_merchantIsBusy = true;
626 			break;
627 		case 12119:
628 			room->selectFrame(kMerchantAnim, kMerchantZ, 0);
629 			if (!persistent->_cretePlayedEyeGhostTown) {
630 				room->playVideo("r2210bc0", 1000, 12120,
631 						   Common::Point(0, 216));
632 				persistent->_cretePlayedEyeGhostTown = true;
633 			} else {
634 				room->enableMouse();
635 				_merchantIsBusy = false;
636 			}
637 			break;
638 		case 12120:
639 			room->selectFrame(kMerchantAnim, kMerchantZ, 0);
640 			room->enableMouse();
641 			_merchantIsBusy = false;
642 			break;
643 		case 12128:
644 		case 12134:
645 		case 12143:
646 		case 12146:
647 			room->enableMouse();
648 			break;
649 		case 12135:
650 			room->playAnimLoop(kOneManBandAnim, kOneManBandZ, kOffsetRightRoom);
651 			break;
652 		case 12142:
653 			if (persistent->_quest == kMedusaQuest && !persistent->_cretePlayedPhilAlchemist) {
654 				persistent->_cretePlayedPhilAlchemist = true;
655 				room->playVideo("r2220bc0", 1000, 12143, Common::Point(640, 216));
656 				room->disableMouse();
657 			}
658 			if (persistent->_quest == kRescuePhilQuest && !persistent->_cretePlayedZeusCheckOutThatBox && persistent->_hintsAreEnabled) {
659 				g_vm->addTimer(12144, 5000, -1);
660 			}
661 			break;
662 		case 12144:
663 			if (!room->isMouseEnabled() || persistent->_cretePlayedZeusCheckOutThatBox)
664 				break;
665 			persistent->_cretePlayedZeusCheckOutThatBox = true;
666 			room->disableMouse();
667 			room->playAnimWithSpeech("r2230ba0",
668 						TranscribedSound::make("r2230wa0",
669 								 "Hey, why don't you check out that box? Maybe it has something that can help"),
670 						4000,
671 						PlayAnimParams::keepLastFrame(),
672 						12145,
673 						kOffsetRightRoom);
674 			break;
675 		case kAtlantisBoatIntro2Finished:
676 			room->enableMouse();
677 			break;
678 		case kAtlantisDoorOpens:
679 			room->disableHotzone("LargeDisk");
680 			room->disableHotzone("MediumDisk");
681 			room->disableHotzone("SmallDisk");
682 			room->disableHotzone("Background");
683 			room->enableHotzone("wood");
684 			room->playVideo("r1210bd0", 600, 12308);
685 			break;
686 		case 12308:
687 			room->enableMouse();
688 			break;
689 		case kSoundVaseSegment1Finished:
690 		case kSoundVaseSegment2Finished:
691 		case kSoundVaseSegment3Finished:
692 		case kSoundVaseSegment4Finished: {
693 			int vase = eventId - kSoundVaseSegment1Finished;
694 			bool won = true;
695 			_vaseBusy[vase] = false;
696 			for (int i = 0; i < 4; i++) {
697 				if (_vaseBusy[i])
698 					won = false;
699 			}
700 
701 			for (int i = 0; i < 4; i++) {
702 				if (_vasePos[i] != vaseSol[i])
703 					won = false;
704 			}
705 
706 			if (!won)
707 				break;
708 
709 			for (int i = 0; i < 4; i++)
710 				room->stopAnim(vaseSegment[i]);
711 
712 			for (int i = 0; i < 4; i++)
713 				room->disableHotzone(Common::String::format("VaseSegment%d", i + 1));
714 
715 			room->playAnim("r1220ba0", 500,
716 				       PlayAnimParams::disappear().partial(0, 17), 12206);
717 			room->playVideo("r1220mb0", 0);
718 			room->playSFX("r1220ea0");
719 			room->disableMouse();
720 			break;
721 		}
722 		case 12206:
723 			showSandals();
724 			persistent->_creteSandalsState = Persistent::SANDALS_SOLVED;
725 			room->enableMouse();
726 			break;
727 		case 12303:
728 		case 12304:
729 		case 12305:
730 			if (_atlantisBoatPosition[0] == 0
731 			    && _atlantisBoatPosition[1] == 0
732 			    && _atlantisBoatPosition[2] == 0) {
733 				handleEvent(12306);
734 			}
735 			break;
736 		case 12306:
737 			room->disableMouse();
738 			hideAtlantisPopupOverlays();
739 			room->playAnimWithSFX(kAtlantisOpening, "r1210eb0", kAtlantisOpeningZ,
740 						PlayAnimParams::keepLastFrame().partial(0, 8),
741 						kAtlantisDoorOpens);
742 			break;
743 		case 12402:
744 			room->enableMouse();
745 			redrawStrongBox();
746 			// Fallthrough
747 		case 12403:
748 			room->disableMouse();
749 			room->playAnimWithSpeech("r2230ba0",
750 						 TranscribedSound::make("r2230wb0", "I think those buttons control the symbols"),
751 						 4000,
752 						 PlayAnimParams::keepLastFrame(), 12404,
753 						 kOffsetRightRoom);
754 			break;
755 		case 12404:
756 		case 12405:
757 			if (persistent->_hintsAreEnabled)
758 				g_vm->addTimer(12406, 5000);
759 			// Fallthrough
760 		case 12407:
761 		case 12408:
762 		case 12145:
763 			room->playAnim("r2230ba0", 4000, PlayAnimParams::disappear().backwards(), -1,
764 				       kOffsetRightRoom);
765 			room->enableMouse();
766 			break;
767 		case 12406:
768 			if (!room->isMouseEnabled())
769 				break;
770 			room->disableMouse();
771 			room->playAnimWithSpeech("r2230ba0",
772 						 TranscribedSound::make("r2230wc0", "Try to spell my name"),
773 						 4000,
774 						 PlayAnimParams::keepLastFrame(), 12407,
775 						 kOffsetRightRoom);
776 			break;
777 		case 12409:
778 			for (int i = 0; i < 12; i++) {
779 				int pos = _strongBoxTiles[i].getPosition();
780 				if (pos == 1 || pos == 2 || pos == 5 || pos == 6) {
781 					_strongBoxTiles[i].setRotationPhase(1);
782 				}
783 			}
784 			g_vm->addTimer(12410, 250);
785 			break;
786 		case 12410:
787 			for (int i = 0; i < 12; i++) {
788 				int pos = _strongBoxTiles[i].getPosition();
789 				if (pos == 1 || pos == 2 || pos == 5 || pos == 6) {
790 					_strongBoxTiles[i].setRotationPhase(2);
791 					_strongBoxTiles[i].rotate();
792 					switch (pos) {
793 					case 1:
794 						_strongBoxTiles[i].setPosition(2);
795 						break;
796 					case 2:
797 						_strongBoxTiles[i].setPosition(6);
798 						break;
799 					case 5:
800 						_strongBoxTiles[i].setPosition(1);
801 						break;
802 					case 6:
803 						_strongBoxTiles[i].setPosition(5);
804 						break;
805 					}
806 				}
807 			}
808 			g_vm->addTimer(12411, 250);
809 			break;
810 		case 12411:
811 			for (int i = 0; i < 12; i++) {
812 				_strongBoxTiles[i].setRotationPhase(-1);
813 			}
814 			redrawStrongBox();
815 			break;
816 		case 12414:
817 			room->playVideo("v4190ma0", 0, 12415);
818 			break;
819 		case 12204:
820 		case 12415:
821 			room->enableMouse();
822 			break;
823 		case kCoinGiven:
824 			g_vm->getHeroBelt()->placeToInventory(kPotion);
825 			break;
826 		case 12124:
827 			_fadingHades = true;
828 			_fadingHadesStartTime = g_vm->getCurrentTime();
829 			break;
830 		case 12125:
831 			room->stopAnim("r2035ba0");
832 			room->playVideo("R2035BE0", 1200, 12127);
833 			break;
834 		case 12127:
835 			g_vm->moveToRoom(kDaedalusRoom);
836 			break;
837 		case kSandalsPlaced:
838 			room->playVideo("r1220bb0", 0, 12204);
839 			break;
840 		}
841 	}
842 
prepareRoom()843 	void prepareRoom() override {
844 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
845 		Persistent *persistent = g_vm->getPersistent();
846 		Quest quest = persistent->_quest;
847 
848 		if (persistent->_creteHadesPusnishesPainAndPanic) {
849 			room->disableHeroBelt();
850 			room->disableMouse();
851 			room->addStaticLayer("r2035pa0", kBackgroundZ); // background
852 			room->selectFrame("r2035ba0", 1200, 0);
853 
854 			// Originally event 12123
855 			room->playSpeech(TranscribedSound::make(
856 						      "r2035wa0",
857 						      "Seems the only thing I can count on you two for is target practice"), 12124);
858 			persistent->_creteHadesPusnishesPainAndPanic = false;
859 			return;
860 		}
861 
862 		room->loadHotZones("Crete.HOT", false);
863 		room->addStaticLayer("r1010pa0", kBackgroundZ); // background
864 		g_vm->getHeroBelt()->setColour(HeroBelt::kWarm);
865 
866 		if (quest != kMedusaQuest && quest != kRescuePhilQuest) {
867 			room->playAnimLoop("r2010oe0", 7000, kOffsetRightRoom);
868 			room->playAnimLoop("r2010tb0", 6500, kOffsetRightRoom);
869 		}
870 		room->playAnimLoop("r2010ta0", 7600, kOffsetRightRoom);
871 		room->playAnimLoop("r1120ba0", 5500);
872 		room->playAnimLoop("r1160ba0", 5000);
873 		room->playAnimLoop("r1170ba0", 5000);
874 
875 		room->selectFrame(kTavernImage, kTavernImageZ, 0, kOffsetRightRoom);
876 		room->enableMouse();
877 		room->setPannable(true);
878 		room->enableHotzone(kTavernHotzone);
879 		room->enableHotzone("Argo");
880 		room->enableHotzone("Hermes");
881 		room->enableHotzone("Zeus");
882 		room->enableHotzone("Poseidon");
883 		room->enableHotzone("MinosPalace");
884 		if (quest != kMedusaQuest && quest != kRescuePhilQuest) {
885 			room->enableHotzone("AlchemistStand");
886 		}
887 
888 		room->setUserPanCallback(-1, -1, 12140, 12142);
889 
890 		if (quest == kMedusaQuest && !persistent->_creteAlchemistExploded) {
891 			persistent->_creteAlchemistExploded = true;
892 			room->disableMouse();
893 			room->playAnimWithSFX("r1190ba0", "r1190ea0", 1005, PlayAnimParams::disappear(), 12128);
894 		}
895 
896 		if (quest == kRescuePhilQuest || quest == kMedusaQuest) {
897 			room->selectFrame("r2010op0", 7500, 0, kOffsetRightRoom);
898 		}
899 
900 		if (quest == kMedusaQuest) {
901 			room->playAnimWithSFX("r2220bb0", "r2220eb0", 4500, PlayAnimParams::loop(), -1, kOffsetRightRoom);
902 		}
903 
904 		showMiniStrongBox();
905 
906 		switch (quest) {
907 		case kCreteQuest:
908 			_tavernTalks.push_back("r2250xa0");
909 			_tavernTalks.push_back("r2250xb0");
910 			_tavernTalks.push_back("r2250xc0");
911 			_tavernTalks.push_back("r2250xd0");
912 			_tavernTalks.push_back("r2250xe0");
913 			_tavernTalks.push_back("r2250xf0");
914 			_tavernTalks.push_back("r2220xa0");
915 			_tavernTalks.push_back("r2220xb0");
916 			_tavernTalks.push_back("r2220xc0");
917 			_tavernTalks.push_back("r2220xd0");
918 			_tavernTalks.push_back("r2220xe0");
919 			_tavernTalks.push_back("r2220xf0");
920 			break;
921 		case kTroyQuest:
922 			_tavernTalks.push_back("r2260xa0");
923 			_tavernTalks.push_back("r2260xb0");
924 			_tavernTalks.push_back("r2195xa0");
925 			_tavernTalks.push_back("r2195xb0");
926 			_tavernTalks.push_back("r2290xf0");
927 			_tavernTalks.push_back("r2220xa0");
928 			_tavernTalks.push_back("r2220xb0");
929 			_tavernTalks.push_back("r2220xc0");
930 			_tavernTalks.push_back("r2220xd0");
931 			_tavernTalks.push_back("r2220xe0");
932 			_tavernTalks.push_back("r2220xf0");
933 			break;
934 		case kMedusaQuest:
935 			_tavernTalks.push_back("r2270xa0");
936 			_tavernTalks.push_back("r2270xb0");
937 			_tavernTalks.push_back("r2290xg0");
938 			_tavernTalks.push_back("r2290xh0");
939 			_tavernTalks.push_back("r2290xi0");
940 			_tavernTalks.push_back("r2290xj0");
941 			_tavernTalks.push_back("r2290xk0");
942 			_tavernTalks.push_back("r2290xl0");
943 			break;
944 		case kRescuePhilQuest:
945 			_tavernTalks.push_back("r2280xa0");
946 			_tavernTalks.push_back("r2280xc0");
947 			_tavernTalks.push_back("r2280xd0");
948 			_tavernTalks.push_back("r2290xg0");
949 			_tavernTalks.push_back("r2290xh0");
950 			_tavernTalks.push_back("r2290xi0");
951 			_tavernTalks.push_back("r2290xj0");
952 			_tavernTalks.push_back("r2290xk0");
953 			_tavernTalks.push_back("r2290xl0");
954 			break;
955 
956 		// To silence warning
957 		case kNoQuest:
958 		case kEndGame:
959 		case kNumQuests:
960 			break;
961 		}
962 		_tavernTalks.push_back("r2290xa0");
963 		_tavernTalks.push_back("r2290xb0");
964 		_tavernTalks.push_back("r2290xc0");
965 		_tavernTalks.push_back("r2290xd0");
966 		_tavernTalks.push_back("r2290xe0");
967 
968 		int bg1_variant = -1;
969 		int bg2_variant = -1;
970 
971 		bool showOiBoat = false;
972 
973 		if (!persistent->_creteShowMerchant && (quest != kMedusaQuest || !persistent->_medisleShowFates)) {
974 			bg1_variant = g_vm->getRnd().getRandomNumberRng(0, 2);
975 			bg2_variant = g_vm->getRnd().getRandomNumberRng(0, 2);
976 			debug("BG variants %d and %d", bg1_variant, bg2_variant);
977 		}
978 
979 		if (randomBool()) {
980 			showOiBoat = true;
981 			room->addStaticLayer("r1010oi0", 4000);
982 		}
983 		if (randomBool())
984 			room->addStaticLayer("r1010oj0", 4000);
985 		if (randomBool())
986 			room->addStaticLayer("r1010ok0", 4000);
987 		if (randomBool())
988 			room->addStaticLayer("r1010ol0", 4000);
989 		if (randomBool())
990 			room->addStaticLayer("r1010on0", 4001);
991 		if (randomBool())
992 			room->addStaticLayer("r1010oo0", 4000);
993 		if (randomBool())
994 			room->addStaticLayer("r1010op0", 4100);
995 		if (randomBool())
996 			room->addStaticLayer("r1010or0", 6500);
997 
998 		if (quest != kCreteQuest)
999 			persistent->_creteShowAtlantisBoat = false;
1000 
1001 		if (persistent->_creteShowAtlantisBoat) {
1002 			room->addStaticLayer("r1010od0", 3900);
1003 			room->addStaticLayer("r1010ta0", 3800);
1004 			room->enableHotzone("AtlantisBoat");
1005 		}
1006 
1007 		room->playAnimLoop("r1010om0", 3000);
1008 
1009 		int minotaurPosition = -1;
1010 		int toughGuyPosition = -1;
1011 		int womanSmellPosition = -1;
1012 		if (quest == kCreteQuest && !persistent->_creteShowMerchant && !persistent->_creteShowAtlantisBoat)
1013 			minotaurPosition = g_vm->getRnd().getRandomNumberRng(0, 3);
1014 
1015 		bool showCat = false;
1016 		bool showStatueMan = false;
1017 		bool showOldMan = false;
1018 		bool showBlondBoy = false;
1019 		bool showMotherAndKidSmall = false;
1020 		bool showMotherAndKid = false;
1021 		bool showManSelling = false;
1022 		bool showDrawinWithoutWoman = false;
1023 		bool showWomanDrawing = false;
1024 		bool showWomanGraffiti = false;
1025 		bool showGirlAndNut = false;
1026 		bool showOneManBand = false;
1027 		int ambientComposite = g_vm->getRnd().getRandomNumberRng(1, 8);
1028 		debug("Ambients from Composite %d selected. \n", ambientComposite);
1029 		switch (ambientComposite) {
1030 		case 1:
1031 			showGirlAndNut = true;
1032 			if (quest != kCreteQuest && quest != kTroyQuest) {
1033 				toughGuyPosition = 1;
1034 				break;
1035 			}
1036 			if (minotaurPosition == 1) {
1037 				if (randomBool())
1038 					toughGuyPosition = 0;
1039 				break;
1040 
1041 			}
1042 			if (persistent->_creteShowMerchant) {
1043 				showOneManBand = true;
1044 				showWomanGraffiti = true;
1045 				break;
1046 			}
1047 			if (randomBool()) {
1048 				toughGuyPosition = 0;
1049 				showOneManBand = true;
1050 				showWomanGraffiti = true;
1051 			}
1052 			else
1053 				toughGuyPosition = 1;
1054 			break;
1055 		case 2:
1056 			womanSmellPosition = g_vm->getRnd().getRandomNumberRng(0, 2);
1057 			showWomanDrawing = true;
1058 			showManSelling = true;
1059 			if (quest != kMedusaQuest && quest != kRescuePhilQuest)
1060 				showMotherAndKid = true;
1061 			showBlondBoy = true;
1062 			break;
1063 		case 3:
1064 			if (quest != kRescuePhilQuest && bg1_variant != 0 && bg1_variant != 1)
1065 				showCat = true;
1066 			showOldMan = true;
1067 			if (!persistent->_creteShowMerchant) {
1068 				showManSelling = true;
1069 				toughGuyPosition = 2;
1070 			}
1071 			showWomanGraffiti = true;
1072 			showWomanDrawing = true;
1073 			break;
1074 		case 4:
1075 			if (quest != kRescuePhilQuest && bg1_variant != 0 && bg1_variant != 1)
1076 				showCat = true;
1077 			showWomanDrawing = true;
1078 			toughGuyPosition = 2;
1079 			showOneManBand = true;
1080 			break;
1081 		case 5:
1082 			if (quest != kCreteQuest && quest != kTroyQuest)
1083 				toughGuyPosition = 1;
1084 			else
1085 				toughGuyPosition = g_vm->getRnd().getRandomBit();
1086 			womanSmellPosition = g_vm->getRnd().getRandomBit();
1087 			break;
1088 		case 6:
1089 			showWomanGraffiti = true;
1090 			showWomanDrawing = true;
1091 			if (quest != kCreteQuest && quest != kTroyQuest)
1092 				toughGuyPosition = 1;
1093 			else
1094 				toughGuyPosition = g_vm->getRnd().getRandomBit();
1095 			break;
1096 		case 7:
1097 			womanSmellPosition = g_vm->getRnd().getRandomNumberRng(0, 2);
1098 			if (womanSmellPosition == 2 && (quest != kCreteQuest && quest != kTroyQuest))
1099 				womanSmellPosition = -1;
1100 			if (quest == kMedusaQuest)
1101 				showStatueMan = true;
1102 			showMotherAndKidSmall = true;
1103 			showWomanGraffiti = true;
1104 			break;
1105 		case 8:
1106 			if (quest != kCreteQuest && quest != kTroyQuest) {
1107 				toughGuyPosition = 1;
1108 				showDrawinWithoutWoman = true;
1109 				break;
1110 			}
1111 
1112 			if (!persistent->_creteShowMerchant && randomBool()) {
1113 				toughGuyPosition = 2;
1114 				showBlondBoy = true;
1115 			}
1116 			else
1117 				toughGuyPosition = 1;
1118 			showOldMan = true;
1119 			showDrawinWithoutWoman = true;
1120 			break;
1121 		}
1122 
1123 		int birdsState = g_vm->getRnd().getRandomNumberRng(0, 2);
1124 		int dolphinPosition = -1;
1125 		if (!persistent->_creteShowAtlantisBoat)
1126 			dolphinPosition = g_vm->getRnd().getRandomNumberRng(0, showOiBoat ? 1 : 2);
1127 		if (quest != kMedusaQuest && quest != kRescuePhilQuest)
1128 			_alchemistAmbient = ambient("r2220ba0", "r2220ec0", 5500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom, true);
1129 
1130 		// Disable conflicting images
1131 		if (minotaurPosition == 1
1132 		    && (toughGuyPosition == 1 || toughGuyPosition == 2))
1133 			toughGuyPosition = -1;
1134 		if (minotaurPosition == 1) {
1135 			showWomanGraffiti = false;
1136 			showManSelling = false;
1137 			showOneManBand = false;
1138 		}
1139 		if (persistent->_creteShowMerchant &&
1140 		    (toughGuyPosition == 0 || toughGuyPosition == 1))
1141 			toughGuyPosition = -1;
1142 		if (womanSmellPosition == 2)
1143 			showMotherAndKid = false;
1144 		if (persistent->_creteShowMerchant)
1145 			showCat = false;
1146 		if (quest != kCreteQuest && quest != kTroyQuest)
1147 			showOldMan = false;
1148 
1149 		debug("toughGuyPosition = %d, minotaurPosition = %d, dolphinPosition = %d",
1150 		      toughGuyPosition, minotaurPosition, dolphinPosition);
1151 		if (showWomanGraffiti)
1152 			ambient("r2370ba0", "r2370ea0", 1700, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1153 		switch (toughGuyPosition) {
1154 		case 0:
1155 			ambient("r2340ba0", "r2340ea0", 1400, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1156 			break;
1157 		case 1:
1158 			ambient("r2340bb0", "r2340eb0", 1400, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1159 			break;
1160 		case 2:
1161 			ambient("r2340be0", "r2340ee0", 1600, 15, 25, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1162 			break;
1163 		}
1164 		if (showOneManBand) {
1165 			room->playAnimLoop(kOneManBandAnim, kOneManBandZ, kOffsetRightRoom);
1166 			room->enableHotzone(kOneManBandHotZone);
1167 		}
1168 		if (showGirlAndNut)
1169 			ambient("r2140ba0", "r2140ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1170 		if (showWomanDrawing)
1171 			ambient("r2110ba0", "r2110ea0", 1600, 10, 30, AmbientAnim::PAN_LEFT);
1172 		if (showDrawinWithoutWoman)
1173 			room->addStaticLayer("r2110bb0", 1600);
1174 		if (showManSelling)
1175 			ambient("r2150ba0", "r2150ea0", 1600, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1176 		if (showMotherAndKid)
1177 			ambient("r2160ba0", "r2160ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1178 		if (showMotherAndKidSmall)
1179 			ambient("r2160bb0", "", 1500, 15, 30, AmbientAnim::PAN_LEFT);
1180 		if (showBlondBoy)
1181 			ambient("r2350ba0", "r2350ea0", 1500, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1182 		if (showOldMan)
1183 			ambient("r2100bb0", "r2100eb0", 1500, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1184 		if (showStatueMan)
1185 			ambient("r2050ba0", "r2050ea0", 1500, 10, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1186 		if (showCat) {
1187 			room->addStaticLayer("r2010on0", kMerchantStandZ);
1188 			ambient("r2080bb0", "r2080eb0", kMerchantZ, 10, 30, AmbientAnim::PAN_LEFT);
1189 		}
1190 
1191 		if (persistent->_creteShowMerchant) {
1192 			room->addStaticLayer("r2010on0", kMerchantStandZ);
1193 			room->selectFrame(kMerchantAnim, kMerchantZ, 0);
1194 			room->playSFX("G0261mA0");
1195 			if (persistent->_creteShowHorned) {
1196 				room->addStaticLayer(kHorned, 1220);
1197 				room->enableHotzone(kHornedHotzone);
1198 			}
1199 			if (persistent->_creteShowHornless2) {
1200 				room->addStaticLayer(kHornless2, 1190);
1201 				room->setHotzoneEnabled(kHornless2Hotzone,
1202 					persistent->_creteTriedHornless[0]);
1203 			}
1204 			if (persistent->_creteShowHornless1) {
1205 				room->addStaticLayer(kHornless1, 1180);
1206 				room->enableHotzone(kHornless1Hotzone);
1207 			}
1208 			if (persistent->_creteShowHornless3) {
1209 				room->addStaticLayer(kHornless3, 1180);
1210 				room->setHotzoneEnabled(kHornless3Hotzone,
1211 					persistent->_creteTriedHornless[1]);
1212 			}
1213 			if (persistent->_creteShowHornless4) {
1214 				room->addStaticLayer(kHornless4, 1180);
1215 				room->setHotzoneEnabled(kHornless4Hotzone,
1216 					persistent->_creteTriedHornless[2]);
1217 				g_vm->addTimer(kMerchantIdleTimer, 10000, -1);
1218 			}
1219 		}
1220 
1221 		if (birdsState == 0) {
1222 			room->addStaticLayer(kTalusImageWithShip, kTalusZ);
1223 			room->enableHotzone(kTalusHotzone);
1224 		} else
1225 			room->addStaticLayer(kTalusImage, kTalusZ);
1226 
1227 		// TODO: fix this
1228 		switch (minotaurPosition) {
1229 		case 0:
1230 			ambient("r2060bf0", "r2060ee0", 1800, 3, 4, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); // shouldn't be an ambient
1231 			break;
1232 		case 1:
1233 			ambient("r2060bt0", "r2060ei0", 1650, 3, 4, AmbientAnim::PAN_RIGHT, kOffsetRightRoom); // shouldn't be an ambient
1234 			break;
1235 		case 2:
1236 //			ambient("r1110ea0", "", 15, 30); // wrong
1237 			break;
1238 		case 3:
1239 			ambient("r1110ba0", "r1110eb0", 850, 20, 40, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1240 			break;
1241 		}
1242 
1243 		switch (womanSmellPosition) {
1244 		case 0:
1245 			ambient("r2380ba0", "r2380ea0", 1550, 15, 30, AmbientAnim::PAN_ANY);
1246 			break;
1247 		case 1:
1248 			ambient("r2380bc0", "r2380ec0", 1550, 15, 30, AmbientAnim::PAN_ANY);
1249 			break;
1250 		case 2:
1251 			ambient("r2380bd0", "r2380ed0", 1550, 15, 30, AmbientAnim::PAN_RIGHT, kOffsetRightRoom);
1252 			break;
1253 		}
1254 
1255 		switch (birdsState) {
1256 		case 0:
1257 			ambient("r1060ba0", "r1060ea0", 4500, 10, 40, AmbientAnim::PAN_ANY);
1258 			break;
1259 		case 1:
1260 			ambient("r1060bb0","r1060eb0", 4500, 5, 40, AmbientAnim::PAN_ANY);
1261 			break;
1262 		case 2:
1263 			ambient("r1060bc0", "r1060ec0", 4500, 5, 40, AmbientAnim::PAN_ANY);
1264 			break;
1265 		}
1266 
1267 		if (dolphinPosition >= 0) {
1268 			Common::String dolphinAnim = Common::String::format(
1269 				"r1150b%c0", 'a' + dolphinPosition);
1270 			Common::String dolphinSound = Common::String::format(
1271 				"r1150e%c0", 'a' + dolphinPosition);
1272 
1273 			ambient(dolphinAnim, dolphinSound, 5500, 5, 20, AmbientAnim::PAN_LEFT);
1274 		}
1275 
1276 		if (bg1_variant >= 0 && bg2_variant >= 0) {
1277 			Common::String bg2 = Common::String::format(
1278 				"r1010o%c1", 'e' + bg2_variant);
1279 			room->addStaticLayer(bg2, 3500);
1280 
1281 			Common::String bg1 = Common::String::format(
1282 				"r1010o%c0", 'e' + bg1_variant);
1283 			room->addStaticLayer(bg1, 1000);
1284 		}
1285 
1286 		room->playMusicLoop("R1010eA0");
1287 
1288 		if (g_vm->getPreviousRoomId() == kMinosPalaceRoom) {
1289 			room->panRightInstant();
1290 			if (persistent->_creteIntroMerchant) {
1291 				room->disableMouse();
1292 				room->panLeftAnim(kIntroMerchantPanFinished);
1293 				_merchantIsBusy = true;
1294 				persistent->_creteIntroMerchant = false;
1295 			}
1296 
1297 			if (persistent->_creteIntroAtlantisBoat) {
1298 				persistent->_creteIntroAtlantisBoat = false;
1299 				room->disableMouse();
1300 				room->playVideo("r1180ba0", 0, 12134, Common::Point(640, 216));
1301 			}
1302 
1303 		}
1304 
1305 		if (quest == kMedusaQuest && persistent->_medisleShowFates) {
1306 			switch (persistent->_creteSandalsState) {
1307 			case Persistent::SANDALS_NOT_SOLVED:
1308 				for (int i = 0; i < 4; i++)
1309 					room->enableHotzone(Common::String::format("VaseSegment%d", i + 1));
1310 				_vasePos[0] = (g_vm->getRnd().getRandomNumberRng(1, 3) + 2) % 4;
1311 				_vasePos[1] = (g_vm->getRnd().getRandomNumberRng(1, 5) + 3) % 6;
1312 				_vasePos[2] = (g_vm->getRnd().getRandomNumberRng(1, 5) + 2) % 6;
1313 				_vasePos[3] = (g_vm->getRnd().getRandomNumberRng(1, 3) + 3) % 4;
1314 				renderVase();
1315 				break;
1316 			case Persistent::SANDALS_SOLVED:
1317 				showSandals();
1318 				break;
1319 			case Persistent::SANDALS_TAKEN:
1320 				room->selectFrame("r1220ba0", 500, 0);
1321 				break;
1322 			}
1323 		}
1324 
1325 		switch (persistent->_quest) {
1326 		case kCreteQuest:
1327 			if (!persistent->_roomVisited[kMinosPalaceRoom]) {
1328 				room->playVideo("r1260ma0", 0);
1329 				break;
1330 			}
1331 
1332 			if (persistent->_creteShowMerchant) {
1333 				room->playVideo("g0261ma0", 0);
1334 				break;
1335 			}
1336 			break;
1337 		case kMedusaQuest:
1338 			if (persistent->_medisleShowFates && persistent->_creteSandalsState == Persistent::SANDALS_NOT_SOLVED)
1339 				room->playVideo("r1220ma0", 0);
1340 			break;
1341 		case kRescuePhilQuest:
1342 			if (persistent->_creteStrongBoxState == Persistent::BOX_CLOSED || persistent->_creteStrongBoxState == Persistent::BOX_OPEN)
1343 				room->playVideo("r2230ma0", 0);
1344 			break;
1345 		// To silence warning
1346 		case kTroyQuest:
1347 		case kNoQuest:
1348 		case kEndGame:
1349 		case kNumQuests:
1350 			break;
1351 		}
1352 
1353 		if (!persistent->_creteSaidHelenPermanentResident && persistent->_quest == kTroyQuest) {
1354 			persistent->_creteSaidHelenPermanentResident = true;
1355 			room->disableMouse();
1356 			room->playVideo("r1250ba0", 0, 12134, Common::Point(0, 216));
1357 		}
1358 	}
1359 
frameCallback()1360 	void frameCallback() override {
1361 		if (_strongBoxPopup && strongBoxIsBusy())
1362 			redrawStrongBox();
1363 		if (_fadingHades) {
1364 			Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1365 			int val = (256 * (g_vm->getCurrentTime() - _fadingHadesStartTime)) / 2000;
1366 			if (val >= 256) {
1367 				_fadingHades = false;
1368 				val = 256;
1369 				handleEvent(12125);
1370 			}
1371 			room->setColorScale("r2035pa0", 256 - val);
1372 		}
1373 	}
1374 
1375 private:
showMiniStrongBox()1376 	void showMiniStrongBox() {
1377 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1378 		Persistent *persistent = g_vm->getPersistent();
1379 		if (persistent->_quest != kRescuePhilQuest)
1380 			return;
1381 
1382 		switch(persistent->_creteStrongBoxState) {
1383 		case Persistent::BOX_CLOSED:
1384 			room->enableHotzone("StrongBoxClosed");
1385 			room->selectFrame("r2010ba0", 5000, 0, kOffsetRightRoom);
1386 			break;
1387 		case Persistent::BOX_OPEN:
1388 			room->enableHotzone("StrongBoxOpen");
1389 			room->selectFrame("r2010ba0", 5000, 1, kOffsetRightRoom);
1390 			break;
1391 		case Persistent::BOX_OPEN_POTION:
1392 			room->enableHotzone("StrongBoxOpenPotion");
1393 			room->selectFrame("r2010ba0", 5000, 2, kOffsetRightRoom);
1394 			break;
1395 		case Persistent::BOX_OPEN_NO_POTION:
1396 			room->enableHotzone("StrongBoxOpenNoPotion");
1397 			room->selectFrame("r2010ba0", 5000, 3, kOffsetRightRoom);
1398 			break;
1399 		}
1400 	}
1401 
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)1402 	AmbientAnim ambient(const Common::String &anim, const Common::String &sound,
1403 			    int zValue, int minint, int maxint,
1404 			    AmbientAnim::PanType pan,
1405 			    Common::Point offset = Common::Point(0,0),
1406 			    bool loop = true) {
1407 		AmbientAnim ret = AmbientAnim(anim, sound, zValue, minint * 1000, maxint * 1000,
1408 					      loop ? AmbientAnim::KEEP_LOOP : AmbientAnim::DISAPPEAR,
1409 					      offset, pan);
1410 		ret.start();
1411 		return ret;
1412 	}
1413 
randomBool() const1414 	bool randomBool() const {
1415 		return g_vm->getRnd().getRandomBit();
1416 	}
1417 
renderAtlantisDisks()1418 	void renderAtlantisDisks() {
1419 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1420 		room->selectFrame(kAtlantisLargeDisk, kAtlantisLargeDiskZ, _atlantisBoatPosition[0]);
1421 		room->selectFrame(kAtlantisMediumDisk, kAtlantisMediumDiskZ, _atlantisBoatPosition[1]);
1422 		room->selectFrame(kAtlantisSmallDisk, kAtlantisSmallDiskZ, _atlantisBoatPosition[2]);
1423 	}
1424 
advanceAtlantisDisk(int diskNum)1425 	void advanceAtlantisDisk(int diskNum) {
1426 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1427 		_atlantisBoatPosition[diskNum] = (_atlantisBoatPosition[diskNum] + 1) % 8;
1428 		renderAtlantisDisks();
1429 		room->playSFX(Common::String::format("r1210e%c0", 'e' + diskNum), 12303 + diskNum);
1430 	}
1431 
hideAtlantisPopupOverlays()1432 	void hideAtlantisPopupOverlays() {
1433 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1434 		room->stopAnim(kAtlantisLargeDisk);
1435 		room->stopAnim(kAtlantisMediumDisk);
1436 		room->stopAnim(kAtlantisSmallDisk);
1437 		room->stopAnim(kAtlantisDiskBackground);
1438 	}
1439 
renderVase()1440 	void renderVase() {
1441 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1442 		for(int i = 0; i < 4; i++)
1443 			room->selectFrame(vaseSegment[i], 1000, _vasePos[i]);
1444 
1445 	}
1446 
showSandals()1447 	void showSandals() {
1448 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1449 		room->playAnim("r1220ba0", 500, PlayAnimParams::loop().partial(9, 17));
1450 		room->enableHotzone("sandals");
1451 	}
1452 
showStrongBox()1453 	void showStrongBox() {
1454 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1455 		Persistent *persistent = g_vm->getPersistent();
1456 		// User already clicked, no need to play that anim
1457 		persistent->_cretePlayedZeusCheckOutThatBox = true;
1458 		room->pushHotZones("Box.Hot");
1459 		room->playSFX("g0082ea0");
1460 		redrawStrongBox();
1461 		_strongBoxPopup = true;
1462 		switch(persistent->_creteStrongBoxState) {
1463 		case Persistent::BOX_CLOSED:
1464 			room->selectFrame("r2230bb0", 1000, 1, kOffsetRightRoom);
1465 			break;
1466 		case Persistent::BOX_OPEN:
1467 			room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom);
1468 			break;
1469 		case Persistent::BOX_OPEN_POTION:
1470 			room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom);
1471 			room->selectFrame("r2230bf0", 300, -2, kOffsetRightRoom);
1472 			break;
1473 		case Persistent::BOX_OPEN_NO_POTION:
1474 			room->selectFrame("r2230bb0", 1000, 3, kOffsetRightRoom);
1475 			room->selectFrame("r2230bf0", 300, -1, kOffsetRightRoom);
1476 			break;
1477 		}
1478 	}
1479 
hideStrongBox()1480 	void hideStrongBox() {
1481 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1482 		room->stopAnim("r2230bb0");
1483 		room->stopAnim("r2230bf0");
1484 		for (int i = 0; i < 12; i++)
1485 			room->stopAnim(LayerId("r2010om0", i, "pos"));
1486 		room->stopAnim(LayerId("r2010om1", 0, "center"));
1487 		for (int i = 0; i < 4; i++) {
1488 			room->stopAnim(LayerId("r2010om1", i, "side"));
1489 		}
1490 		_strongBoxPopup = false;
1491 	}
1492 
redrawStrongBox()1493 	void redrawStrongBox() {
1494 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1495 		Persistent *persistent = g_vm->getPersistent();
1496 
1497 		room->setHotzoneEnabled("Potion", persistent->_creteStrongBoxState == Persistent::BOX_OPEN_POTION);
1498 		room->setHotzoneEnabled("Latch", persistent->_creteStrongBoxState == Persistent::BOX_CLOSED);
1499 		room->setHotzoneEnabled("ButtonN", persistent->_creteStrongBoxState == Persistent::BOX_OPEN);
1500 		room->setHotzoneEnabled("ButtonS", persistent->_creteStrongBoxState == Persistent::BOX_OPEN);
1501 		room->setHotzoneEnabled("ButtonE", persistent->_creteStrongBoxState == Persistent::BOX_OPEN);
1502 		room->setHotzoneEnabled("ButtonW", persistent->_creteStrongBoxState == Persistent::BOX_OPEN);
1503 		room->setHotzoneEnabled("ButtonC", persistent->_creteStrongBoxState == Persistent::BOX_OPEN);
1504 
1505 		switch(persistent->_creteStrongBoxState) {
1506 		case Persistent::BOX_CLOSED:
1507 			break;
1508 		case Persistent::BOX_OPEN:
1509 			room->selectFrame(LayerId("r2010om1", 0, "center"), 400, 0, Common::Point(1060, 308));
1510 			for (int i = 0; i < 4; i++) {
1511 				room->selectFrame(LayerId("r2010om1", i, "side"), 400, 1,
1512 						  strongBoxSideDotOffsets[i].get());
1513 			}
1514 			{
1515 				bool wasMoving = strongBoxIsBusy();
1516 				for (int i = 0; i < 12; i++) {
1517 					_strongBoxTiles[i].show();
1518 				}
1519 				if (wasMoving && !strongBoxIsBusy()) {
1520 					strongBoxCheckSolution();
1521 				}
1522 			}
1523 			break;
1524 		case Persistent::BOX_OPEN_POTION:
1525 		case Persistent::BOX_OPEN_NO_POTION:
1526 			room->selectFrame(LayerId("r2010om1", 0, "center"), 400, 0, Common::Point(1060, 308));
1527 			for (int i = 0; i < 4; i++) {
1528 				room->selectFrame(LayerId("r2010om1", i, "side"), 400, 1,
1529 						  strongBoxSideDotOffsets[i].get());
1530 			}
1531 			for (int i = 0; i < 12; i++) {
1532 				_strongBoxTiles[i].show();
1533 			}
1534 			break;
1535 		}
1536 	}
1537 
strongBoxIsBusy()1538 	bool strongBoxIsBusy() {
1539 		for (int i = 0; i < 12; i++) {
1540 			if (_strongBoxTiles[i].isMoving()) {
1541 				return true;
1542 			}
1543 		}
1544 		return false;
1545 	}
1546 
strongBoxCheckSolution()1547 	void strongBoxCheckSolution() {
1548 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1549 		Persistent *persistent = g_vm->getPersistent();
1550 		bool zOk = false, eOk = false, uOk = false, sOk = false;
1551 		for (int i = 0; i < 12; i++) {
1552 			if (_strongBoxTiles[i].getPosition() == 0
1553 			    && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterZ
1554 			    && (_strongBoxTiles[i].getOrientation() == 0
1555 				|| _strongBoxTiles[i].getOrientation() == 180))
1556 				zOk = true;
1557 			if (_strongBoxTiles[i].getPosition() == 1
1558 			    && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterE
1559 			    && _strongBoxTiles[i].getOrientation() == 0)
1560 				eOk = true;
1561 			if (_strongBoxTiles[i].getPosition() == 2
1562 			    && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterU
1563 			    && _strongBoxTiles[i].getOrientation() == 0)
1564 				uOk = true;
1565 			if (_strongBoxTiles[i].getPosition() == 3
1566 			    && _strongBoxTiles[i].getLetter() == StrongBoxTile::kLetterS
1567 			    && (_strongBoxTiles[i].getOrientation() == 0
1568 				|| _strongBoxTiles[i].getOrientation() == 180))
1569 				sOk = true;
1570 		}
1571 
1572 		if (zOk && eOk && uOk && sOk) {
1573 			persistent->_creteStrongBoxState = Persistent::BOX_OPEN_POTION;
1574 			room->disableMouse();
1575 			room->enableHotzone("Potion");
1576 			room->disableHotzone("ButtonS");
1577 			room->disableHotzone("ButtonN");
1578 			room->disableHotzone("ButtonE");
1579 			room->disableHotzone("ButtonW");
1580 			room->disableHotzone("ButtonC");
1581 			room->playAnimWithSFX("r2230bf0", "r2230ea0", 300,
1582 					      PlayAnimParams::keepLastFrame().partial(0, -2),
1583 					      12414, kOffsetRightRoom);
1584 		}
1585 	}
1586 
strongBoxMoveTiles(int p1,int p2,int p3,int p4)1587 	void strongBoxMoveTiles(int p1, int p2, int p3, int p4) {
1588 		Common::SharedPtr<VideoRoom> room = g_vm->getVideoRoom();
1589 		room->playSFX("r2230ee0");
1590 		for (int i = 0; i < 12; i++) {
1591 			int pos = _strongBoxTiles[i].getPosition();
1592 			if (pos == p1)
1593 				_strongBoxTiles[i].moveTo(p2);
1594 			if (pos == p2)
1595 				_strongBoxTiles[i].moveTo(p3);
1596 			if (pos == p3)
1597 				_strongBoxTiles[i].moveTo(p4);
1598 			if (pos == p4)
1599 				_strongBoxTiles[i].moveTo(p1);
1600 		}
1601 	}
1602 
1603 	bool _fadingHades;
1604 	int _fadingHadesStartTime;
1605 	int _tavernCounter;
1606 	int _oneManBandCounter;
1607 	int _atlantisBoatPosition[3];
1608 	bool _merchantIsBusy;
1609 	int _vasePos[4];
1610 	bool _vaseBusy[4];
1611 	bool _strongBoxPopup;
1612 	StrongBoxTile _strongBoxTiles[12];
1613 	Common::Array<Common::String> _tavernTalks;
1614 	AmbientAnim _alchemistAmbient;
1615 };
1616 
makeCreteHandler()1617 Common::SharedPtr<Hadesch::Handler> makeCreteHandler() {
1618 	return Common::SharedPtr<Hadesch::Handler>(new CreteHandler());
1619 }
1620 
1621 }
1622