aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
authorBastien Bouclet2011-01-15 19:11:53 +0000
committerBastien Bouclet2011-01-15 19:11:53 +0000
commit09c35e99b8d06a883eeab10a4f3955c0a3777973 (patch)
treead23150e1ffea66a8cefa849d183b8975bfcb89f /engines/mohawk
parent295550b26c2261f371bc86950ec768b1ef460fbd (diff)
downloadscummvm-rg350-09c35e99b8d06a883eeab10a4f3955c0a3777973.tar.gz
scummvm-rg350-09c35e99b8d06a883eeab10a4f3955c0a3777973.tar.bz2
scummvm-rg350-09c35e99b8d06a883eeab10a4f3955c0a3777973.zip
MOHAWK: Implement Myst's clock tower gears puzzle
svn-id: r55253
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp297
-rw-r--r--engines/mohawk/myst_stacks/myst.h24
-rw-r--r--engines/mohawk/video.cpp15
-rw-r--r--engines/mohawk/video.h1
4 files changed, 321 insertions, 16 deletions
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index 4aa91e2433..413c3a0f06 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -90,6 +90,8 @@ void MystScriptParser_Myst::setupOpcodes() {
OPCODE(122, o_cabinSafeHandleStartMove);
OPCODE(123, o_cabinSafeHandleMove);
OPCODE(124, o_cabinSafeHandleEndMove);
+ OPCODE(126, o_clockLeverStartMove);
+ OPCODE(127, o_clockLeverEndMove);
OPCODE(128, o_treePressureReleaseStart);
if (!observatoryIsDDMMYYYY2400()) {
OPCODE(129, o_observatoryMonthChangeStart);
@@ -107,9 +109,14 @@ void MystScriptParser_Myst::setupOpcodes() {
OPCODE(135, o_observatoryDaySliderMove);
OPCODE(136, o_observatoryYearSliderMove);
OPCODE(137, o_observatoryTimeSliderMove);
+ OPCODE(138, o_clockResetLeverStartMove);
+ OPCODE(139, o_clockResetLeverMove);
+ OPCODE(140, o_clockResetLeverEndMove);
OPCODE(141, o_circuitBreakerStartMove);
OPCODE(142, o_circuitBreakerMove);
OPCODE(143, o_circuitBreakerEndMove);
+ OPCODE(144, o_clockLeverMove);
+ OPCODE(145, o_clockLeverMove);
OPCODE(146, o_boilerIncreasePressureStart);
OPCODE(147, o_boilerLightPilot);
OPCODE(148, NOP);
@@ -175,7 +182,7 @@ void MystScriptParser_Myst::setupOpcodes() {
OPCODE(209, o_libraryBookcaseTransform_init);
OPCODE(210, o_generatorControlRoom_init);
OPCODE(211, o_fireplace_init);
- OPCODE(212, opcode_212);
+ OPCODE(212, o_clockGears_init);
OPCODE(213, opcode_213);
OPCODE(214, o_observatory_init);
OPCODE(215, opcode_215);
@@ -221,6 +228,7 @@ void MystScriptParser_Myst::disablePersistentScripts() {
_observatoryYearChanging = false;
_observatoryTimeChanging = false;
_greenBookRunning = false;
+ _clockLeverPulled = false;
}
void MystScriptParser_Myst::runPersistentScripts() {
@@ -280,6 +288,9 @@ void MystScriptParser_Myst::runPersistentScripts() {
if (_greenBookRunning)
greenBook_run();
+
+ if (_clockLeverPulled)
+ clockGears_run();
}
uint16 MystScriptParser_Myst::getVar(uint16 var) {
@@ -2769,6 +2780,262 @@ void MystScriptParser_Myst::o_imagerEraseStop(uint16 op, uint16 var, uint16 argc
_imagerValidationRunning = false;
}
+void MystScriptParser_Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock lever start move", op);
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ lever->drawFrame(0);
+ _vm->_cursor->setCursor(700);
+ _clockMiddleGearMovedAlone = false;
+ _clockLeverPulled = false;
+}
+
+void MystScriptParser_Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock left lever move", op);
+
+ if (!_clockLeverPulled) {
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+
+ // Make the handle follow the mouse
+ int16 maxStep = lever->getStepsV() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((_vm->_mouse.y - rect.top) * lever->getStepsV()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ lever->drawFrame(step);
+
+ if (step == maxStep) {
+ // Start videos for first step
+ if (_clockWeightPosition < 2214) {
+ _vm->_sound->replaceSound(5113);
+ clockGearForwardOneStep(1);
+
+ // Left lever
+ if (op == 144)
+ clockGearForwardOneStep(2);
+ else // Right lever
+ clockGearForwardOneStep(0);
+
+ clockWeightDownOneStep();
+ }
+ _clockLeverPulled = true;
+ }
+ }
+}
+
+void MystScriptParser_Myst::clockGearForwardOneStep(uint16 gear) {
+ static const uint16 startTime[] = { 0, 324, 618 };
+ static const uint16 endTime[] = { 324, 618, 950 };
+ static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
+ static const uint16 x[] = { 224, 224, 224 };
+ static const uint16 y[] = { 49, 82, 109 };
+
+ // Increment value by one
+ _clockGearsPositions[gear] = _clockGearsPositions[gear] % 3 + 1;
+
+ // Set video bounds
+ uint16 gearPosition = _clockGearsPositions[gear] - 1;
+ _clockGearsVideos[gear] = _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]);
+ _vm->_video->setVideoBounds(_clockGearsVideos[gear],
+ Graphics::VideoTimestamp(startTime[gearPosition], 600),
+ Graphics::VideoTimestamp(endTime[gearPosition], 600));
+}
+
+void MystScriptParser_Myst::clockWeightDownOneStep() {
+ // Set video bounds
+ _clockWeightVideo = _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+ _vm->_video->setVideoBounds(_clockWeightVideo,
+ Graphics::VideoTimestamp(_clockWeightPosition, 600),
+ Graphics::VideoTimestamp(_clockWeightPosition + 246, 600));
+
+ // Increment value by one step
+ _clockWeightPosition += 246;
+}
+
+void MystScriptParser_Myst::clockGears_run() {
+ if (!_vm->_video->isVideoPlaying() && _clockWeightPosition < 2214) {
+ _clockMiddleGearMovedAlone = true;
+ _vm->_sound->replaceSound(5113);
+ clockGearForwardOneStep(1);
+ clockWeightDownOneStep();
+ }
+}
+
+void MystScriptParser_Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock lever end move", op);
+ static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
+
+ _vm->_cursor->hideCursor();
+ _clockLeverPulled = false;
+
+ // Let movies stop playing
+ for (uint i = 0; i < ARRAYSIZE(videos); i++) {
+ VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack));
+ if (handle != NULL_VID_HANDLE)
+ _vm->_video->delayUntilMovieEnds(handle);
+ }
+
+ if (_clockMiddleGearMovedAlone)
+ _vm->_sound->replaceSound(8113);
+
+ // Get current lever frame
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ int16 maxStep = lever->getStepsV() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((_vm->_mouse.y - rect.top) * lever->getStepsV()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ // Release lever
+ for (int i = step; i >= 0; i--) {
+ lever->drawFrame(i);
+ _vm->_system->delayMillis(10);
+ }
+
+ // Check if puzzle is solved
+ clockGearsCheckSolution();
+
+ _vm->_cursor->showCursor();
+}
+
+void MystScriptParser_Myst::clockGearsCheckSolution() {
+ if (_clockGearsPositions[0] == 2
+ && _clockGearsPositions[1] == 2
+ && _clockGearsPositions[2] == 1
+ && !_state.gearsOpen) {
+
+ // Make weight go down
+ _vm->_sound->replaceSound(9113);
+ _clockWeightVideo = _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+ _vm->_video->setVideoBounds(_clockWeightVideo,
+ Graphics::VideoTimestamp(_clockWeightPosition, 600),
+ Graphics::VideoTimestamp(2214, 600));
+ _vm->_video->waitUntilMovieEnds(_clockWeightVideo);
+ _clockWeightPosition = 2214;
+
+ _vm->_sound->replaceSound(6113);
+ _vm->_system->delayMillis(1000);
+ _vm->_sound->replaceSound(7113);
+
+ // Gear opening video
+ _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225);
+ _state.gearsOpen = 1;
+ _vm->redrawArea(40);
+
+ _vm->_sound->replaceBackground(4113, 16384);
+ }
+}
+
+void MystScriptParser_Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock reset lever start move", op);
+
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ lever->drawFrame(0);
+ _vm->_cursor->setCursor(700);
+}
+
+void MystScriptParser_Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock reset lever move", op);
+
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+
+ // Make the handle follow the mouse
+ int16 maxStep = lever->getStepsV() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((_vm->_mouse.y - rect.top) * lever->getStepsV()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ lever->drawFrame(step);
+
+ if (step == maxStep && _clockWeightPosition != 0)
+ clockReset();
+}
+
+void MystScriptParser_Myst::clockReset() {
+ static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
+
+ _vm->_cursor->hideCursor();
+
+ _vm->_sound->stopBackground();
+ _vm->_sound->replaceSound(5113);
+
+ // Play reset videos
+ clockResetWeight();
+ clockResetGear(0);
+ clockResetGear(1);
+ clockResetGear(2);
+
+ // Let movies stop playing
+ for (uint i = 0; i < ARRAYSIZE(videos); i++) {
+ VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack));
+ if (handle != NULL_VID_HANDLE)
+ _vm->_video->delayUntilMovieEnds(handle);
+ }
+
+ _vm->_sound->replaceSound(10113);
+
+ // Close gear
+ if (_state.gearsOpen) {
+ _vm->_sound->replaceSound(6113);
+ _vm->_system->delayMillis(1000);
+ _vm->_sound->replaceSound(7113);
+
+ // TODO: Play cl1wggat backwards
+ // Redraw gear
+ _state.gearsOpen = 0;
+ _vm->redrawArea(40);
+ }
+
+ _vm->_cursor->showCursor();
+}
+
+void MystScriptParser_Myst::clockResetWeight() {
+ // Set video bounds
+ _clockWeightVideo = _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
+ _vm->_video->setVideoBounds(_clockWeightVideo,
+ Graphics::VideoTimestamp(2214 * 2 - _clockWeightPosition, 600),
+ Graphics::VideoTimestamp(2214 * 2, 600));
+
+ // Reset position
+ _clockWeightPosition = 0;
+}
+
+void MystScriptParser_Myst::clockResetGear(uint16 gear) {
+ static const uint16 time[] = { 324, 618, 950 };
+ static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
+ static const uint16 x[] = { 224, 224, 224 };
+ static const uint16 y[] = { 49, 82, 109 };
+
+ // Set video bounds
+ uint16 gearPosition = _clockGearsPositions[gear] - 1;
+ if (gearPosition != 2) {
+ _clockGearsVideos[gear] = _vm->_video->playBackgroundMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]);
+ _vm->_video->setVideoBounds(_clockGearsVideos[gear],
+ Graphics::VideoTimestamp(time[gearPosition], 600),
+ Graphics::VideoTimestamp(time[2], 600));
+ }
+
+ // Reset gear position
+ _clockGearsPositions[gear] = 3;
+}
+
+void MystScriptParser_Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+ debugC(kDebugScript, "Opcode %d: Clock reset lever end move", op);
+
+ // Get current lever frame
+ MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
+ int16 maxStep = lever->getStepsV() - 1;
+ Common::Rect rect = lever->getRect();
+ int16 step = ((_vm->_mouse.y - rect.top) * lever->getStepsV()) / rect.height();
+ step = CLIP<int16>(step, 0, maxStep);
+
+ // Release lever
+ for (int i = step; i >= 0; i--) {
+ lever->drawFrame(i);
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->checkCursorHints();
+}
+
void MystScriptParser_Myst::o_libraryBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
_libraryBookPage = 0;
_libraryBookNumPages = argv[0];
@@ -3024,21 +3291,21 @@ void MystScriptParser_Myst::o_fireplace_init(uint16 op, uint16 var, uint16 argc,
_fireplaceLines[i] = 0;
}
-void MystScriptParser_Myst::opcode_212(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
+void MystScriptParser_Myst::o_clockGears_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
// Used for Card 4113 (Clock Tower Cog Puzzle)
-
- if (false) {
- // 3 videos to be played of Cog Movement
- // TODO: Not 100% sure of movie positions.
- _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg1", kMystStack), 220, 50);
- _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg2", kMystStack), 220, 80);
- _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wg3", kMystStack), 220, 110);
-
- // 1 video of weight descent
- _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack), 123, 0);
-
- // Video of Cog Open on Success
- _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack), 195, 225);
+ debugC(kDebugScript, "Opcode %d: Gears puzzle init", op);
+
+ // Set gears position
+ if (_state.gearsOpen) {
+ _clockGearsPositions[0] = 2;
+ _clockGearsPositions[1] = 2;
+ _clockGearsPositions[2] = 1;
+ _clockWeightPosition = 2214;
+ } else {
+ _clockGearsPositions[0] = 3;
+ _clockGearsPositions[1] = 3;
+ _clockGearsPositions[2] = 3;
+ _clockWeightPosition = 0;
}
}
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index cbb81b2e07..1e70b9aaf2 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -71,6 +71,7 @@ private:
void observatoryYearChange_run();
void observatoryTimeChange_run();
void greenBook_run();
+ void clockGears_run();
DECLARE_OPCODE(o_libraryBookPageTurnLeft);
DECLARE_OPCODE(o_libraryBookPageTurnRight);
@@ -139,6 +140,13 @@ private:
DECLARE_OPCODE(o_clockMinuteWheelStartTurn);
DECLARE_OPCODE(o_clockWheelEndTurn);
DECLARE_OPCODE(o_clockHourWheelStartTurn);
+ DECLARE_OPCODE(o_clockLeverStartMove);
+ DECLARE_OPCODE(o_clockLeverMove);
+ DECLARE_OPCODE(o_clockLeverEndMove);
+ DECLARE_OPCODE(o_clockResetLeverStartMove);
+ DECLARE_OPCODE(o_clockResetLeverMove);
+ DECLARE_OPCODE(o_clockResetLeverEndMove);
+
DECLARE_OPCODE(o_libraryCombinationBookStartRight);
DECLARE_OPCODE(o_libraryCombinationBookStartLeft);
DECLARE_OPCODE(o_observatoryTimeChangeStart);
@@ -157,7 +165,7 @@ private:
DECLARE_OPCODE(o_libraryBookcaseTransform_init);
DECLARE_OPCODE(o_generatorControlRoom_init);
DECLARE_OPCODE(o_fireplace_init);
- DECLARE_OPCODE(opcode_212);
+ DECLARE_OPCODE(o_clockGears_init);
DECLARE_OPCODE(opcode_213);
DECLARE_OPCODE(o_observatory_init);
DECLARE_OPCODE(opcode_215);
@@ -216,6 +224,13 @@ private:
uint16 _clockTurningWheel;
+ VideoHandle _clockGearsVideos[3]; // 148 to 156
+ VideoHandle _clockWeightVideo; // 160
+ uint16 _clockGearsPositions[3]; // 164 to 168
+ uint16 _clockWeightPosition; // 172
+ bool _clockMiddleGearMovedAlone; // 176
+ bool _clockLeverPulled; // 328
+
uint16 _dockVaultState; // 92
bool _towerRotationMapRunning;
@@ -279,6 +294,13 @@ private:
void clockWheelStartTurn(uint16 wheel);
void clockWheelTurn(uint16 var);
+ void clockGearForwardOneStep(uint16 gear);
+ void clockWeightDownOneStep();
+ void clockGearsCheckSolution();
+ void clockReset();
+ void clockResetWeight();
+ void clockResetGear(uint16 gear);
+
void towerRotationMapRotate();
void towerRotationDrawBuildings();
uint16 towerRotationMapComputeAngle();
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 55f087e568..c82adade9d 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -143,6 +143,21 @@ void VideoManager::waitUntilMovieEnds(VideoHandle videoHandle) {
_videoStreams[videoHandle].clear();
}
+void VideoManager::delayUntilMovieEnds(VideoHandle videoHandle) {
+ bool continuePlaying = true;
+
+ while (!_videoStreams[videoHandle].endOfVideo() && !_vm->shouldQuit() && continuePlaying) {
+ if (updateBackgroundMovies())
+ _vm->_system->updateScreen();
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ delete _videoStreams[videoHandle].video;
+ _videoStreams[videoHandle].clear();
+}
+
VideoHandle VideoManager::playBackgroundMovie(const Common::String &filename, int16 x, int16 y, bool loop) {
VideoHandle videoHandle = createVideoHandle(filename, x, y, loop);
if (videoHandle == NULL_VID_HANDLE)
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index ec9536bbf4..e0571431e6 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -110,6 +110,7 @@ public:
void seekToFrame(VideoHandle handle, uint32 frame);
void setVideoLooping(VideoHandle handle, bool loop);
void waitUntilMovieEnds(VideoHandle videoHandle);
+ void delayUntilMovieEnds(VideoHandle videoHandle);
private:
MohawkEngine *_vm;