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