diff options
Diffstat (limited to 'engines/mohawk/riven_stacks/gspit.cpp')
-rw-r--r-- | engines/mohawk/riven_stacks/gspit.cpp | 437 |
1 files changed, 436 insertions, 1 deletions
diff --git a/engines/mohawk/riven_stacks/gspit.cpp b/engines/mohawk/riven_stacks/gspit.cpp index 8617b285eb..b70a12c635 100644 --- a/engines/mohawk/riven_stacks/gspit.cpp +++ b/engines/mohawk/riven_stacks/gspit.cpp @@ -22,7 +22,12 @@ #include "mohawk/riven_stacks/gspit.h" -#include "engines/mohawk/riven.h" +#include "mohawk/cursors.h" +#include "mohawk/riven.h" +#include "mohawk/riven_card.h" +#include "mohawk/riven_sound.h" + +#include "common/events.h" namespace Mohawk { namespace RivenStacks { @@ -30,6 +35,436 @@ namespace RivenStacks { GSpit::GSpit(MohawkEngine_Riven *vm) : DomeSpit(vm, kStackGspit) { + REGISTER_COMMAND(GSpit, xgresetpins); + REGISTER_COMMAND(GSpit, xgrotatepins); + REGISTER_COMMAND(GSpit, xgpincontrols); + REGISTER_COMMAND(GSpit, xgisland25_opencard); + REGISTER_COMMAND(GSpit, xgisland25_resetsliders); + REGISTER_COMMAND(GSpit, xgisland25_slidermd); + REGISTER_COMMAND(GSpit, xgisland25_slidermw); + REGISTER_COMMAND(GSpit, xgscpbtn); + REGISTER_COMMAND(GSpit, xgisland1490_domecheck); + REGISTER_COMMAND(GSpit, xgplateau3160_dopools); + REGISTER_COMMAND(GSpit, xgwt200_scribetime); + REGISTER_COMMAND(GSpit, xgwt900_scribe); + REGISTER_COMMAND(GSpit, xgplaywhark); + REGISTER_COMMAND(GSpit, xgrviewer); + REGISTER_COMMAND(GSpit, xgwharksnd); + REGISTER_COMMAND(GSpit, xglview_prisonoff); + REGISTER_COMMAND(GSpit, xglview_villageoff); + REGISTER_COMMAND(GSpit, xglviewer); + REGISTER_COMMAND(GSpit, xglview_prisonon); + REGISTER_COMMAND(GSpit, xglview_villageon); +} + +void GSpit::lowerPins() { + // Lower the pins + + uint32 &pinUp = _vm->_vars["gpinup"]; + + if (pinUp == 0) + return; + + uint32 &pinPos = _vm->_vars["gpinpos"]; + uint32 startTime = (pinPos - 1) * 600 + 4830; + pinUp = 0; + + // Play the down sound + _vm->_sound->playSound(13); + + uint32 &upMovie = _vm->_vars["gupmoov"]; + + // Play the video of the pins going down + VideoEntryPtr handle = _vm->_video->playMovieRiven(upMovie); + assert(handle); + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); + _vm->_video->waitUntilMovieEnds(handle); + + upMovie = 0; +} + +void GSpit::xgresetpins(uint16 argc, uint16 *argv) { + // As the function name suggests, this resets the pins + lowerPins(); + _vm->_vars["gupmoov"] = 0; +} + +void GSpit::xgrotatepins(uint16 argc, uint16 *argv) { + // Rotate the pins, if necessary + + if (_vm->_vars["gpinup"] == 0) + return; + + uint32 &pinPos = _vm->_vars["gpinpos"]; + uint32 startTime = (pinPos - 1) * 1200; + + if (pinPos == 4) + pinPos = 1; + else + pinPos++; + + // Play the rotating sound + _vm->_sound->playSound(12); + + // Play the video of the pins rotating + VideoEntryPtr handle = _vm->_video->playMovieRiven(_vm->_vars["gupmoov"]); + assert(handle); + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 1215, 600)); + _vm->_video->waitUntilMovieEnds(handle); +} + +void GSpit::xgpincontrols(uint16 argc, uint16 *argv) { + // Handle a click on a section of an island + + RivenHotspot *panel = _vm->getCard()->getHotspotByBlstId(13); + + // Get our mouse position and adjust it to the beginning of the hotspot + Common::Point mousePos = _vm->_system->getEventManager()->getMousePos(); + mousePos.x -= panel->getRect().left; + mousePos.y -= panel->getRect().top; + + // And now adjust it to which box we hit + mousePos.x /= 10; + mousePos.y /= 11; + + // Lastly, adjust it based on the rotational position + uint32 &pinPos = _vm->_vars["gpinpos"]; + switch (pinPos) { + case 1: + mousePos.x = 5 - mousePos.x; + mousePos.y = (4 - mousePos.y) * 5; + break; + case 2: + mousePos.x = (4 - mousePos.x) * 5; + mousePos.y = 1 + mousePos.y; + break; + case 3: + mousePos.x = 1 + mousePos.x; + mousePos.y = mousePos.y * 5; + break; + case 4: + mousePos.x = mousePos.x * 5; + mousePos.y = 5 - mousePos.y; + break; + default: + // (Should never happen) + error("Bad pin pos"); + } + + // Now check to see if this section of the island exists + uint32 islandIndex = _vm->_vars["glkbtns"] - 1; + uint16 imagePos = mousePos.x + mousePos.y; + + static const uint16 islandImages[5][11] = { + { 1, 2, 6, 7 }, + { 11, 16, 21, 22 }, + { 12, 13, 14, 15, 17, 18, 19, 20, 23, 24, 25 }, + { 5 }, + { 3, 4, 8, 9, 10 } + }; + + // The scripts set gimagemax to hold the max pin array length in islandPins above + uint32 imageCount = _vm->_vars["gimagemax"]; + uint32 image = 0; + for (; image < imageCount; image++) + if (islandImages[islandIndex][image] == imagePos) + break; + + // If we past it, we don't have a valid map coordinate + if (image == imageCount) + return; + + uint32 &pinUp = _vm->_vars["gpinup"]; + uint32 &curImage = _vm->_vars["gimagecurr"]; + + // Lower the pins if they are currently raised + if (pinUp == 1) { + lowerPins(); + + // If we just lowered the selected section, don't raise it up again + if (curImage == image) + return; + } + + // Raise the pins by translating the position to the movie code + static const uint16 pinMovieCodes[] = { 1, 2, 1, 2, 1, 3, 4, 3, 4, 5, 1, 1, 2, 3, 4, 2, 5, 6, 7, 8, 3, 4, 9, 10, 11 }; + + // Play the up sound + _vm->_sound->playSound(14); + + // Actually play the movie + VideoEntryPtr handle = _vm->_video->playMovieRiven(pinMovieCodes[imagePos - 1]); + assert(handle); + uint32 startTime = 9630 - pinPos * 600; + handle->setBounds(Audio::Timestamp(0, startTime, 600), Audio::Timestamp(0, startTime + 550, 600)); + _vm->_video->waitUntilMovieEnds(handle); + + // Update the relevant variables + _vm->_vars["gupmoov"] = pinMovieCodes[imagePos - 1]; + pinUp = 1; + curImage = image; +} + +void GSpit::xgisland25_opencard(uint16 argc, uint16 *argv) { + checkDomeSliders(); +} + +void GSpit::xgisland25_resetsliders(uint16 argc, uint16 *argv) { + resetDomeSliders(16, 11); +} + +void GSpit::xgisland25_slidermd(uint16 argc, uint16 *argv) { + dragDomeSlider(16, 11); +} + +void GSpit::xgisland25_slidermw(uint16 argc, uint16 *argv) { + checkSliderCursorChange(11); +} + +void GSpit::xgscpbtn(uint16 argc, uint16 *argv) { + runDomeButtonMovie(); +} + +void GSpit::xgisland1490_domecheck(uint16 argc, uint16 *argv) { + runDomeCheck(); +} + +void GSpit::xgplateau3160_dopools(uint16 argc, uint16 *argv) { + // Play the deactivation of a pool if one is active and a different one is activated + _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); + _vm->_video->playMovieBlockingRiven(_vm->_vars["glkbtns"] * 2); +} + +void GSpit::xgwt200_scribetime(uint16 argc, uint16 *argv) { + // Get the current time + _vm->_vars["gscribetime"] = _vm->_system->getMillis(); +} + +void GSpit::xgwt900_scribe(uint16 argc, uint16 *argv) { + uint32 &scribeVar = _vm->_vars["gscribe"]; + + if (scribeVar == 1 && _vm->_system->getMillis() > _vm->_vars["gscribetime"] + 40000) + scribeVar = 2; +} + +static const uint16 s_viewerTimeIntervals[] = { 0, 816, 1617, 2416, 3216, 4016, 4816, 5616, 6416, 7216, 8016, 8816 }; + +void GSpit::xgrviewer(uint16 argc, uint16 *argv) { + // This controls the viewer on the right side of the 'throne' on Garden Island + // (It shows the colors of the marbles) + + // If the light is on, turn it off + uint32 &viewerLight = _vm->_vars["grview"]; + if (viewerLight == 1) { + viewerLight = 0; + _vm->_sound->playSound(27); + _vm->refreshCard(); + + // Delay a bit before turning + _vm->_system->delayMillis(200); + } + + // Calculate how much we're moving + Common::String buttonName = _vm->getCard()->getCurHotspot()->getName(); + uint32 buttonPos = buttonName.lastChar() - '0'; + + uint32 &curPos = _vm->_vars["grviewpos"]; + uint32 newPos = curPos + buttonPos; + + // Now play the movie + VideoEntryPtr handle = _vm->_video->playMovieRiven(1); + assert(handle); + handle->setBounds(Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); + _vm->_video->waitUntilMovieEnds(handle); + + // Set the new position and let the card's scripts take over again + curPos = newPos % 6; // Clip it to 0-5 + _vm->refreshCard(); +} + +void GSpit::xgplaywhark(uint16 argc, uint16 *argv) { + // The whark response to using the lights + + // If we've gotten a visit already since we turned out the light, bail out + uint32 &wharkState = _vm->_vars["gwharktime"]; + + if (wharkState != 1) + return; + + wharkState = 0; + + // Increase the amount of times the whark has visited + uint32 &wharkVisits = _vm->_vars["gwhark"]; + wharkVisits++; + + // If we're at 5 or more, the whark will no longer visit us :( + if (wharkVisits >= 5) { + wharkVisits = 5; + return; + } + + // Activate the correct video based on the amount of times we've been visited + switch (wharkVisits) { + case 1: + _vm->_video->activateMLST(_vm->getCard()->getMovie(3)); + break; + case 2: + // One of two random videos + _vm->_video->activateMLST(_vm->getCard()->getMovie(4 + _vm->_rnd->getRandomBit())); + break; + case 3: + // One of two random videos + _vm->_video->activateMLST(_vm->getCard()->getMovie(6 + _vm->_rnd->getRandomBit())); + break; + case 4: + // Red alert! Shields online! Brace yourself for impact! + _vm->_video->activateMLST(_vm->getCard()->getMovie(8)); + break; + } + + // For whatever reason the devs felt fit, code 31 is used for all of the videos + _vm->_video->playMovieBlockingRiven(31); + _vm->refreshCard(); +} + +void GSpit::xgwharksnd(uint16 argc, uint16 *argv) { + // TODO: Random background whark videos +} + +void GSpit::xglviewer(uint16 argc, uint16 *argv) { + // This controls the viewer on the left side of the 'throne' on Garden Island + // (It shows the village from the middle of the lake) + + // Calculate how much we're moving + Common::String buttonName = _vm->getCard()->getCurHotspot()->getName(); + uint32 buttonPos = buttonName.lastChar() - '0'; + + uint32 &curPos = _vm->_vars["glviewpos"]; + uint32 newPos = curPos + buttonPos; + + // Now play the movie + VideoEntryPtr handle = _vm->_video->playMovieRiven(1); + assert(handle); + handle->setBounds(Audio::Timestamp(0, s_viewerTimeIntervals[curPos], 600), Audio::Timestamp(0, s_viewerTimeIntervals[newPos], 600)); + _vm->_video->waitUntilMovieEnds(handle); + + // Set the new position to the variable + curPos = newPos % 6; // Clip it to 0-5 + + // And update the screen with the new image + _vm->getCard()->drawPicture(curPos + 2); +} + +void GSpit::xglview_villageon(uint16 argc, uint16 *argv) { + // Turn on the left viewer to 'village mode' + _vm->_vars["glview"] = 2; + _vm->getCard()->drawPicture(_vm->_vars["glviewpos"] + 2); +} + +void GSpit::xglview_villageoff(uint16 argc, uint16 *argv) { + // Turn off the left viewer when in 'village mode' (why is this external?) + _vm->_vars["glview"] = 0; + _vm->getCard()->drawPicture(1); +} + +static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) { + uint32 &cathState = vm->_vars["gcathstate"]; + uint16 movie; + + // Choose a new movie + if (cathState == 1) { + static const int movieList[] = { 9, 10, 19, 19, 21, 21 }; + movie = movieList[vm->_rnd->getRandomNumber(5)]; + } else if (cathState == 2) { + static const int movieList[] = { 18, 20, 22 }; + movie = movieList[vm->_rnd->getRandomNumber(2)]; + } else { + static const int movieList[] = { 11, 11, 12, 17, 17, 17, 17, 23 }; + movie = movieList[vm->_rnd->getRandomNumber(7)]; + } + + // Update Catherine's state + if (movie == 10 || movie == 17 || movie == 18 || movie == 20) + cathState = 1; + else if (movie == 19 || movie == 21 || movie == 23) + cathState = 2; + else + cathState = 3; + + // Begin playing the new movie + vm->_video->activateMLST(vm->getCard()->getMovie(movie)); + VideoEntryPtr video = vm->_video->playMovieRiven(30); + + // Reset the timer + vm->installTimer(&catherineViewerIdleTimer, video->getDuration().msecs() + vm->_rnd->getRandomNumber(60) * 1000); +} + +void GSpit::xglview_prisonon(uint16 argc, uint16 *argv) { + // Activate random background Catherine videos + + // Turn on the left viewer to 'prison mode' + _vm->_vars["glview"] = 1; + + // Get basic starting states + uint16 cathMovie = _vm->_rnd->getRandomNumberRng(8, 23); + uint16 turnOnMovie = 4; + uint32 &cathState = _vm->_vars["gcathstate"]; + + // Adjust the turn on movie + if (cathMovie == 14) + turnOnMovie = 6; + else if (cathMovie == 15) + turnOnMovie = 7; + + // Adjust Catherine's state + if (cathMovie == 9 || cathMovie == 11 || cathMovie == 12 || cathMovie == 22) + cathState = 3; + else if (cathMovie == 19 || cathMovie == 21 || cathMovie == 23 || cathMovie == 14) + cathState = 2; + else + cathState = 1; + + // Turn on the viewer + _vm->_cursor->hideCursor(); + _vm->_video->playMovieBlockingRiven(turnOnMovie); + _vm->_cursor->showCursor(); + + uint32 timeUntilNextMovie; + + // Begin playing a movie immediately if Catherine is already in the viewer + if (cathMovie == 8 || (cathMovie >= 13 && cathMovie <= 16)) { + _vm->_video->activateMLST(_vm->getCard()->getMovie(cathMovie)); + VideoEntryPtr video = _vm->_video->playMovieRiven(30); + + timeUntilNextMovie = video->getDuration().msecs() + _vm->_rnd->getRandomNumber(60) * 1000; + } else { + // Otherwise, just redraw the imager + timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000; + _vm->getCard()->drawPicture(8); + } + + // Create the timer for the next video + _vm->installTimer(&catherineViewerIdleTimer, timeUntilNextMovie); +} + +void GSpit::xglview_prisonoff(uint16 argc, uint16 *argv) { + // Deactivate random background Catherine videos + + // Update the viewer state (now off) + _vm->_vars["glview"] = 0; + + // Remove the timer we set in xglview_prisonon() + _vm->removeTimer(); + + // Play the 'turn off' movie after stopping any videos still playing + _vm->_video->stopVideos(); + _vm->_cursor->hideCursor(); + _vm->_video->playMovieBlockingRiven(5); + _vm->_cursor->showCursor(); + + // Redraw the viewer + _vm->getCard()->drawPicture(1); } } // End of namespace RivenStacks |