aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/riven_stacks/gspit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk/riven_stacks/gspit.cpp')
-rw-r--r--engines/mohawk/riven_stacks/gspit.cpp437
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