diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/mohawk/myst_stacks/myst.cpp | 297 | ||||
-rw-r--r-- | engines/mohawk/myst_stacks/myst.h | 24 | ||||
-rw-r--r-- | engines/mohawk/video.cpp | 15 | ||||
-rw-r--r-- | engines/mohawk/video.h | 1 |
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; |