From 8050bca8d32d42bc3572d2158b6fdc4e7b9c3861 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Fri, 7 Dec 2012 08:13:34 +0100 Subject: MOHAWK: Implement the Myst boiler movies --- engines/mohawk/myst_stacks/myst.cpp | 137 ++++++++++++++++++++++++++++++------ engines/mohawk/myst_stacks/myst.h | 12 +++- 2 files changed, 128 insertions(+), 21 deletions(-) diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp index c1ddc74c82..036faef1a1 100644 --- a/engines/mohawk/myst_stacks/myst.cpp +++ b/engines/mohawk/myst_stacks/myst.cpp @@ -51,6 +51,8 @@ Myst::Myst(MohawkEngine_Myst *vm) : _dockVaultState = 0; _cabinDoorOpened = 0; _cabinMatchState = 2; + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; _matchBurning = false; _tree = 0; _treeAlcove = 0; @@ -189,7 +191,7 @@ void Myst::setupOpcodes() { OPCODE(215, o_gulls2_init); OPCODE(216, o_treeCard_init); OPCODE(217, o_treeEntry_init); - OPCODE(218, opcode_218); + OPCODE(218, o_boilerMovies_init); OPCODE(219, o_rocketSliders_init); OPCODE(220, o_rocketLinkVideo_init); OPCODE(221, o_greenBook_init); @@ -202,7 +204,7 @@ void Myst::setupOpcodes() { OPCODE(303, NOP); OPCODE(304, o_treeCard_exit); OPCODE(305, o_treeEntry_exit); - OPCODE(306, NOP); + OPCODE(306, o_boiler_exit); OPCODE(307, o_generatorControlRoom_exit); OPCODE(308, NOP); OPCODE(309, NOP); @@ -1869,17 +1871,50 @@ void Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) _state.cabinPilotLightLit = 1; _vm->redrawArea(98); + boilerFireUpdate(false); + // Put out match _matchGoOutTime = _vm->_system->getMillis(); if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - if (_state.cabinValvePosition > 12) + if (_state.cabinValvePosition > 12) { + // Compute the speed of the gauge to synchronize it with the next tree move + uint32 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + boilerResetGauge(rate); + _state.treeLastMoveTime = _vm->_system->getMillis(); + } + } +} - // TODO: Complete. Play movies +Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) { + Common::Rational rate = Common::Rational(2088, delay); + if (pressure < 12) + return -rate; + else + return rate; +} + +void Myst::boilerResetGauge(const Common::Rational &rate) { + if (_vm->_video->endOfVideo(_cabinGaugeMovie)) { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); + } } + + Audio::Timestamp goTo; + if (rate > 0) + goTo = Audio::Timestamp(0, 0, 600); + else + goTo = _vm->_video->getDuration(_cabinGaugeMovie); + + _vm->_video->seekToTime(_cabinGaugeMovie, goTo); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); } void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) { @@ -1893,7 +1928,12 @@ void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); } @@ -1903,7 +1943,8 @@ void Myst::boilerPressureIncrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition < 25) { _state.cabinValvePosition++; if (_state.cabinValvePosition == 1) { - // TODO: Play fire movie + // Set fire to high + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1927,7 +1968,8 @@ void Myst::boilerPressureDecrease_run() { if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition > 0) { _state.cabinValvePosition--; if (_state.cabinValvePosition == 0) { - // TODO: Play fire movie + // Set fire to low + boilerFireUpdate(false); // Draw fire _vm->redrawArea(305); @@ -1961,7 +2003,12 @@ void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(8098, 49152); - // TODO: Play movies + if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) { + uint16 delay = treeNextMoveDelay(_state.cabinValvePosition); + Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay); + _vm->_video->setVideoRate(_cabinGaugeMovie, rate); + } + } else { if (_state.cabinValvePosition > 0) _vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10); @@ -2067,6 +2114,11 @@ void Myst::tree_run() { // Check if alcove is accessible treeSetAlcoveAccessible(); + if (_cabinGaugeMovie != NULL_VID_HANDLE) { + Common::Rational rate = boilerComputeGaugeRate(pressure, delay); + boilerResetGauge(rate); + } + _state.treeLastMoveTime = time; } } @@ -3510,24 +3562,62 @@ void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { treeSetAlcoveAccessible(); } -void Myst::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) { - varUnusedCheck(op, var); +void Myst::o_boilerMovies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Boiler movies init", op); + + boilerFireInit(); + boilerGaugeInit(); +} + +void Myst::boilerFireInit() { + if (_vm->getCurCard() == 4098) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279, true); + _vm->_video->pauseMovie(_cabinFireMovie, true); - // Used for Card 4097 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 138); + _vm->redrawArea(305); + boilerFireUpdate(true); + } else { + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition >= 1) { + _cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244, true); + } } +} - // Used for Card 4098 (Cabin Boiler) - // TODO: Fill in logic - if (false) { - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279); - _vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 97); +void Myst::boilerFireUpdate(bool init) { + uint position = _vm->_video->getTime(_cabinFireMovie); + + if (_state.cabinPilotLightLit == 1) { + if (_state.cabinValvePosition == 0) { + if (position > (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } else { + if (position < (uint)Audio::Timestamp(0, 200, 600).msecs() || init) { + _vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600)); + _vm->_video->pauseMovie(_cabinFireMovie, false); + } + } } } +void Myst::boilerGaugeInit() { + if (_vm->getCurCard() == 4098) { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96); + } else { + _cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136); + } + + Audio::Timestamp frame; + + if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12) + frame = _vm->_video->getDuration(_cabinGaugeMovie); + else + frame = Audio::Timestamp(0, 0, 600); + + _vm->_video->drawVideoFrame(_cabinGaugeMovie, frame); +} + void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Rocket sliders init", op); @@ -3648,6 +3738,13 @@ void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { _treeAlcove = 0; } +void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { + debugC(kDebugScript, "Opcode %d: Exit boiler card", op); + + _cabinGaugeMovie = NULL_VID_HANDLE; + _cabinFireMovie = NULL_VID_HANDLE; +} + void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) { debugC(kDebugScript, "Opcode %d: Generator room exit", op); diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h index e9bff08cb4..8ecb3e4755 100644 --- a/engines/mohawk/myst_stacks/myst.h +++ b/engines/mohawk/myst_stacks/myst.h @@ -174,7 +174,7 @@ private: DECLARE_OPCODE(o_gulls2_init); DECLARE_OPCODE(o_treeCard_init); DECLARE_OPCODE(o_treeEntry_init); - DECLARE_OPCODE(opcode_218); + DECLARE_OPCODE(o_boilerMovies_init); DECLARE_OPCODE(o_rocketSliders_init); DECLARE_OPCODE(o_rocketLinkVideo_init); DECLARE_OPCODE(o_greenBook_init); @@ -183,6 +183,7 @@ private: DECLARE_OPCODE(o_bookAddSpecialPage_exit); DECLARE_OPCODE(o_treeCard_exit); DECLARE_OPCODE(o_treeEntry_exit); + DECLARE_OPCODE(o_boiler_exit); DECLARE_OPCODE(o_generatorControlRoom_exit); @@ -259,6 +260,9 @@ private: uint16 _cabinMatchState; // 60 uint32 _matchGoOutTime; // 144 + VideoHandle _cabinFireMovie; // 240 + VideoHandle _cabinGaugeMovie; // 244 + bool _boilerPressureIncreasing; bool _boilerPressureDecreasing; bool _basementPressureIncreasing; @@ -317,6 +321,12 @@ private: Common::Point towerRotationMapComputeCoords(const Common::Point ¢er, uint16 angle); void towerRotationMapDrawLine(const Common::Point ¢er, const Common::Point &end); + void boilerFireInit(); + void boilerFireUpdate(bool init); + void boilerGaugeInit(); + Common::Rational boilerComputeGaugeRate(uint16 pressure, uint32 delay); + void boilerResetGauge(const Common::Rational &rate); + void treeSetAlcoveAccessible(); uint32 treeNextMoveDelay(uint16 pressure); -- cgit v1.2.3